AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 1117419
Accepted
QF0
QF0
Asked: 2022-12-07 11:06:54 +0800 CST2022-12-07 11:06:54 +0800 CST 2022-12-07 11:06:54 +0800 CST

CGI 脚本:什么时候可以返回文档而不是 HTTP 响应?

  • 772

下面的脚本 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.

apache-2.2
  • 3 3 个回答
  • 40 Views

3 个回答

  • Voted
  1. vidarlo
    2022-12-07T12:05:35+08:002022-12-07T12:05:35+08:00

    在这种情况下,PHP 和 CGI​​ 是两种不同的东西。

    CGI 是程序(在本例中为 bash 脚本)和 Web 服务器之间的接口。此接口指定 Web 服务器和程序之间的通信。

    此标准要求程序在实际内容之前返回所有标头,包括状态标头。在 HTTP 中,标头和正文由一行分隔 - 因此您拥有的格式

    Header
    Header
    
    Content
    

    在标头之后,您可以自由地包含完整的 HTML 文档 - 或与您发送的标头相匹配的任何其他类型的数据。

    PHP 为您做了一些假设,除非您覆盖它,否则它会自动设置内容类型、状态代码等。

    • 0
  2. Best Answer
    yagmoth555
    2022-12-07T12:06:02+08:002022-12-07T12:06:02+08:00

    在 CGI 中,您需要发送 Content-Type。PHP 为您生成它。(通过浏览器检查输出,即使您在代码中看不到它,您也会看到它。

    我有一个用 C 编写的 CGI,您确实需要内容类型;

    以我为例;

    printf("内容类型: text/html;charset=us-ascii\n\n");

    如果您需要更改 php 中的标头,则必须在脚本开头调用标头。

    IE;

    header('Content-Type: application/json');

    • 0
  3. Elstone IT Services Limited
    2022-12-07T12:20:48+08:002022-12-07T12:20:48+08:00

    如果通过 Apache 通过 CGI 调用脚本,则需要包含有效的 CGI 标头响应,而不是 HTTP 响应。我认为本质上(详见下文)您需要从文件中删除“Status: 200 OK”,它可能会起作用。

    Apache 自己有一篇很好的文章 ( https://httpd.apache.org/docs/2.2/howto/cgi.html ),它向您展示了获得有效响应的最低要求。

    客户端收到的示例标头可能如下所示:

    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 文件,有多个通信层:

    • Apache 在 TCP 端口上发出请求。如果通过 HTTP,这包括请求标头。
    • Apache 运行任何规则(例如 mod_rewrite)并处理任何所需的 SSL 连接/握手。
    • 然后 Apache 将文件扩展名检测为 PHP,并通过 PHP 解释器调用 PHP 脚本。
    • PHP 代码被解释,并变成一个静态字符串(希望 :-) 返回给 Apache 并包含 HTML 代码。
    • 然后,Apache 将标头信息与任何其他出站处理一起添加到 HTML 页面。
    • 这被序列化并通过 TCP 连接传输回客户端。

    探索标头的另一个好方法是使用 Firefox / Chrome 开发者工具(在 Firefox 中按 F12 打开它们)。打开开发人员工具后转到网络选项卡并重新加载页面(在 Windows/Linux 上为 Ctrl + R)。有一个“原始”选项,您可以在其中查看发送和接收的确切数据。

    最后,如果您找到一个网站,或者您的 CGI 是通过 http 而不是 https 提供服务的,您可以安装 Wireshark ( https://www.wireshark.org ) 并轻松监控流量对话以了解您使用的内容之间的区别。正在发送被误解的内容以及 Apache 提供的普通静态 html 页面对话看起来像什么。

    PS(2022 年)如果您确实在运行 Apache 2.2:

    • 您可能会错过 Apache2.4 中的其他功能,这些功能可能会帮助您更快地到达目的地:https ://httpd.apache.org/docs/2.4/new_features_2_4.html
    • 请注意,Apache 2.2 已停产(自 2017 年起),并且包含许多漏洞:https ://httpd.apache.org/security/vulnerabilities_22.html
    • 0

相关问题

  • Apache Django Mod_Wsgi - 自动重新加载应用程序

  • Apache:对多个虚拟主机使用相同的目录指令

  • Apache 上的子域不工作 - 找不到服务器

  • PHP 作为 CGI 还是 Apache 模块?

  • 避免将某些丢失的文件记录到 Apache2 错误日志中

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve