我正在编写一个简单的 http 服务器,我想使用 php-cgi
来处理 POST
请求。我将 handlePOST
写成如下:
void KServer::handlePOST(int sockfd, string file, string pdata){
char* argvs[MAX_PARAMS];
argvs[0] = const_cast<char*>(CGI_PATH);
argvs[1] = const_cast<char*>(file.c_str());
stringstream ss;
ss<<pdata.length();
string clen, sname;
ss>>clen;
clen = "CONTENT_LENGTH=" + clen;
sname = "SCRIPT_FILENAME="+file;
char* env[] = {
"REQUEST_METHOD=POST",
"REDIRECT_STATUS=CGI",
const_cast<char*>(clen.c_str()),
const_cast<char*>(sname.c_str()),
"CONTENT_TYPE=application/x-www-form-urlencoded",
0
};
istringstream stream(pdata);
cin.rdbuf(stream.rdbuf());
execve(argvs[0], argvs, env);
...
我知道 php-cgi
从 STDIN
获取 POST
数据。然后我将 POST
数据 (var. pdata
) 放入 cin.rdbuf
。但是,程序在执行 execve 时无法从 STDIN
获取数据。但是如果我使用控制台输入字符串,程序可以正确运行。
最佳答案
当您的自定义 HTTP 服务器读取套接字时,它不太可能总是设法在到达这一点之前准确读取 HTTP 消息 header 部分中的字节数;因此,当它执行外部进程时,包含 POST 数据的消息正文部分现在正等待在其标准输入上读取。
很有可能,您正在使用 C++ I/O 库,甚至可能是 C stdio
库来读取标准输入或套接字。当然,这意味着 iostreams
或 stdio
所采用的内置输入缓冲已经设法吞下了很大一部分 POST
来自 HTTP
消息正文的数据,紧跟在其 header 之后。它现在在等着你,继续阅读你的 std::cin
,stdin
;或者您的代码实际读取的任何内容。
因此,可悲的是,当您执行外部进程时,它会沮丧地发现它所期望的 POST
数据已经全部或部分被消耗掉,它的标准输入。相反,它就坐在这里,在您的进程中,等待您继续阅读您的 std::cin
、stdin
或其他内容。
换句话说,要让它发挥作用,您不能只执行一个外部进程,然后就不用管整个烂摊子了。您将需要设置一个到外部进程标准输入的管道,您有责任继续仔细阅读构成 POST
数据的 HTTP 消息正文,就像您已经刚刚读完它的头,然后将它转储到管道中。
这意味着解析 Content-Length header ,以准确了解正文中有多少字节,并准确读取(因为您不会获得 EOF,并依赖它,因为套接字将保持打开状态用于您预期的 HTTP 回复)。
当然,您还需要仔细处理由于写入管道而发生的所有事情,即在消耗全部管道数据之前优雅地处理读取器关闭,从而导致管道损坏,等等……
关于php - Http 服务器使用 C++ 将数据发布到 php-cgi,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36102026/