英文:
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_DIRECT
和 INTERNET_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>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论