C++WinHttp获取响应标头和正文

C++ WinHttp get response header and body

本文关键字:正文 获取 响应 C++WinHttp      更新时间:2023-10-16

我目前正在尝试编写一个类,以使发送简单请求更容易。
最后,我希望它能像这样使用:

int _tmain(int argc, _TCHAR* argv[])
{
    HttpRequest Request(L"Example UserAgent/1.0",L"",L"");
    Request.SendRequest(L"google.com",L"GET",NULL);
    if (Request.responseHeader)
        printf("%s",Request.responseHeader);
    if (Request.responseBody)
        printf("%s",Request.responseBody);
    getchar();
    return 0;
}

但就目前而言,它根本不起作用。我不知道如何获得响应标头,而且我无法将响应标头写入类的公共成员
是的,我真的不擅长C++,尤其是在winapi方面
我希望你能帮我
这是我到目前为止的代码:

#include "stdafx.h"
#include <windows.h>
#include <winhttp.h>
#pragma comment(lib, "winhttp.lib")
class HttpRequest {
  private:
    DWORD dwSize;
    DWORD dwDownloaded;
    LPSTR pszOutBuffer;
    BOOL  bResults;
    HINTERNET hSession;
    HINTERNET hConnect;
    HINTERNET hRequest;
    LPCWSTR _userAgent;
    //LPCWSTR _proxyIp;
    //LPCWSTR _proxyPort;
    size_t bodySize;
  public:
    HttpRequest(LPCWSTR, LPCWSTR, LPCWSTR);
    void SendRequest(LPCWSTR, LPCWSTR, LPVOID);
    LPSTR responseHeader[1000000];
    LPSTR responseBody[1000000];
};
HttpRequest::HttpRequest(LPCWSTR userAgent, LPCWSTR proxyIp, LPCWSTR proxyPort) {
    _userAgent = userAgent;
    //_proxyIp = proxyIp;
    //_proxyPort = proxyPort;
    hSession = WinHttpOpen( userAgent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 );
}
void HttpRequest::SendRequest(LPCWSTR url, LPCWSTR method, LPVOID body) {
    bodySize = 0;
    if (hSession)
        hConnect = WinHttpConnect( hSession, url, INTERNET_DEFAULT_HTTPS_PORT, 0 );
    else
        printf("session handle failedn");
    if (hConnect)
        hRequest = WinHttpOpenRequest( hConnect, method, NULL, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE );
    else
        printf("connect handle failedn");
    if (hRequest)
        bResults = WinHttpSendRequest( hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, body, 0, 0, 0 );
    else
        printf("request handle failedn");
    if( bResults )
        bResults = WinHttpReceiveResponse( hRequest, NULL );
    if( bResults )
    {
        do 
        {
            // Check for available data.
            dwSize = 0;
            if( !WinHttpQueryDataAvailable( hRequest, &dwSize ) )
                printf( "Error %u in WinHttpQueryDataAvailable.n", GetLastError( ) );
            // Allocate space for the buffer.
            pszOutBuffer = new char[dwSize+1];
            if( !pszOutBuffer )
            {
                printf( "Out of memoryn" );
                dwSize=0;
            }
            else
            {
                // Read the data.
                ZeroMemory( pszOutBuffer, dwSize+1 );
                if( !WinHttpReadData( hRequest, (LPVOID)pszOutBuffer, dwSize, &dwDownloaded ) )
                    printf( "Error %u in WinHttpReadData.n", GetLastError( ) );
                else { 
                    //printf( "%s", pszOutBuffer );
                    responseBody[bodySize++] = pszOutBuffer; 
                }
                // Free the memory allocated to the buffer.
                delete [] pszOutBuffer;
            }
        } while( dwSize > 0 );
    }
    // Report any errors.
    if( !bResults )
        printf( "Error %d has occurred.n", GetLastError( ) );
    // Close any open handles.
    if( hRequest ) WinHttpCloseHandle( hRequest );
    if( hConnect ) WinHttpCloseHandle( hConnect );
    if( hSession ) WinHttpCloseHandle( hSession );
}

使用WinHttpQueryHeaders()访问响应标头。使用WINHTTP_QUERY_RAW_HEADERS(_CRLF)标志指定要检索所有可用标头。

您还需要更改类以动态分配其responseHeaderresponseBody成员。通过使用静态数组,您不仅浪费了大量内存,还限制了可以处理的响应大小。

