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;
}
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:
InternetConnect()
wants the server's hostname and port (ie "ip-api.com"
and "80"
), and the INTERNET_FLAG_SECURE
flag when connecting to an HTTPS server.
HttpOpenRequest()
wants the resource's path on the server (ie "/json/168.197.155.244"
).
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.