如何在C++上使用WinHTTP进行HTTPS调用(POST请求)
How to make HTTPS calls (POST requests) using WinHTTP on C++?
我正在C++上编写程序,以便使用WinHTTP对Java Servlet进行调用(POST请求)。当我通过HTTP请求POST时,一切正常,当我通过HTTPS请求时就会出现问题。它向服务器发送空请求,但切断请求主体(但它有内容)
int sendPostRequest(char *pszPostData, LPCTSTR servletUrl, char* resultBuffer, ofstream &outputFile) {
outputFile << "====================================== SENDING REEQUEST ======================================" << endl;
HINTERNET hSession = WinHttpOpen(
userAgent,
WINHTTP_ACCESS_TYPE_NO_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS,
0);
if (!hSession)
{
_tprintf(_TEXT("Failed to open WinHTTP session: %ldn"), GetLastError());
outputFile << "Failed to open WinHTTP session: %ldn" << GetLastError() << endl;
return NULL;
}
else {
_tprintf(_TEXT("Oppening WinHTTP session successful: %ldn"), GetLastError());
outputFile << "Oppening WinHTTP session successful: %ldn" << GetLastError() << endl;
}
HINTERNET hConnect = WinHttpConnect(
hSession,
serverIP,
serverPort,
0);
if (!hConnect)
{
_tprintf(_TEXT("Failed to connect to server: %ldn"), GetLastError());
outputFile << "Failed to connect to server: %ldn" << GetLastError() << endl;
WinHttpCloseHandle(hSession);
return NULL;
}
else {
_tprintf(_TEXT("Connection to server successful: %ldn"), GetLastError());
outputFile << "Connection to server successful: %ldn" << GetLastError() << endl;
}
_tprintf(_TEXT("Post data : %ldn"), pszPostData);
outputFile << "Post data : %ldn" << pszPostData << endl;
DWORD dwDataLen = strlen(pszPostData);
HINTERNET hRequest = WinHttpOpenRequest(
hConnect,
_TEXT("POST"),
servletUrl,
NULL,
WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
WINHTTP_FLAG_REFRESH);
if (!hRequest)
{
_tprintf(_TEXT("Failed to open request: %ldn"), GetLastError());
outputFile << "Failed to open request: %ldn" << GetLastError() << endl;
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return -1;
}
else {
_tprintf(_TEXT("Opening request successful: %ldn"), GetLastError());
outputFile << "Opening request successful: %ldn" << GetLastError() << endl;
}
DWORD dwReqOpts = 0;
DWORD dwSize = sizeof(DWORD);
WinHttpSetOption(
hRequest,
WINHTTP_OPTION_SECURITY_FLAGS,
&dwReqOpts,
sizeof(DWORD));
BOOL done = false;
BOOL rc = WinHttpSendRequest(
hRequest,
contentTypeHeader,
-1,
(LPVOID)pszPostData,
dwDataLen,
dwDataLen,
NULL);
if (rc) {
rc = WinHttpReceiveResponse(hRequest, NULL);
_tprintf(_TEXT("Sending request successful: %ldn"), GetLastError());
outputFile << "Sending request successful: %ldn" << GetLastError() << endl;
}
else
{
_tprintf(_TEXT("Send request failed: %ldn"), GetLastError());
outputFile << "Send request failed: %ldn" << GetLastError() << endl;
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return -1;
}
// Get the status from the server
DWORD dwCode = 0;
if (rc)
{
rc = WinHttpQueryHeaders(
hRequest,
WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
NULL,
&dwCode,
&dwSize,
NULL);
}
if (dwCode != HTTP_STATUS_OK)
{
_tprintf(_TEXT("HTTP Request failed: %ldn"), dwCode);
outputFile << "HTTP Request failed: %ldn" << dwCode << endl;
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
}
else
{
_tprintf(_TEXT("HTTP Request is ok: %ldn"), dwCode);
outputFile << "HTTP Request is ok : %ldn" << dwCode << endl;
// Keep reading from the remote server until there's nothing left to read
DWORD dwBytesToBeRead = 0, dwBytesRead = 0;
//char szBuffer[8192] = { 0 };
//strcpy(resultBuffer, "");
do
{
if (!WinHttpQueryDataAvailable(hRequest, &dwBytesToBeRead))
{
_tprintf(_TEXT("No data available from server? %ld"), GetLastError());
outputFile << "No data available from server? %ld" << GetLastError() << endl;
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return -1;
}
if (!WinHttpReadData(
hRequest,
//szBuffer,
resultBuffer,
//sizeof(szBuffer),
RESULT_BUFFER_SIZE,
&dwBytesRead))
{
_tprintf(_TEXT("Failed to read data from server: %ld"), GetLastError());
outputFile << "Failed to read data from server: %ld" << GetLastError() << endl;
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return -1;
}
if (dwBytesRead > 0)
{
//szBuffer[dwBytesRead] = 0;
resultBuffer[dwBytesRead] = 0; // NULL-terminated returned buffer
}
} while (dwBytesRead > 0);
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return 0;
}
return -1;
}
其中pszPostData
-请求体的内容,servletUrl
-Servlet(端点)的url,resultBuffer
-调用结果将写入该缓冲区,outputFile
-日志文件。
那么,如何在不剪切请求正文的情况下进行HTTPS调用呢?
关于WinHttpSendRequest方法,在第二个参数插入:L"content-type:application/x-www-form-urlencoded"
和第三个参数-1
,根据w3。
它应该可以进行此更正。
另外,检查你的.php文件的编码,有一次给我带来了麻烦。
我今天遇到了这个问题,因为我面临着一个非常类似的问题。在WinHttpConnect()
中,我将pswzServerName
作为"example.com"发送。问题是,在Apache中,我强制将domain.com
重定向到www.domain.com
,并将http
重定向到https
。由于我在WinHttpConnect()
中指定了example.com
,此重定向导致未发送POST数据、内容长度标头错误和内容类型标头错误。
有两种解决方案,最后一种是最佳选择:
Removing my htaccess non-www to www and http to https redirect
OR
just changing `pswzServerName` to 'www.example.com' (including the www.) in WinHttpConnect()
花了很长时间试图弄清楚为什么winhttp不起作用,因为这很容易被忽视,所以希望它能帮助其他可能处境相同的人。
即使这是一个老问题,这也可能有所帮助:
将WINHTTP_FLAG_SECURE
添加到WinHttpOpenRequest
中,它应该可以工作。
...
HINTERNET hRequest = WinHttpOpenRequest(
hConnect,
_TEXT("POST"),
servletUrl,
NULL,
WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
WINHTTP_FLAG_REFRESH+WINHTTP_FLAG_SECURE); /// Here
...
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 函数调用中参数的顺序重要吗
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在c++类上调用void函数
- 为什么 std::unique 不调用 std::sort?
- 调用专用模板时出错"no matching function for call to [...]"
- 选择要调用的构造函数
- C++为什么尽管我调用了void函数,它却不起作用
- 构造函数正在调用一个使用当前类类型的函数
- 变量没有改变?通过向量的函数调用
- 没有为自己的结构调用列表推回方法
- 调用'begin(int [n])'没有匹配函数
- 什么时候调用析构函数
- 如何用参数值调用函数(仅在运行时已知)
- std::cout.imbue()多重调用
- 如何在C++上使用WinHTTP进行HTTPS调用(POST请求)