2016-03-19 137 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回覆)。

而且,當然,您還需要小心處理因寫入管道而發生的所有事情,即在消耗整個管道數據之前正常處理讀取器關閉,導致管道損壞等...

相關問題