Skip to content

Commit 14bd587

Browse files
committed
Adds manual proxy handling for WinHTTP
1 parent 60c7c55 commit 14bd587

File tree

1 file changed

+67
-4
lines changed

1 file changed

+67
-4
lines changed

src/_native/winhttp.cpp

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,69 @@ static int crack_url(wchar_t *url, URL_COMPONENTS *parts, int add_nuls) {
150150

151151
extern "C" {
152152

153+
#define CHECK_WINHTTP(x) if (!x) { winhttp_error(); goto exit; }
154+
155+
156+
static bool winhttp_apply_proxy(HINTERNET hSession, HINTERNET hRequest, const wchar_t *url) {
157+
bool result = false;
158+
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxy_config = { 0 };
159+
WINHTTP_AUTOPROXY_OPTIONS proxy_opt = {
160+
.dwFlags = WINHTTP_AUTOPROXY_ALLOW_STATIC,
161+
.fAutoLogonIfChallenged = TRUE
162+
};
163+
WINHTTP_PROXY_INFO proxy_info = { 0 };
164+
165+
// First load the global-ish config settings
166+
if (!WinHttpGetIEProxyConfigForCurrentUser(&proxy_config)) {
167+
if (GetLastError() != ERROR_FILE_NOT_FOUND) {
168+
goto exit;
169+
}
170+
// No global config, so assume auto-detect
171+
proxy_config.lpszProxy = proxy_config.lpszProxyBypass = proxy_config.lpszAutoConfigUrl = NULL;
172+
proxy_config.fAutoDetect = TRUE;
173+
}
174+
if (proxy_config.lpszProxy) {
175+
GlobalFree(proxy_config.lpszProxy);
176+
}
177+
if (proxy_config.lpszProxyBypass) {
178+
GlobalFree(proxy_config.lpszProxyBypass);
179+
}
180+
if (proxy_config.fAutoDetect) {
181+
proxy_opt.dwFlags |= WINHTTP_AUTOPROXY_AUTO_DETECT;
182+
proxy_opt.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP
183+
| WINHTTP_AUTO_DETECT_TYPE_DNS_A;
184+
}
185+
if (proxy_config.lpszAutoConfigUrl) {
186+
proxy_opt.dwFlags |= WINHTTP_AUTOPROXY_CONFIG_URL;
187+
proxy_opt.lpszAutoConfigUrl = proxy_config.lpszAutoConfigUrl;
188+
}
189+
190+
// Now resolve the proxy required for the specified URL
191+
CHECK_WINHTTP(WinHttpGetProxyForUrl(hSession, url, &proxy_opt, &proxy_info));
192+
193+
// Apply the proxy settings to the request
194+
CHECK_WINHTTP(WinHttpSetOption(
195+
hRequest,
196+
WINHTTP_OPTION_PROXY,
197+
&proxy_info,
198+
sizeof(proxy_info)
199+
));
200+
201+
result = true;
202+
exit:
203+
if (proxy_info.lpszProxy) {
204+
GlobalFree((HGLOBAL)proxy_info.lpszProxy);
205+
}
206+
if (proxy_info.lpszProxyBypass) {
207+
GlobalFree((HGLOBAL)proxy_info.lpszProxyBypass);
208+
}
209+
if (proxy_opt.lpszAutoConfigUrl) {
210+
GlobalFree((HGLOBAL)proxy_opt.lpszAutoConfigUrl);
211+
}
212+
return result;
213+
}
214+
215+
153216
PyObject *winhttp_urlopen(PyObject *, PyObject *args, PyObject *kwargs) {
154217
static const char * keywords[] = {"url", "method", "headers", "accepts", "chunksize", "on_progress", "on_cred_request", NULL};
155218
wchar_t *url = NULL;
@@ -202,11 +265,9 @@ PyObject *winhttp_urlopen(PyObject *, PyObject *args, PyObject *kwargs) {
202265
goto exit;
203266
}
204267

205-
#define CHECK_WINHTTP(x) if (!x) { winhttp_error(); goto exit; }
206-
207268
hSession = WinHttpOpen(
208269
NULL,
209-
WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY,
270+
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
210271
WINHTTP_NO_PROXY_NAME,
211272
WINHTTP_NO_PROXY_BYPASS,
212273
url_parts.nScheme == INTERNET_SCHEME_HTTPS
@@ -218,7 +279,7 @@ PyObject *winhttp_urlopen(PyObject *, PyObject *args, PyObject *kwargs) {
218279
// retry without it.
219280
hSession = WinHttpOpen(
220281
NULL,
221-
WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY,
282+
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
222283
WINHTTP_NO_PROXY_NAME,
223284
WINHTTP_NO_PROXY_BYPASS,
224285
0
@@ -248,6 +309,8 @@ PyObject *winhttp_urlopen(PyObject *, PyObject *args, PyObject *kwargs) {
248309
);
249310
CHECK_WINHTTP(hRequest);
250311

312+
CHECK_WINHTTP(winhttp_apply_proxy(hSession, hRequest, url));
313+
251314
opt = WINHTTP_DECOMPRESSION_FLAG_ALL;
252315
CHECK_WINHTTP(WinHttpSetOption(
253316
hRequest,

0 commit comments

Comments
 (0)