header()函数的工作原理是什么?

7

背景:
我需要在浏览器中运行PHP脚本,但是我不想安装服务器并承受在计算机上运行服务器以及包括防火墙等所有相关内容的开销。

因此,我编写了自己的服务器。它是一个简单的PHP脚本,监听我的LAN IP的80端口的连接,然后我只需在浏览器中加载该IP即可工作。它接收HTTP请求并使用exec启动第二个PHP脚本-这样我就可以轻松地对其进行更改,而无需重新启动服务器脚本。这个第二个PHP脚本解析请求,并最终include实际被调用的脚本。从那里获取输出,并使用适当的头(我可以更改)将响应发送回浏览器。

是啊,这很混乱,但它可以正常工作。它做到了我需要它做的事情。

现在来谈问题:
我不能使用header()。它似乎没有影响通过套接字连接发送回浏览器的内容。我已经制作了一个setheader()函数,并将头存储在数组中以便预置到响应中。

我想知道header()函数在内部是如何工作的,以便我可能能够使用该函数而不是我的“黑客”功能。


1
从手册中:只有在使用支持头文件的SAPI时,头文件才能被访问和输出。 - Gordon
您能否打印您的服务器脚本发送给浏览器的示例响应,其中包含头部和正文? - Igor Nikolaev
7个回答

2

header()函数被CLI SAPI完全忽略。但对于Apache和CGI SAPI有一定影响。

简单来说,CLI SAPI在sapi_*_header_*函数中不实现任何逻辑。举个例子,在php_cli.c文件中:

static int sapi_cli_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) /* {{{ */
{
    /* We do nothing here, this function is needed to prevent that the fallback
    * header handling is called. */
    return SAPI_HEADER_SENT_SUCCESSFULLY;
}
/* }}} */

所有这些函数基本上都会返回NULL0或一个虚假的成功消息。
对于CGI SAPI,在cgi_main.c中:
static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
{
    char buf[SAPI_CGI_MAX_HEADER_LENGTH];
    sapi_header_struct *h;
    zend_llist_position pos;
    zend_bool ignore_status = 0;
    int response_status = SG(sapi_headers).http_response_code;

    // Lots of other code...
}

你可以通过使用php-cgi二进制文件和一些数组操作轻松地使此工作生效: server.php
$script_to_run = 'script.php';
exec('php-cgi '.escapeshellarg($script_to_run), $output);
$separator = array_search("", $output);

$headers = array_slice($output, 0, $separator);
$body = implode("\r\n", array_slice($output, $separator+1));

print_r($headers);
print $body;

script.php

header('Content-Type: text/plain');
echo 'Hello, World!';

输出:

Array
(
    [0] => X-Powered-By: PHP/5.3.8
    [1] => Content-Type: text/plain
)
Hello, World!

1

header() 函数的工作方式与您的实现完全相同:它只是在响应中发送纯文本标头,而在页面内容之前(这就是为什么如果已经向客户端发送了任何内容,它将抛出错误)。所以,我认为您正在正确地执行它。无论如何,您的实现存在一些问题。我认为安装 Web 服务器会更容易一些。


0

一个通常的HTTP响应看起来像这样:

HTTP/1.1 200 OK
Date: Thu, 10 Nov 2011 15:35:27 GMT
Server: Apache
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=None

<!DOCTYPE html>
<html>
....

PHP函数header()负责将头部信息放入响应的第一部分。实际的HTML输出可以使用print等方式。

如果是PHP脚本在Apache上运行,那么该脚本负责将您的头部信息放入其响应中。header()仅在输出发送到标准输出(stdout)而不是自定义写入套接字(socket)时才起作用,以便在PHP-CGI脚本结束后,适当的头部可以预先添加到输出中。


0

你是否使用正确的CGI风格调用?否则,大多数与HTTP相关的函数在PHP中将无法工作,而且CGI并不像从Apache或IIS进行库调用那样好。

为什么不使用EasyPHP或类似的东西呢?

附注:您所说的“解析请求”是什么意思?


0

实际发送头由 PHP 的 SAPI(服务器 API)层执行。示例 SAPI 包括 Apache 的 mod_php 和当您调用 exec 时将运行的 PHP CLI 版本。在 CLI SAPI 的情况下,发送头是无操作的,因为通常没有意义为在命令行上运行的脚本显示 HTTP 头。

尝试使用 php-cgi 作为二进制文件而不是 PHP。CGI SAPI 应该输出正确的头。


0

由 SAPI 模块(调用 PHP 脚本的代码)决定如何处理标头。CLI SAPI(您可能正在使用的)只会忽略脚本设置的任何标头。CGI SAPI(可以使用 php-cgi 命令)默认输出它们,但支持命令行界面来抑制它们。理想情况下,您应该编写自己的 SAPI 模块,以正确地与您的 Web 服务器进行交互。


0

我知道我听起来很蠢,但为什么不只是安装wamp或lamp呢?这是一种真正的“解压缩、运行和完成”的解决方案,可以真正节省您的麻烦。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接