中使用Winhttp将JSON数据发布到api

中使用Winhttp将JSON数据发布到api

本文介绍了如何在C ++中使用Winhttp将JSON数据发布到api的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要使用C ++将json数据发布到api.在API中,我还需要包含app_idapp_key作为标头.下面是我正在使用的代码:

I need to post json data to api using c++. In the API, I also need to include app_id and app_key as header. Below is the code I am using:

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;
}

LPCWSTR additionalHeaders = L"Content-Type: application/json\r\n" + L"app_id: 7ty44" + L"app_key: e36ff19de5623";
DWORD headersLength = -1;

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,
            additionalHeaders,
            headersLength,
            (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;

}

我在additional headers中包含了app_idapp_key,但是不确定这是否是正确的方法.另外,如何通过传递需要发送的json数据来调用它.我没有找到任何合适的例子.谢谢

I have include the app_id and app_key in additional headers but not sure if this is the correct way to do it or not. Also how can I call it by passing the json data which I need to send. I did not find any good working example for this. Thanks

推荐答案

从与"S Andrew"的讨论开始,这是一个Win32控制台应用程序,使用旧的免费软件中使用的包装函数来测试WinHTTP的GET/POST.

From the discussion with "S Andrew", a Win32 Console App to test GET/POST with WinHTTP, using a wrapper function used in an old freeware

在网站 www.dummy.restapiexample.com

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <conio.h>

#include <Winhttp.h>
#pragma comment(lib, "Winhttp")

#include <Shlwapi.h> // SHRegGetValue
#pragma comment(lib, "Shlwapi")

#define HTTP_TIMEOUT 15000
HINTERNET hOpen, hOpenProxy;
void GetProxy(WCHAR* sProxyName);
DWORD WinHTTPRequest(LPCTSTR pServerName, LPCTSTR pRequest, WCHAR* sCommand, LPVOID pPostData, int nPostDataLength, LPCWSTR pwszHeaders, char **dataOut, int *nRead, WCHAR **dataHeaderOut, BOOL bTestProxy, BOOL bSecure, WCHAR* wsRedirect, DWORD *dwReturnStatus);
WCHAR g_wsCurrentProxy[255] = L"";

int main()
{
    hOpen = WinHttpOpen(L"Test", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME,  WINHTTP_NO_PROXY_BYPASS, 0);
    WinHttpSetTimeouts(hOpen, HTTP_TIMEOUT, HTTP_TIMEOUT, HTTP_TIMEOUT, HTTP_TIMEOUT);

    WCHAR wsHostName[MAX_PATH] = L"www.dummy.restapiexample.com";
    WCHAR wsURLPathGet[MAX_PATH] = L"/api/v1/employees";
    WCHAR wsURLPathPost[MAX_PATH] = L"/api/v1/create";
    char sPostData[500] = "{\"name\":\"Test Unique Name 1\",\"salary\":\"123456\",\"age\":\"18\"}";

    char *sHTTPData = NULL;
    int nDataRead = 0;
    WCHAR *wsDataHeader = NULL;
    WCHAR wsRedirect[2048 + 32 + 3]; // INTERNET_MAX_URL_LENGTH
    DWORD dwStatus = 0;

    WCHAR wsAdditionalHeaders[1024] = L"";
    lstrcpy(wsAdditionalHeaders,
        L"Accept: application/json\r\n"
        L"Content-Type: application/x-www-form-urlencoded\r\n"
        //L"Accept-Encoding: gzip, deflate, br\r\n");
        L"Accept-Encoding: txt\r\n");

    printf("Before first GET - Type a key\n");
    _getch();
    DWORD dwReturn = WinHTTPRequest(wsHostName, wsURLPathGet, L"GET", WINHTTP_NO_REQUEST_DATA, NULL, wsAdditionalHeaders, &sHTTPData, &nDataRead, &wsDataHeader, 0, 0, wsRedirect, &dwStatus);
    if (dwStatus == 0)
        printf(sHTTPData);
    else
        printf("Error Status : [%d]\n", dwStatus);
    if (sHTTPData)
        delete[] sHTTPData;
    if (wsDataHeader)
        delete[] wsDataHeader;

    printf("\n\nBefore POST - Type a key\n");
    _getch();
    dwReturn = WinHTTPRequest(wsHostName, wsURLPathPost, L"POST", sPostData, NULL, wsAdditionalHeaders, &sHTTPData, &nDataRead, &wsDataHeader, 0, 0, wsRedirect, &dwStatus);
    if (dwStatus == 0)
        printf(sHTTPData);
    else
        printf("Error Status : [%d]\n", dwStatus);
    if (sHTTPData)
        delete[] sHTTPData;
    if (wsDataHeader)
        delete[] wsDataHeader;

    printf("\n\nBefore second GET - Type a key\n");
    _getch();
    dwReturn = WinHTTPRequest(wsHostName, wsURLPathGet, L"GET", WINHTTP_NO_REQUEST_DATA, NULL, wsAdditionalHeaders, &sHTTPData, &nDataRead, &wsDataHeader, 0, 0, wsRedirect, &dwStatus);
    if (dwStatus == 0)
        printf(sHTTPData);
    else
        printf("Error Status : [%d]\n", dwStatus);
    if (sHTTPData)
        delete[] sHTTPData;
    if (wsDataHeader)
        delete[] wsDataHeader;

    printf("\n\nEND - Type a key\n");
    _getch();
    if (hOpen)
        WinHttpCloseHandle(hOpen);
    if (hOpenProxy)
        WinHttpCloseHandle(hOpenProxy);
    return 0;
}

