HTTP连接失败,但返回错误代码为0。

huangapple go评论106阅读模式
英文:

HTTP Connection fails but returns an error code of 0

问题

在调用此代码时,我遇到的问题是 InternetConnectW 返回一个值为0的句柄,但 GetLastError 也返回0。我已验证主机("https://qh7g3o0ypc.execute-api.ap-northeast-1.amazonaws.com")和端口(443)。这是什么情况,我该如何解决呢?

英文:

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?

答案1

得分: 0

我找到了问题。原来是我错误地设置了标志和服务。

首先,根据这里INTERNET_OPEN_TYPE_DIRECTINTERNET_OPEN_TYPE_PRECONFIG 相互冲突。因此,我移除了 INTERNET_OPEN_TYPE_DIRECT,以告诉Windows我想使用存储在注册表中的网络设置。

接下来,我查看了Windows文档,这里,发现尽管定义了 INTERNET_SERVICE_HTTPS,但 HTTP 和 HTTPS 请求都由 INTERNET_SERVICE_HTTP 服务标志定义。

最后,我没有在正确的位置包含 INTERNET_FLAG_SECURE 标志。我从这个问题中发现,这个标志需要包含在对 HttpOpenRequestW 的调用中,包含在其他任何地方都是多余的。

在做了所有这些更改后,我的代码看起来像这样:

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();
      
   // 首先,向Windows报告我们将使用的用户代理请求HTTP数据。如果失败,则返回错误。
   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;
   }
   
   // 接下来,尝试创建一个到所需端口的URL的Internet连接;如果失败则返回错误
   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;
   }
   
   // 现在,如果我们想要一个安全连接,那么将安全标志添加到连接中
   if (secure) {
      flags |= INTERNET_FLAG_SECURE;
   }
   
   // 最后,使用会话变量、动词和URL打开HTTP请求;如果失败则记录并返回错误
   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;
}

<details>
<summary>英文:</summary>

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

First, according to [this][1], `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][2], 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][3], 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;
}


  [1]: https://learn.microsoft.com/en-us/windows/win32/wininet/enabling-internet-functionality#setting-access-types
  [2]: https://INTERNET_OPEN_TYPE_DIRECT
  [3]: https://stackoverflow.com/questions/18910463/how-to-send-https-request-using-wininet

</details>



huangapple
  • 本文由 发表于 2023年2月27日 15:18:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/75577659.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定