33 if (s.empty())
return {};
34 const int len = MultiByteToWideChar(CP_UTF8, 0, s.data(),
static_cast<int>(s.size()),
nullptr, 0);
35 std::wstring ws(len, L
'\0');
36 MultiByteToWideChar(CP_UTF8, 0, s.data(),
static_cast<int>(s.size()), ws.data(), len);
54 uc.dwStructSize =
sizeof(uc);
55 uc.dwHostNameLength =
static_cast<DWORD
>(-1);
56 uc.dwUrlPathLength =
static_cast<DWORD
>(-1);
57 uc.dwExtraInfoLength =
static_cast<DWORD
>(-1);
59 if (!WinHttpCrackUrl(wurl.c_str(),
static_cast<DWORD
>(wurl.size()), 0, &uc))
62 out.
host.assign(uc.lpszHostName, uc.dwHostNameLength);
63 out.
path.assign(uc.lpszUrlPath, uc.dwUrlPathLength);
64 if (uc.lpszExtraInfo && uc.dwExtraInfoLength)
65 out.
path.append(uc.lpszExtraInfo, uc.dwExtraInfoLength);
67 out.
isHttps = (uc.nScheme == INTERNET_SCHEME_HTTPS);
80 resp.
error =
"Failed to parse URL: " + url;
84 HINTERNET hSession = WinHttpOpen(L
"WoWModelViewer",
85 WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
86 WINHTTP_NO_PROXY_NAME,
87 WINHTTP_NO_PROXY_BYPASS,
92 resp.
error =
"WinHttpOpen failed";
97 DWORD optionFlags = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
98 WinHttpSetOption(hSession, WINHTTP_OPTION_REDIRECT_POLICY, &optionFlags,
sizeof(optionFlags));
100 HINTERNET hConnect = WinHttpConnect(hSession, parts.
host.c_str(), parts.
port, 0);
103 resp.
error =
"WinHttpConnect failed";
104 WinHttpCloseHandle(hSession);
108 const DWORD flags = parts.
isHttps ? WINHTTP_FLAG_SECURE : 0;
109 HINTERNET hRequest = WinHttpOpenRequest(hConnect, L
"GET",
110 parts.
path.c_str(),
nullptr,
112 WINHTTP_DEFAULT_ACCEPT_TYPES,
117 resp.
error =
"WinHttpOpenRequest failed";
118 WinHttpCloseHandle(hConnect);
119 WinHttpCloseHandle(hSession);
123 if (!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0,
124 WINHTTP_NO_REQUEST_DATA, 0, 0, 0))
126 resp.
error =
"WinHttpSendRequest failed";
127 WinHttpCloseHandle(hRequest);
128 WinHttpCloseHandle(hConnect);
129 WinHttpCloseHandle(hSession);
133 if (!WinHttpReceiveResponse(hRequest,
nullptr))
135 resp.
error =
"WinHttpReceiveResponse failed";
136 WinHttpCloseHandle(hRequest);
137 WinHttpCloseHandle(hConnect);
138 WinHttpCloseHandle(hSession);
143 DWORD statusCode = 0;
144 DWORD statusSize =
sizeof(statusCode);
145 WinHttpQueryHeaders(hRequest,
146 WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
147 WINHTTP_HEADER_NAME_BY_INDEX, &statusCode, &statusSize, WINHTTP_NO_HEADER_INDEX);
148 resp.
statusCode =
static_cast<int>(statusCode);
151 size_t totalBytes = 0;
154 DWORD clSize =
sizeof(clBuf);
155 if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CONTENT_LENGTH,
156 WINHTTP_HEADER_NAME_BY_INDEX, clBuf, &clSize, WINHTTP_NO_HEADER_INDEX))
158 totalBytes =
static_cast<size_t>(_wtoi64(clBuf));
163 std::vector<char> buffer;
165 DWORD bytesAvailable = 0;
166 while (WinHttpQueryDataAvailable(hRequest, &bytesAvailable) && bytesAvailable > 0)
168 buffer.resize(bytesAvailable);
170 if (WinHttpReadData(hRequest, buffer.data(), bytesAvailable, &bytesRead))
172 resp.
body.append(buffer.data(), bytesRead);
173 received += bytesRead;
175 progress(received, totalBytes);
179 WinHttpCloseHandle(hRequest);
180 WinHttpCloseHandle(hConnect);
181 WinHttpCloseHandle(hSession);