2016-03-19 169 views
1

我在写一个简单的http服务器,并且我想使用php-cgi来处理POST请求。我写的handlePOST如下:Http服务器使用C++将数据发布到php-cgi

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-cgiSTDIN得到POST数据。我把POST数据(变种pdata)放入cin.rdbuf。但是,执行execve时,程序无法从STDIN获取数据。但如果我使用控制台输入字符串,程序可以正常运行。

回答

0

当你的自定义http服务器读取套接字时,它总是设法读取HTTP消息的标题部分中的字节数,这是非常不可能的。所以当它执行外部进程时,包含POST数据的消息的正文部分现在正等待在其标准输入中读取。

很可能,您正在使用C++ I/O库或者甚至是库来读取标准输入或套接字。当然,这意味着iostreamsstdio采用的内置输入缓冲已经设法吞下来自HTTP消息正文后面的大量POST数据,该消息紧跟在其头部之后。它现在正在等待或你,继续阅读你的std::cin,stdin;或者你的代码实际上在阅读什么。

因此,遗憾的是,当您执行外部进程时,它会惊奇地发现它所期望的数据已被其标准输入全部或部分使用。相反,它坐在这里,在你的过程中,等待你继续阅读你的std::cin,stdin,或其他任何东西。

换句话说,为了这个工作,你不能只是执行一个外部的过程,并且洗掉整个混乱的手。您需要为外部进程的标准输入设置一个管道,并且您有责任仔细阅读HTTP消息的主体,这就形成了POST数据,就像您刚刚完成读取其标头一样,然后将其倒入管道中。

这意味着解析Content-Length标题,确切知道正文中有多少字节,并正确读取(因为您不会获取EOF并依赖它,因为套接字将保留打开预期的HTTP回复)。

而且,当然,您还需要小心处理因写入管道而发生的所有事情,即在消耗整个管道数据之前正常处理读取器关闭,导致管道损坏等...

相关问题