c++httpwinapihttprequestwininet

C++::HttpQueryInfo returns status code 403 only the first time


I have the following code that it works for any site that I have tried except this one where I get status code 403 after running ::HttpQueryInfo. But, if I call ::HttpSendRequest twice before calling ::HttpQueryInfo it returns status code 200, it works as expected without problems and I don't understand why I would need to call twice the ::HttpSendRequest for this particular situation.

 HINTERNET hInternet;
  ::InternetConnect(hInternet, L"dev.mysql.com", 443, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);

  const TCHAR * lplpszAcceptTypes[] = { _T("*/*"), nullptr };
  ::HttpOpenRequest(hInternet, L"GET",
                    L"/get/Downloads/Connector-ODBC/8.0/mysql-connector-odbc-8.0.31-winx64.msi",
                    L"HTTP/1.0", L"", lplpszAcceptTypes,
                    INTERNET_FLAG_RELOAD | INTERNET_FLAG_KEEP_CONNECTION |
                    INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP |
                    INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS | INTERNET_FLAG_SECURE,
                    0);

  ::HttpSendRequest(hInternet, NULL, 0, 0, 0);

  DWORD statusCode = 0, size = sizeof(DWORD);
  ::HttpQueryInfo(hInternet, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, (LPVOID)&statusCode,
                  &size, nullptr);

Also, I don't know if it's useful but this is the response header

HTTP/1.1 403 Forbidden
Server: AkamaiNetStorage
Content-Length: 4545
Content-Type: text/html
Set-Cookie: AK_NETWORKTYPE=ESSL; expires=Wed, 17-May-2023 09:21:16 GMT
ETag: "46491460e504640b96a3f5e60da0945f:1434117667"
Expires: Wed, 17 May 2023 09:19:16 GMT
Cache-Control: max-age=0, no-cache, no-store
Pragma: no-cache
Date: Wed, 17 May 2023 09:19:16 GMT
Connection: keep-alive

Solution

  • The server is performing some sort of request validation. Testing that URL in Fiddler produces the same 403 result.

    Making the request look more like a real browser request by adding the headers:

    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0
    Accept: */*
    Accept-Encoding: gzip, deflate, br
    

    Makes the request work (although the response is a 302 redirect to a different CDN URL, which WinHTTP should honor automatically).