void GetProxy(WCHAR* sProxyName)
{
    lstrcpy(sProxyName, L"");
    unsigned long nBufferSize = 4096;
    WCHAR wszBuf[4096] = { 0 };
    WINHTTP_PROXY_INFO* pInfo = (WINHTTP_PROXY_INFO*)wszBuf;
    if (WinHttpQueryOption(NULL, WINHTTP_OPTION_PROXY, pInfo, &nBufferSize))
    {
        if (pInfo->dwAccessType == WINHTTP_OPTION_PROXY)
        {
            WCHAR wsKey[MAX_PATH] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings";
            WCHAR wsValue[MAX_PATH] = L"ProxyEnable";
            DWORD dwValue = (DWORD)FALSE;
            DWORD dwSize = sizeof(dwValue);
            LONG nStatus = SHRegGetValue(HKEY_CURRENT_USER, wsKey, wsValue, SRRF_RT_DWORD, NULL, &dwValue, &dwSize);
            if ((nStatus == ERROR_FILE_NOT_FOUND) || (nStatus == ERROR_PATH_NOT_FOUND))
                nStatus = SHRegGetValue(HKEY_LOCAL_MACHINE, wsKey, wsValue, SRRF_RT_DWORD, NULL, &dwValue, &dwSize);
            if (nStatus != ERROR_SUCCESS)
                dwValue = FALSE;
            if (dwValue)
                lstrcpy(sProxyName, pInfo->lpszProxy);
        }
    }
}

