我正在向 IIS7 服务器上的 php 脚本发送带有 POST 数据的 WinHttp 请求,但服务器未收到 POST 正文。 如果我使用 GET 或带有 NULL 正文的 POST 通过 WinHttp 发送,或者使用带有正文的 POST 通过 HTML 表单发送,则一切都会按预期进行。
下面是一些简单的代码,显示了带正文和不带正文的 WinHttp POST 调用之间的区别:
没有身体:
HINTERNET hSession = WinHttpOpen(L"WinHTTP/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);//WINHTTP_FLAG_ASYNC);
HINTERNET mConnection = WinHttpConnect(hSession, L"127.0.0.1", 80, 0);
HINTERNET hRequest = WinHttpOpenRequest(mConnection, L"POST", L"/test.php", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
void* bodyData = NULL;
DWORD bodyLength = 0;
bResult = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, bodyData, bodyLength, bodyLength, 0);
有本体:
HINTERNET hSession = WinHttpOpen(L"WinHTTP/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);//WINHTTP_FLAG_ASYNC);
HINTERNET mConnection = WinHttpConnect(hSession, L"127.0.0.1", 80, 0);
HINTERNET hRequest = WinHttpOpenRequest(mConnection, L"POST", L"/test.php", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
char* pBodyStr = "a=1&b=2";
void* bodyData = (void*) pBodyStr;
DWORD bodyLength = strlen(pBodyStr);
bResult = WinHttpSendRequest(hRequest, L"content-type:application/x-www-form-urlencoded", -1, bodyData, bodyLength, bodyLength, 0);
所以唯一的区别是主体参数和内容类型标头。 真正奇怪的是,这可能 20 次中有 1 次有效,但通常服务器不会收到正文,并且会超时。 这里有什么明显错误吗?
对于仍然遇到此问题的其他人,请尝试使用 PUT 而不是 POST。
在我的例子中,WinHttp 客户端是在 VFP 中,但结果是相同的。 通过浏览器发送的 POST 工作正常,但是当我从 WinHttp 对象发送时,请求正文显示为空。
PUT,然而,工作正常......除了
// Simply using
//
// file_get_contents('php://input')
//
// does not work with the request sent by WinHttp.WinHttpRequest.
$fp = fopen('php://input', 'rb');
stream_filter_append($fp, 'dechunk', STREAM_FILTER_READ);
$report_contents = stream_get_contents($fp);
再次强调,这在基于浏览器的请求中不是问题。
此外,POST 对于 ASP.NET 客户端来说工作得很好。 仅当尝试在 PHP/Linux 页面上读取它时才会出现此问题。
我发现,当
bodyData
指向的数据并不总是保持活动状态足够长的时间以使 WinHTTP 完成数据发送时,就会发生此行为。这导致服务器有时可以很好地接收数据,而有时 POST 正文将为空。