以下のスクリプト 1 は bash で、 にありますhttps://example.com/cgi-bin/test
。取得すると、「Under construction」という出力が生成されます。ヘッダーといくつかの HTML がエコーされますStatus
。Content-type
代わりに HTML ドキュメント全体をエコーしようとすると、Apache は無効なヘッダーについてエラーを出します。
以下のスクリプト 2 は php で、 にありますhttps://example.com/cgi-bin/test2.php
。bash スクリプトとは異なり、これは HTML ドキュメントを返します。
スクリプト 2 は HTML ドキュメント全体を送信できるのに、スクリプト 1 はできないのはなぜでしょうか?
スクリプト 1
#!/bin/bash
cat <<'EOF'
Status: 200 OK
Content-type: text/html
<p>Under construction.</p>
EOF
スクリプト 2
<?php
print <<<EOF
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
...etc
</head>
<body>
...etc
</body>
</html>
EOF;
?>
編集
php
2つのバージョンがあります: CLIバージョンとCGIバージョンです。コマンドラインからスクリプト2を実行するとphp test2.php
、のみによって生成される出力は、php
まさにあなたが見ているとおりです。HTML ドキュメントphp-cgi
は CGI バージョンです (Ubuntu/Deb に としてインストールしますapt install php-cgi
)。Apache は (事実上) CGI バージョンを実行します (実際には少し異なる方法で実行されますが、結果は同じです)。
$ php-cgi test2.php
Content-type: text/html; charset=UTF-8
<!DOCTYPE html>
...rest of doc
CGIスクリプトは少なくともContent-type
Apacheに返す必要があります(ただし、を含むより多くのヘッダーを返すことができますStatus
)。したがって、答えは次のようになります。両方スクリプト 1 は を明示的に返すためContent-type
、スクリプトは機能しますが、 の内部的な CGI バージョンはphp
同じことを行います。
bash スクリプトは、 も返す限り、HTML ドキュメント全体を返すことができますContent-type
。
答え1
CGI では、Content-Type を送信する必要があります。PHP がそれを生成します。(ブラウザ経由で出力を確認すると、コード内に表示されていなくても表示されます。)
私は C で作成した CGI を持っていますが、コンテンツ タイプが本当に必要です。
たとえば私の場合、
printf("コンテンツタイプ: text/html;charset=us-ascii\n\n");
PHP でヘッダーを変更する必要がある場合は、スクリプトの先頭で header を呼び出す必要があります。
すなわち;
ヘッダー('Content-Type: application/json');
答え2
この文脈では、PHP と CGI は異なるものです。
CGI は、プログラム (この場合は bash スクリプト) と Web サーバー間のインターフェイスです。このインターフェイスは、Web サーバーとプログラム間の通信を指定します。
この標準では、プログラムが全て実際のコンテンツの前に、ステータスヘッダーを含むヘッダーが配置されます。HTTPでは、ヘッダーと本文は1行で区切られます。そのため、
Header
Header
Content
ヘッダーの後には、完全な HTML ドキュメント、または送信するヘッダーに一致するその他の種類のデータを自由に含めることができます。
PHP はいくつかの仮定を立て、それを上書きしない限り、コンテンツ タイプ、ステータス コードなどを自動的に設定します。
答え3
Apache を通じて CGI 経由でスクリプトを呼び出す場合は、HTTP 応答ではなく、有効な CGI ヘッダー応答を含める必要があります。基本的には (詳細は下記)、ファイルから「Status: 200 OK」を削除すれば、機能すると思います。
Apache自身による良い記事があります(参考:) は、有効な応答を達成するための最小限のものを示します。
クライアントが受信するヘッダーの例は次のようになります。
HTTP/1.x 200 OK
Transfer-Encoding: chunked
Date: Tue, 06 Dec 2021 19:58:00 GMT
Server: My_Bash_Script
Connection: close
X-Powered-By: My_Bash_Script
Pragma: public
Expires: Tue, 06 Dec 2021 20:58:00 GMT
Cache-Control: max-age=3600, public
Last-Modified: Tue, 06 Dec 2021 20:58:00 GMT
Content-Encoding: gzip
Vary: Accept-Encoding, Cookie, User-Agent
Content-Type: text/html; charset=UTF-8
<!DOCTYPE html>
<head><title>Under construction</title>
<body><p>Under construction.</p></body>
</html>
ただし、CGI では、「Content-Type: text/html; charset=UTF-8」から下のみを送信する必要があります。
ヘッダーについて説明している非常に良い記事がここにあります: https://code.tutsplus.com/tutorials/http-headers-for-dummies--net-8039
Apache 経由で提供される PHP ファイルに関しては、通信にはいくつかの層があります。
- リクエストは TCP ポートで Apache に対して行われます。HTTP 経由の場合は、リクエスト ヘッダーが含まれます。
- Apache はあらゆるルール (例: mod_rewrite) を実行し、必要な SSL 接続/ハンドシェイクを処理します。
- 次に、Apache はファイル拡張子を PHP として検出し、PHP インタープリターを介して PHP スクリプトを呼び出します。
- PHP コードが解釈され、静的な文字列に変換され (うまくいけば :-)、Apache に返され、HTML コードが含まれます。
- 次に、Apache は他の送信処理とともに、ヘッダー情報を HTML ページに追加します。
- これはシリアル化され、TCP 接続を介してクライアントにパイプされます。
ヘッダーを調べるもう 1 つの良い方法は、Firefox / Chrome 開発者ツールを使用することです (Firefox で F12 キーを押すと開きます)。開発者ツールが開いたら、ネットワーク タブに移動してページを再読み込みします (Windows/Linux では Ctrl + R)。送受信された正確なデータを表示できる「Raw」オプションがあります。
最後に、ウェブサイトを見つけた場合、またはCGIがhttpsではなくhttpで提供されている場合、Wireshark(https://www.wireshark.org) を使用すると、トラフィック会話を簡単に監視して、誤解されている送信内容と、Apache によって提供される通常の静的 HTML ページ会話の違いを把握できます。
PS (2022 年) 実際に Apache 2.2 を実行している場合: