summaryrefslogtreecommitdiff
path: root/wx+/http.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'wx+/http.cpp')
-rw-r--r--wx+/http.cpp85
1 files changed, 51 insertions, 34 deletions
diff --git a/wx+/http.cpp b/wx+/http.cpp
index af51090c..ce3de482 100644
--- a/wx+/http.cpp
+++ b/wx+/http.cpp
@@ -6,11 +6,12 @@
#include "http.h"
#ifdef ZEN_WIN
- #include <zen/win.h> //tame wininet.h include
- #include <wininet.h>
+ #include <zen/win.h> //tame WinINet.h include
+ #include <WinINet.h>
#endif
#if defined ZEN_LINUX || defined ZEN_MAC
+ #include <wx/app.h>
#include <zen/thread.h> //std::thread::id
#include <wx/protocol/http.h>
#endif
@@ -31,7 +32,7 @@ namespace
#endif
-std::string sendHttpRequestImpl(const std::wstring& url, //throw FileError
+std::string sendHttpRequestImpl(const std::wstring& url, //throw SysError
const std::wstring& userAgent,
const std::string* postParams, //issue POST if bound, GET otherwise
int level = 0)
@@ -49,7 +50,7 @@ std::string sendHttpRequestImpl(const std::wstring& url, //throw FileError
nullptr, //_In_ LPCTSTR lpszProxyBypass,
0); //_In_ DWORD dwFlags
if (!hInternet)
- THROW_LAST_FILE_ERROR(_("Internet access failed."), L"InternetOpen");
+ THROW_LAST_SYS_ERROR(L"InternetOpen");
ZEN_ON_SCOPE_EXIT(::InternetCloseHandle(hInternet));
HINTERNET hSession = ::InternetConnect(hInternet, //_In_ HINTERNET hInternet,
@@ -61,16 +62,28 @@ std::string sendHttpRequestImpl(const std::wstring& url, //throw FileError
0, //_In_ DWORD dwFlags,
0); //_In_ DWORD_PTR dwContext
if (!hSession)
- THROW_LAST_FILE_ERROR(_("Internet access failed."), L"InternetConnect");
+ THROW_LAST_SYS_ERROR(L"InternetConnect");
ZEN_ON_SCOPE_EXIT(::InternetCloseHandle(hSession));
const wchar_t* acceptTypes[] = { L"*/*", nullptr };
- DWORD requestFlags = INTERNET_FLAG_KEEP_CONNECTION |
- INTERNET_FLAG_NO_UI |
- INTERNET_FLAG_RELOAD | //
- INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS; //relevant for GET only
+ DWORD requestFlags =
+ //INTERNET_FLAG_KEEP_CONNECTION |
+ // the combination 1. INTERNET_FLAG_KEEP_CONNECTION (= adds "Connection: Keep-Alive" but NOT "Keep-Alive: timeout" to the header)
+ // 2. *no* "Keep-Alive: timeout" header entry 3. call from within VM and 4. *no* Fiddler running 5. HTTP POST
+ // leads to Godaddy blocking the IP: http://www.freefilesync.org/forum/viewtopic.php?t=3855
+ // => it seems a broken keep alive header is the trigger: But why is it then working outside the VM or when Fiddler is running??? Why not a problem for HTTP GET?
+ // note: HTTP/1.1 has keep-alive semantics by default, so this flag is probably useless anyway
+ INTERNET_FLAG_NO_UI;
+
if (postParams)
- requestFlags |= INTERNET_FLAG_NO_AUTO_REDIRECT; //POST would be re-issued as GET during auto-redirect => handle ourselves!
+ {
+ requestFlags |= INTERNET_FLAG_NO_AUTO_REDIRECT; //POST would be re-issued as GET during auto-redirect => handle ourselves!
+ }
+ else //HTTP GET
+ {
+ requestFlags |= INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP;
+ requestFlags |= INTERNET_FLAG_RELOAD; //not relevant for POST (= never cached)
+ }
HINTERNET hRequest = ::HttpOpenRequest(hSession, //_In_ HINTERNET hConnect,
postParams ? L"POST" : L"GET", //_In_ LPCTSTR lpszVerb,
@@ -81,18 +94,22 @@ std::string sendHttpRequestImpl(const std::wstring& url, //throw FileError
requestFlags, //_In_ DWORD dwFlags,
0); //_In_ DWORD_PTR dwContext
if (!hRequest)
- THROW_LAST_FILE_ERROR(_("Internet access failed."), L"HttpOpenRequest");
+ THROW_LAST_SYS_ERROR(L"HttpOpenRequest");
ZEN_ON_SCOPE_EXIT(::InternetCloseHandle(hRequest));
- const std::wstring headers = postParams ? L"Content-type: application/x-www-form-urlencoded" : L"";
- std::string postParamsTmp = postParams ? *postParams : "";
- char* postParamBuf = postParamsTmp.empty() ? nullptr : &*postParamsTmp.begin();
+ const std::wstring headers = postParams ? L"Content-type: application/x-www-form-urlencoded" : L"";
+
+ assert(std::all_of(headers.begin(), headers.end(), [](wchar_t c){ return makeUnsigned(c) < 128; }));
+ //HttpSendRequest has finicky behavior for non-ASCII headers: https://msdn.microsoft.com/en-us/library/windows/desktop/aa384247
+
+ std::string postParamsBuf = postParams ? *postParams : "";
+
if (!::HttpSendRequest(hRequest, //_In_ HINTERNET hRequest,
headers.c_str(), //_In_ LPCTSTR lpszHeaders,
- static_cast<DWORD>(headers.size()), //_In_ DWORD dwHeadersLength,
- postParamBuf, //_In_ LPVOID lpOptional,
- static_cast<DWORD>(postParamsTmp.size()))) //_In_ DWORD dwOptionalLength
- THROW_LAST_FILE_ERROR(_("Internet access failed."), L"HttpSendRequest");
+ static_cast<DWORD>(headers.size()), //_In_ DWORD dwHeadersLength,
+ postParamsBuf.empty() ? nullptr : &postParamsBuf[0], //_In_ LPVOID lpOptional,
+ static_cast<DWORD>(postParamsBuf.size()))) //_In_ DWORD dwOptionalLength
+ THROW_LAST_SYS_ERROR(L"HttpSendRequest");
DWORD sc = 0;
{
@@ -102,7 +119,7 @@ std::string sendHttpRequestImpl(const std::wstring& url, //throw FileError
&sc, //_Inout_ LPVOID lpvBuffer,
&bufLen, //_Inout_ LPDWORD lpdwBufferLength,
nullptr)) //_Inout_ LPDWORD lpdwIndex
- THROW_LAST_FILE_ERROR(_("Internet access failed."), L"HttpQueryInfo: HTTP_QUERY_STATUS_CODE");
+ THROW_LAST_SYS_ERROR(L"HttpQueryInfo: HTTP_QUERY_STATUS_CODE");
}
//http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_Redirection
@@ -113,19 +130,19 @@ std::string sendHttpRequestImpl(const std::wstring& url, //throw FileError
DWORD bufLen = 10000;
std::wstring location(bufLen, L'\0');
if (!::HttpQueryInfo(hRequest, HTTP_QUERY_LOCATION, &*location.begin(), &bufLen, nullptr))
- THROW_LAST_FILE_ERROR(_("Internet access failed."), L"HttpQueryInfo: HTTP_QUERY_LOCATION");
+ THROW_LAST_SYS_ERROR(L"HttpQueryInfo: HTTP_QUERY_LOCATION");
if (bufLen >= location.size()) //HttpQueryInfo expected to write terminating zero
- throw FileError(_("Internet access failed."), L"HttpQueryInfo: HTTP_QUERY_LOCATION, buffer overflow");
+ throw SysError(L"HttpQueryInfo: HTTP_QUERY_LOCATION, buffer overflow");
location.resize(bufLen);
if (!location.empty())
return sendHttpRequestImpl(location, userAgent, postParams, level + 1);
}
- throw FileError(_("Internet access failed."), L"Unresolvable redirect.");
+ throw SysError(L"Unresolvable redirect.");
}
if (sc != HTTP_STATUS_OK) //200
- throw FileError(_("Internet access failed."), replaceCpy<std::wstring>(L"HTTP status code %x.", L"%x", numberTo<std::wstring>(sc)));
+ throw SysError(replaceCpy<std::wstring>(L"HTTP status code %x.", L"%x", numberTo<std::wstring>(sc)));
//e.g. 404 - HTTP_STATUS_NOT_FOUND
std::string buffer;
@@ -140,10 +157,10 @@ std::string sendHttpRequestImpl(const std::wstring& url, //throw FileError
&*(buffer.begin() + buffer.size() - blockSize), //_Out_ LPVOID lpBuffer,
blockSize, //_In_ DWORD dwNumberOfBytesToRead,
&bytesRead)) //_Out_ LPDWORD lpdwNumberOfBytesRead
- THROW_LAST_FILE_ERROR(_("Internet access failed."), L"InternetReadFile");
+ THROW_LAST_SYS_ERROR(L"InternetReadFile");
if (bytesRead > blockSize) //better safe than sorry
- throw FileError(_("Internet access failed."), L"InternetReadFile: buffer overflow.");
+ throw SysError(L"InternetReadFile: buffer overflow.");
if (bytesRead < blockSize)
buffer.resize(buffer.size() - (blockSize - bytesRead)); //caveat: unsigned arithmetics
@@ -161,11 +178,11 @@ std::string sendHttpRequestImpl(const std::wstring& url, //throw FileError
webAccess.SetTimeout(10 /*[s]*/); //default: 10 minutes: WTF are these wxWidgets people thinking???
if (!webAccess.Connect(server)) //will *not* fail for non-reachable url here!
- throw FileError(_("Internet access failed."), L"wxHTTP::Connect");
+ throw SysError(L"wxHTTP::Connect");
if (postParams)
if (!webAccess.SetPostText(L"application/x-www-form-urlencoded", utfCvrtTo<wxString>(*postParams)))
- throw FileError(_("Internet access failed."), L"wxHTTP::SetPostText");
+ throw SysError(L"wxHTTP::SetPostText");
std::unique_ptr<wxInputStream> httpStream(webAccess.GetInputStream(page)); //must be deleted BEFORE webAccess is closed
const int sc = webAccess.GetResponse();
@@ -179,14 +196,14 @@ std::string sendHttpRequestImpl(const std::wstring& url, //throw FileError
if (!newUrl.empty())
return sendHttpRequestImpl(newUrl, userAgent, postParams, level + 1);
}
- throw FileError(_("Internet access failed."), L"Unresolvable redirect.");
+ throw SysError(L"Unresolvable redirect.");
}
if (sc != 200) //HTTP_STATUS_OK
- throw FileError(_("Internet access failed."), replaceCpy<std::wstring>(L"HTTP status code %x.", L"%x", numberTo<std::wstring>(sc)));
+ throw SysError(replaceCpy<std::wstring>(L"HTTP status code %x.", L"%x", numberTo<std::wstring>(sc)));
if (!httpStream || webAccess.GetError() != wxPROTO_NOERR)
- throw FileError(_("Internet access failed."), L"wxHTTP::GetError");
+ throw SysError(L"wxHTTP::GetError");
std::string buffer;
int newValue = 0;
@@ -221,7 +238,7 @@ std::string urlencode(const std::string& str)
}
-std::string zen::sendHttpPost(const std::wstring& url, const std::wstring& userAgent, const std::vector<std::pair<std::string, std::string>>& postParams) //throw FileError
+std::string zen::sendHttpPost(const std::wstring& url, const std::wstring& userAgent, const std::vector<std::pair<std::string, std::string>>& postParams) //throw SysError
{
//convert post parameters into "application/x-www-form-urlencoded"
std::string flatParams;
@@ -231,13 +248,13 @@ std::string zen::sendHttpPost(const std::wstring& url, const std::wstring& userA
if (!flatParams.empty())
flatParams.pop_back();
- return sendHttpRequestImpl(url, userAgent, &flatParams); //throw FileError
+ return sendHttpRequestImpl(url, userAgent, &flatParams); //throw SysError
}
-std::string zen::sendHttpGet(const std::wstring& url, const std::wstring& userAgent) //throw FileError
+std::string zen::sendHttpGet(const std::wstring& url, const std::wstring& userAgent) //throw SysError
{
- return sendHttpRequestImpl(url, userAgent, nullptr); //throw FileError
+ return sendHttpRequestImpl(url, userAgent, nullptr); //throw SysError
}
bgstack15