下面的脚本 1 是 bash,位于https://example.com/cgi-bin/test
. 获取时它会产生输出“Under construction”。它回显Status
和Content-type
标题,以及一些 HTML。如果我改为尝试回显整个 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
有两种风格: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
.
在这种情况下,PHP 和 CGI 是两种不同的东西。
CGI 是程序(在本例中为 bash 脚本)和 Web 服务器之间的接口。此接口指定 Web 服务器和程序之间的通信。
此标准要求程序在实际内容之前返回所有标头,包括状态标头。在 HTTP 中,标头和正文由一行分隔 - 因此您拥有的格式
在标头之后,您可以自由地包含完整的 HTML 文档 - 或与您发送的标头相匹配的任何其他类型的数据。
PHP 为您做了一些假设,除非您覆盖它,否则它会自动设置内容类型、状态代码等。
在 CGI 中,您需要发送 Content-Type。PHP 为您生成它。(通过浏览器检查输出,即使您在代码中看不到它,您也会看到它。
我有一个用 C 编写的 CGI,您确实需要内容类型;
以我为例;
printf("内容类型: text/html;charset=us-ascii\n\n");
如果您需要更改 php 中的标头,则必须在脚本开头调用标头。
IE;
header('Content-Type: application/json');
如果通过 Apache 通过 CGI 调用脚本,则需要包含有效的 CGI 标头响应,而不是 HTTP 响应。我认为本质上(详见下文)您需要从文件中删除“Status: 200 OK”,它可能会起作用。
Apache 自己有一篇很好的文章 ( https://httpd.apache.org/docs/2.2/howto/cgi.html ),它向您展示了获得有效响应的最低要求。
客户端收到的示例标头可能如下所示:
但是你的CGI,只需要从“Content-Type: text/html; charset=UTF-8”往下发送。
可以在这里找到一篇很好的文章来解释标题: https ://code.tutsplus.com/tutorials/http-headers-for-dummies--net-8039
关于通过 Apache 提供的 PHP 文件,有多个通信层:
探索标头的另一个好方法是使用 Firefox / Chrome 开发者工具(在 Firefox 中按 F12 打开它们)。打开开发人员工具后转到网络选项卡并重新加载页面(在 Windows/Linux 上为 Ctrl + R)。有一个“原始”选项,您可以在其中查看发送和接收的确切数据。
最后,如果您找到一个网站,或者您的 CGI 是通过 http 而不是 https 提供服务的,您可以安装 Wireshark ( https://www.wireshark.org ) 并轻松监控流量对话以了解您使用的内容之间的区别。正在发送被误解的内容以及 Apache 提供的普通静态 html 页面对话看起来像什么。
PS(2022 年)如果您确实在运行 Apache 2.2: