POST Request in WinHttp c++

15,899

In order for PHP (or any other post-processing language) to recognise POST data, add this:

LPCWSTR additionalHeaders = L"Content-Type: application/x-www-form-urlencoded\r\n";
DWORD headersLength = -1;

bResults = WinHttpSendRequest(  hRequest,
                                additionalHeaders,
                                headersLength ,
                                (LPVOID)data,
                                data_len,
                                data_len, 
                                0);

The rest of a code is functional, should work: enter image description here

Share:
15,899
Jose
Author by

Jose

Updated on June 04, 2022

Comments

  • Jose
    Jose almost 2 years

    I'm trying to make a POST request in c++ with the WinHTTP api Click to the Microsoft Guide, the problem is that the example that is available in the microsoft webpage is a "GET" request so I came up with this code searching on the internet:

    First we call the code:

    HttpsWebRequestPost("example.com", "/api.php?action=UserLogin", "loginUsername=" + USERNAME + "&loginPassword=" + PASSWORD + "&url=/index.php?page=Portal");
    

    Then:

    #include <Windows.h>
    #include <WinHttp.h>
    #include <stdio.h>
    #include <iostream> //getchar
    #include <fstream>
    
    #pragma comment(lib, "winhttp.lib")
    
    using namespace std;
    
    std::wstring get_utf16(const std::string &str, int codepage)
    {
        if (str.empty()) return std::wstring();
        int sz = MultiByteToWideChar(codepage, 0, &str[0], (int)str.size(), 0, 0);
        std::wstring res(sz, 0);
        MultiByteToWideChar(codepage, 0, &str[0], (int)str.size(), &res[0], sz);
        return res;
    }
    
    string HttpsWebRequestPost(string domain, string url, string dat)
    {
        //Extra
        LPSTR  data = const_cast<char *>(dat.c_str());;
        DWORD data_len = strlen(data);
    
    
        wstring sdomain = get_utf16(domain, CP_UTF8);
        wstring surl = get_utf16(url, CP_UTF8);
        string response;
    
        DWORD dwSize = 0;
        DWORD dwDownloaded = 0;
        LPSTR pszOutBuffer;
        BOOL  bResults = FALSE;
        HINTERNET  hSession = NULL,
            hConnect = NULL,
            hRequest = NULL;
    
        // Use WinHttpOpen to obtain a session handle.
        hSession = WinHttpOpen(L"WinHTTP Example/1.0",
            WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
            WINHTTP_NO_PROXY_NAME,
            WINHTTP_NO_PROXY_BYPASS, 0);
    
        // Specify an HTTP server.
        if (hSession)
            hConnect = WinHttpConnect(hSession, sdomain.c_str(),
                INTERNET_DEFAULT_HTTP_PORT, 0);
    
        // Create an HTTP request handle.
        if (hConnect)
            hRequest = WinHttpOpenRequest(hConnect, L"POST", surl.c_str(),
                NULL, WINHTTP_NO_REFERER,
                WINHTTP_DEFAULT_ACCEPT_TYPES,
                0);
    
        // Send a request.
        if (hRequest)
            bResults = WinHttpSendRequest(hRequest,
                WINHTTP_NO_ADDITIONAL_HEADERS, 0,
                (LPVOID)data, data_len,
                data_len, 0);
    
    
        // End the request.
        if (bResults)
            bResults = WinHttpReceiveResponse(hRequest, NULL);
    
        // Keep checking for data until there is nothing left.
        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 memory\n");
                    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);
                        response = response + string(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);
    
        return response;
    
    }
    

    But using WireShark I only get:

    Hypertext Transfer Protocol
        POST ***************** HTTP/1.1\r\n
        Connection: Keep-Alive\r\n
        User-Agent: WinHTTP Example/1.0\r\n
        Content-Length: **\r\n
        Host: ******\r\n
        \r\n
    

    Anyone can help meto fix this or know an easier method? Thanks