c++httpsmql4

HTTP Connection fails but returns an error code of 0


I'm writing an HTTP requester for a library in MQL4. This is what I have so far:

#define INTERNET_OPEN_TYPE_PRECONFIG 0
#define INTERNET_OPEN_TYPE_DIRECT    1
#define INTERNET_FLAG_NO_UI          0x00000200
#define INTERNET_FLAG_SECURE         0x00800000
#define INTERNET_FLAG_NO_CACHE_WRITE 0x04000000
#define INTERNET_SERVICE_HTTP        3
#define INTERNET_SERVICE_HTTPS       6

HttpRequester::HttpRequester(const string verb, const string host, const string resource, 
   const int port, const bool secure, const string referrer = NULL) {
   m_ready = false;
   ResetLastError();
      
   // First, set the secure flag if we want a secure connection and define the service
   int service = INTERNET_SERVICE_HTTP;
   int flags = INTERNET_OPEN_TYPE_DIRECT | INTERNET_OPEN_TYPE_PRECONFIG | INTERNET_FLAG_NO_CACHE_WRITE;
   if (secure) {
      flags |= INTERNET_FLAG_SECURE;
      service = INTERNET_SERVICE_HTTPS;
   }
   
   // Next, report to Windows the user agent that we'll request HTTP data with. If this fails
   // then return an error
   m_open_handle = InternetOpenW(GetUserAgentString(), flags, NULL, NULL, 0);
   if (m_open_handle == INTERNET_INVALID_HANDLE) {
      SetUserError(INTERNET_OPEN_FAILED_ERROR);
      return;
   }
   
   // Now, attempt to create an intenrnet connection to the URL at the desired port;
   // if this fails then return an error
   m_session_handle = InternetConnectW(m_open_handle, host, port, "", "", service, flags, 1);
   if (m_session_handle == INTERNET_INVALID_HANDLE) {
      SetUserError(INTERNET_CONNECT_FAILED_ERROR);
      return;
   }
   
   // Finally, open the HTTP request with the session variable, verb and URL; if this fails
   // then log and return an error
   string accepts[];
   m_request_handle = HttpOpenRequestW(m_session_handle, verb, resource, NULL, referrer, 
      accepts, INTERNET_FLAG_NO_UI, 1);
   if (m_request_handle == INTERNET_INVALID_HANDLE) {
      SetUserError(INTERNET_OPEN_REQUEST_FAILED_ERROR);
      return;
   }
   
   m_ready = true;
}

When calling this code, the issue I'm having is that InternetConnectW returns a handle of 0, but GetLastError also returns 0. I have verified the host ("https://qh7g3o0ypc.execute-api.ap-northeast-1.amazonaws.com") and port (443). What is going on here and how do I fix this?


Solution

  • I found the issue. It turns out that I was setting my flags and service improperly.

    First, according to this, INTERNET_OPEN_TYPE_DIRECT and INTERNET_OPEN_TYPE_PRECONFIG conflict with each other. So, I removed INTERNET_OPEN_TYPE_DIRECT to tell Windows that I would like to use the network settings stored in the registry.

    Next, I looked at the Windows documentation, here, and found out that, although INTERNET_SERVICE_HTTPS is defined, both HTTP and HTTPS requests are defined by the INTERNET_SERVICE_HTTP service flag.

    Finally, I was not including the INTERNET_FLAG_SECURE flag in the right place. I discovered, from this question, that this flag needs to be included on the call to HttpOpenRequestW and including it anywhere else would be redundant.

    After making all these changes, my code looks like this:

    HttpRequester::HttpRequester(const string verb, const string host, const string resource, 
       const int port, const bool secure, const string referrer = NULL) {
       m_ready = false;
       ResetLastError();
          
       // First, report to Windows the user agent that we'll request HTTP data with. If this fails
       // then return an error
       int flags = INTERNET_OPEN_TYPE_PRECONFIG | INTERNET_FLAG_NO_CACHE_WRITE;
       m_open_handle = InternetOpenW(GetUserAgentString(), flags, NULL, NULL, 0);
       if (m_open_handle == INTERNET_INVALID_HANDLE) {
          SetUserError(INTERNET_OPEN_FAILED_ERROR);
          return;
       }
       
       // Next, attempt to create an intenrnet connection to the URL at the desired port;
       // if this fails then return an error
       m_session_handle = InternetConnectW(m_open_handle, host, port, "", "", INTERNET_SERVICE_HTTP, flags, 0);
       if (m_session_handle == INTERNET_INVALID_HANDLE) {
          SetUserError(INTERNET_CONNECT_FAILED_ERROR);
          return;
       }
       
       // Now, if we want a secure connection then add the secure flag to the connection
       if (secure) {
          flags |= INTERNET_FLAG_SECURE;
       }
       
       // Finally, open the HTTP request with the session variable, verb and URL; if this fails
       // then log and return an error
       string accepts[];
       m_request_handle = HttpOpenRequestW(m_session_handle, verb, resource, NULL, referrer, 
          accepts, flags, 0);
       if (m_request_handle == INTERNET_INVALID_HANDLE) {
          SetUserError(INTERNET_OPEN_REQUEST_FAILED_ERROR);
          return;
       }
       
       m_ready = true;
    }