c++visual-studiowininetwindows-11

how to get the data from a json from the web using wininet in C++?


I'm new to C++, I am trying to consume the ip-api.com API to fetch a geolocation based on an IP number. But I can't make a request correctly. What can I change in this code to get the JSON response correctly?

string GetLocation() {
    DWORD size = 0;
    DWORD wrt;
    LPCWSTR down = L"Downloader";
    string msg = "";

    /*wstring ipConvert(ipAdr().begin(), ipAdr().end());
    LPCWSTR ip = ipConvert.c_str();*/

    string url = "http://ip-api.com/json/168.197.155.244";
    wstring urlConvert(url.begin(), url.end());
    LPCWSTR urlFinal = L"http://ip-api.com/json/168.197.155.244";
    LPCWSTR headers = L"Content-Type: application/json\r\n";


    HINTERNET open = InternetOpen(down, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
    HINTERNET connect = InternetConnect(open, urlFinal, NULL, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
    HINTERNET request = HttpOpenRequest(connect, NULL, urlFinal, NULL, NULL, 0, 0, 0);
    HttpAddRequestHeaders(request, headers, -1, HTTP_ADDREQ_FLAG_ADD);

    HttpSendRequest(request, NULL, 0, NULL, 0);
    InternetQueryDataAvailable(request, &size, 0, 0);
    char* buff = new char[size + 1];
    memset(buff, 0, size + 1);

    InternetReadFile(request, buff, size, &wrt);
    msg += buff;

    InternetCloseHandle(open);
    InternetCloseHandle(connect);
    InternetCloseHandle(request);

    return msg;
}

Solution

  • Aside from your complete lack of any error handling, the main issue with your code is that you can't pass a URL to InternetConnect() and HttpOpenRequest(), as you are doing.

    You need to break up the URL into its constituent pieces (see InternetCrackUrl()) - namely: scheme, hostname, port, and path - and then pass the approach pieces to each function as needed:

    Alternatively, you can use InternetOpenUrl() instead. In which case, you don't need to use HttpOpenRequest() and HttpSendRequest() at all (and BTW, your use of HttpAddRequestHeaders() can be removed completely, as you are not sending any data to the server, so there is no need to add a Content-Type header to the request). See Handling Uniform Resource Locators in WinInet's documentation for more details about that.