DWORD WinHTTPRequest(LPCTSTR pServerName, LPCTSTR pRequest, WCHAR* sCommand, LPVOID pPostData, int nPostDataLength, LPCWSTR pwszHeaders, char **dataOut, int *nRead, WCHAR **dataHeaderOut, BOOL bTestProxy, BOOL bSecure, WCHAR* wsRedirect, DWORD *dwReturnStatus)
{
    HINTERNET hCurrentOpen = NULL;
    if (bTestProxy)
    {
        WCHAR sProxy[255] = L"";
        GetProxy(sProxy);
        if (lstrcmp(sProxy, L"") == 0)
            hCurrentOpen = hOpen;
        else if (lstrcmp(sProxy, g_wsCurrentProxy) != 0)
        {
            if (hOpenProxy)
                WinHttpCloseHandle(hOpenProxy);
            hOpenProxy = WinHttpOpen(L"Test", WINHTTP_ACCESS_TYPE_NAMED_PROXY, sProxy, NULL, 0/*INTERNET_FLAG_ASYNC*/);
            lstrcpy(g_wsCurrentProxy, sProxy);
            hCurrentOpen = hOpenProxy;
        }
        else
            hCurrentOpen = hOpenProxy;
    }
    else
        hCurrentOpen = hOpen;

    HINTERNET hConnect = NULL;
    if (bSecure)
        hConnect = WinHttpConnect(hCurrentOpen, pServerName, INTERNET_DEFAULT_HTTPS_PORT, 0);
    else
        hConnect = WinHttpConnect(hCurrentOpen, pServerName, INTERNET_DEFAULT_HTTP_PORT, 0);

    if (!hConnect)
    {
        DWORD dwError = GetLastError();
        return dwError;
    }

    DWORD dwFlags;
    if (bSecure)
        dwFlags = WINHTTP_FLAG_SECURE | WINHTTP_FLAG_REFRESH;
    else
        dwFlags = WINHTTP_FLAG_REFRESH;

    HINTERNET hRequest = WinHttpOpenRequest(hConnect, sCommand, pRequest, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, dwFlags);
    if (!hRequest)
    {
        DWORD dwError = GetLastError();
        WinHttpCloseHandle(hConnect);
        return dwError;
    }

    WinHttpAddRequestHeaders(hRequest, pwszHeaders, -1, WINHTTP_ADDREQ_FLAG_ADD);
    int nLengthPostData;
    if (nPostDataLength == NULL)
    {
        if (pPostData)
            nLengthPostData = strlen((char*)pPostData);
        else
            nLengthPostData = 0;
    }
    else
        nLengthPostData = nPostDataLength;

    BOOL bSuccess;
    if (wsRedirect != NULL)
    {
        DWORD dwOption;
        DWORD dwOptionSize;
        dwOption = WINHTTP_OPTION_REDIRECT_POLICY_NEVER;
        dwOptionSize = sizeof(DWORD);
        bSuccess = WinHttpSetOption(hRequest, WINHTTP_OPTION_REDIRECT_POLICY, (LPVOID)&dwOption, dwOptionSize);
        DWORD dwOptionValue = WINHTTP_DISABLE_REDIRECTS;
        bSuccess = WinHttpSetOption(hRequest, WINHTTP_OPTION_DISABLE_FEATURE, &dwOptionValue, sizeof(dwOptionValue));
    }
    BOOL b = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, pPostData, pPostData == NULL ? 0 : nLengthPostData, nLengthPostData, 0 );
    if (!b)
    {
        DWORD dwError = GetLastError();
        WinHttpCloseHandle(hConnect);
        WinHttpCloseHandle(hRequest);
        return dwError;
    }
    WinHttpReceiveResponse( hRequest, NULL);
    DWORD dwStatus = 0;
    DWORD dwStatusSize = sizeof(DWORD);
    if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &dwStatus, &dwStatusSize, NULL))
    {
        if (HTTP_STATUS_REDIRECT == dwStatus || HTTP_STATUS_MOVED == dwStatus)
        {
            DWORD dwSize;
            WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_LOCATION, WINHTTP_HEADER_NAME_BY_INDEX, NULL, &dwSize, WINHTTP_NO_HEADER_INDEX);
            if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
                return 500;
            LPWSTR pwsRedirectURL = new WCHAR[dwSize];
            bSuccess = WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_LOCATION, WINHTTP_HEADER_NAME_BY_INDEX, pwsRedirectURL, &dwSize, WINHTTP_NO_HEADER_INDEX);
            if (!bSuccess)
                return 500;
            if (wsRedirect != NULL)
                lstrcpy(wsRedirect, pwsRedirectURL);
            if (dwReturnStatus != NULL)
                *dwReturnStatus = dwStatus;
            delete[] pwsRedirectURL;
        }
        else if (dwStatus != HTTP_STATUS_OK && dwStatus != HTTP_STATUS_BAD_REQUEST && dwStatus != HTTP_STATUS_CREATED)
        {
            DWORD dwError = GetLastError();
            WinHttpCloseHandle(hConnect);
            WinHttpCloseHandle(hRequest);
            if (dwReturnStatus != NULL)
                *dwReturnStatus = dwStatus;
            return dwError;
        }
    }
    if (dataHeaderOut != NULL)
    {
        DWORD dwSize = 0;
        WCHAR *pOutBuffer = NULL;
        if (!WinHttpQueryHeaders(hRequest,WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, NULL, &dwSize, WINHTTP_NO_HEADER_INDEX))
        {
            DWORD dwErr = GetLastError();
            if (dwErr != ERROR_INSUFFICIENT_BUFFER)
            {
                DWORD dwError = GetLastError();
                WinHttpCloseHandle(hConnect);
                WinHttpCloseHandle(hRequest);
                return dwError;
            }
        }
        pOutBuffer = new WCHAR[dwSize];
        if (WinHttpQueryHeaders(hRequest,WINHTTP_QUERY_RAW_HEADERS_CRLF,WINHTTP_HEADER_NAME_BY_INDEX, pOutBuffer, &dwSize, WINHTTP_NO_HEADER_INDEX))
        {
            pOutBuffer[dwSize] = '\0';
            *dataHeaderOut = (WCHAR*)pOutBuffer;
        }
        //delete[] pOutBuffer;
    }

    char *sReadBuffer = NULL;
    DWORD nTotalRead = 0;
    DWORD nToRead = 0;
    DWORD nBytesRead = 0;
    do {
        if (!WinHttpQueryDataAvailable(hRequest, &nToRead))
            break;
        if (nToRead == 0)
            break;
        sReadBuffer = (char*)((sReadBuffer == NULL) ? malloc(nToRead) : realloc(sReadBuffer, nTotalRead + nToRead + 1));
        if (WinHttpReadData(hRequest, sReadBuffer + nTotalRead, nToRead, &nBytesRead))
        {
            nTotalRead += nBytesRead;
        }
    } while (nToRead > 0);
    if (sReadBuffer != NULL && nTotalRead > 0)
    {
        {
            char *sBuffer = new char[nTotalRead + 1];
            memcpy(sBuffer, sReadBuffer, nTotalRead + 1);
            sBuffer[nTotalRead] = '\0';
            *dataOut = sBuffer;
        }
        free(sReadBuffer);
    }

    *nRead = nTotalRead;
    WinHttpCloseHandle(hConnect);
    WinHttpCloseHandle(hRequest);
    return ERROR_SUCCESS;
}

这篇关于如何在C ++中使用Winhttp将JSON数据发布到api的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-15 19:03