通过WinInet请求JSON数据会复制数据的某些部分

时间:2014-06-16 08:16:51

标签: c++ json get request wininet

我有一些返回JSON数据的API URL,如下所示:

{"data":[{"id":"1","param":"value1"},{"id":"2","param":"value2"}, ... {"id":"N","param":"valueN"}]}

每个id都应该是唯一的。

当我通过浏览器(Firefox或Chrome)请求此API网址时,它会返回有效数据,即每个id都是唯一的,而且不会复制数据部分。

但是,当我通过我自己的基于WinInet的函数请求此API网址时,它会复制某些数据部分。它仍然是有效的JSON,但有些id是重复的,有些则没有。就像这样:

{"data":[{"id":"1","param":"value1"},{"id":"1","param":"value1"},{"id":"2","param":"value2"},{"id":"3","param":"value3"},{"id":"3","param":"value3"} ... {"id":"N","param":"valueN"}]}

我正在使用GET方法。这是我的WinInet函数:

using namespace std;

enum EMethod    {M_UNKNOWN, M_POST, M_GET, M_DELETE};
enum EProtocol  {P_UNKNOWN, P_HTTP, P_HTTPS};

// |example:|
/*
string responce = SendInetRequest(
    P_HTTPS, M_GET, "www.site.com", "page.php", "param1=val1&param2=val2");
*/
string SendInetRequest(const EProtocol _eProtocol, 
                        const EMethod _eMethod,
                        const string& _server,
                        const string& _page,
                        const string& _params = "")
{
    char szData[1024];
    string recvStr;

    // initialize WinInet
    HINTERNET hInternet = ::InternetOpenA("WinInet Test", 
        INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    if (hInternet != NULL)
    {
        INTERNET_PORT port = NULL;
        DWORD flags = NULL;

        switch (_eProtocol)
        {
        case P_HTTP:
            port = INTERNET_DEFAULT_HTTP_PORT;
            flags = /*INTERNET_FLAG_KEEP_CONNECTION*/
                INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_PRAGMA_NOCACHE;
            break;
        case P_HTTPS:
            port = INTERNET_DEFAULT_HTTPS_PORT;
            flags = INTERNET_FLAG_SECURE | 
                INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_PRAGMA_NOCACHE;
            break;
        default:
            return NULL;
        }

        // open HTTP session
        HINTERNET hConnect = ::InternetConnectA(hInternet, 
            _server.c_str(), port, NULL,NULL, INTERNET_SERVICE_HTTP, 0, 1);
        if (hConnect != NULL) 
        {
            string request;
            string method;
            string headers;
            string data;

            switch (_eMethod)
            {
            case M_GET:     
                method = "GET";
                request = _page + 
                    (_params.empty() ? "" : ("?" + _params));
                break;
            case M_POST:    
                method = "POST";
                request = _page;
                headers = "Content-Type: application/x-www-form-urlencoded";
                data = _params.empty() ? "" : _params;
                break;
            case M_DELETE:
                method = "DELETE";
                request = _page + 
                    (_params.empty() ? "" : ("?" + _params));
                break;
            default:        
                return NULL;
            }

            // open request
            HINTERNET hRequest = ::HttpOpenRequestA(hConnect, method.c_str(), 
                (LPCSTR)request.c_str() ,NULL, NULL, 0, flags, 1);
            if (hRequest != NULL) 
            {   
                // send request
                BOOL isSend = ::HttpSendRequestA(hRequest, headers.c_str(), 
                    headers.length(), (LPVOID)data.c_str(), data.length());

                if (isSend)
                {
                    for(;;)
                    {
                        // reading data
                        DWORD dwByteRead;
                        BOOL isRead = ::InternetReadFile(hRequest, 
                            szData, sizeof(szData) - 1, &dwByteRead);

                        // break cycle if error or end
                        if (isRead == FALSE || dwByteRead == 0)
                            break;

                        // saving result
                        recvStr.append(szData, dwByteRead);
                        szData[dwByteRead] = 0;
                    }
                }

                // close request
                ::InternetCloseHandle(hRequest);
            }
            // close session
            ::InternetCloseHandle(hConnect);
        }
        // close WinInet
        ::InternetCloseHandle(hInternet);
    }

    return recvStr;
}

那我的功能出了什么问题?与普通浏览器不同,为什么它会复制响应JSON数据的某些部分?

1 个答案:

答案 0 :(得分:0)

您需要在之前将空终结符字节添加到szData ,然后将其附加到recvStr,以便您只附加刚收到的数据。

                    // saving result
                    szData[dwByteRead] = 0;
                    recvStr.append(szData, dwByteRead);