试试这个:

#include "stdafx.h"
#include <windows.h>
#include <winhttp.h>
#include <string>
#include <vector>
#pragma comment(lib, "winhttp.lib")
class HttpRequest
{
private:
    std::wstring _userAgent;
    //std::wstring _proxyIp;
    //std::wstring _proxyPort;
public:
    HttpRequest(const std::wstring&, const std::wstring&, const std::wstring&);
    bool SendRequest(const std::wstring&, const std::wstring&, void*, DWORD);
    std::wstring responseHeader;
    std::vector<BYTE> responseBody;
};
HttpRequest::HttpRequest(const std::wstring &userAgent, const std::wstring &proxyIp, const std::wstring &proxyPort) :
    _userAgent(userAgent)
    //,_proxyIp(proxyIp)
    //,_proxyPort(proxyPort)
{
}
bool HttpRequest::SendRequest(const std::wstring &url, const std::wstring &method, void *body, DWORD bodySize)
{
    DWORD dwSize;
    DWORD dwDownloaded;
    DWORD headerSize = 0;
    BOOL  bResults = FALSE;
    HINTERNET hSession;
    HINTERNET hConnect;
    HINTERNET hRequest;
    responseHeader.resize(0);
    responseBody.resize(0);
    hSession = WinHttpOpen( _userAgent.c_str(), WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 );
    if (hSession)
        hConnect = WinHttpConnect( hSession, url.c_str(), INTERNET_DEFAULT_HTTPS_PORT, 0 );
    else
        printf("session handle failedn");
    if (hConnect)
        hRequest = WinHttpOpenRequest( hConnect, method.c_str(), NULL, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE );
    else
        printf("connect handle failedn");
    if (hRequest)
        bResults = WinHttpSendRequest( hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, body, bodySize, 0, 0 );
    else
        printf("request handle failedn");
    if (bResults)
        bResults = WinHttpReceiveResponse( hRequest, NULL );
    if (bResults)
    {
        bResults = WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, WINHTTP_NO_OUTPUT_BUFFER, &headerSize, WINHTTP_NO_HEADER_INDEX);
        if ((!bResults) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
        {
            responseHeader.resize(headerSize / sizeof(wchar_t));
            if (responseHeader.empty())
            {
                bResults = TRUE;
            }
            else
            {
                bResults = WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, &responseHeader[0], &headerSize, WINHTTP_NO_HEADER_INDEX);
                if( !bResults ) headerSize = 0;
                responseHeader.resize(headerSize / sizeof(wchar_t));
            }
        }
    }
    if (bResults)
    {
        do
        {
            // Check for available data.
            dwSize = 0;
            bResults = WinHttpQueryDataAvailable( hRequest, &dwSize );
            if (!bResults)
            {
                printf( "Error %u in WinHttpQueryDataAvailable.n", GetLastError( ) );
                break;
            }
            if (dwSize == 0)
                break;
            do
            {
                // Allocate space for the buffer.
                DWORD dwOffset = responseBody.size();
                responseBody.resize(dwOffset+dwSize);
                // Read the data.
                bResults = WinHttpReadData( hRequest, &responseBody[dwOffset], dwSize, &dwDownloaded );
                if (!bResults)
                {
                    printf( "Error %u in WinHttpReadData.n", GetLastError( ) );
                    dwDownloaded = 0;
                }
                responseBody.resize(dwOffset+dwDownloaded);
                if (dwDownloaded == 0)
                    break;
                dwSize -= dwDownloaded;
            }
            while (dwSize > 0);
        }
        while (true);
    }
    // Report any errors.
    if (!bResults)
        printf( "Error %d has occurred.n", GetLastError( ) );
    // Close any open handles.
    if( hRequest ) WinHttpCloseHandle( hRequest );
    if( hConnect ) WinHttpCloseHandle( hConnect );
    if( hSession ) WinHttpCloseHandle( hSession );
    return bResults;
}

int _tmain(int argc, _TCHAR* argv[])
{
    HttpRequest Request(L"Example UserAgent/1.0",L"",L"");
    if (Request.SendRequest(L"google.com",L"GET",NULL,0))
    {
        printf("%ls",Request.responseHeader.c_str());
        if (!Request.responseBody.empty())
            printf("%*s",Request.responseBody.size(),(char*)&Request.responseBody[0]);
    }
    getchar();
    return 0;
}