New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added proxy parameters for ClientSession #2582
Conversation
Any test? |
@asvetlov OK, the code is very simple, but there is something different.
But actually it's not working, even value of Something went wrong, so I tested another example:
This time the proxy was not used, so I guess first request of session decided proxy of whole session and can not be changed? Emmmmmm... BTW, if you don't like the I will added tests soon. |
Design thoughts.
Maybe we need multiple proxies support too? |
@asvetlov class ProxySwitchHandler:
def choose_proxy(self, url):
# ...
return 'foo.bar:3128' |
@asvetlov I'm not sure async def test_session_proxy_http_headers(proxy_test_server, loop):
url = 'http://aiohttp.io/path'
proxy = await proxy_test_server()
conn = aiohttp.TCPConnector(loop=loop)
sess = aiohttp.ClientSession(connector=conn, loop=loop, proxy=proxy.url)
await sess.get(url)
assert 'ProxyFlag' not in proxy.request.headers
conn = aiohttp.TCPConnector(loop=loop)
sess = aiohttp.ClientSession(connector=conn, loop=loop, proxy=proxy.url, proxy_headers={'ProxyFlag': '1'})
await sess.get(url)
assert 'ProxyFlag' in proxy.request.headers |
Codecov Report
@@ Coverage Diff @@
## master #2582 +/- ##
=======================================
Coverage 97.71% 97.71%
=======================================
Files 36 36
Lines 7229 7229
Branches 1262 1262
=======================================
Hits 7064 7064
Misses 58 58
Partials 107 107 Continue to review full report at Codecov.
|
Very often the session uses two different proxies: one for HTTP and other for HTTPS. @aio-libs/aiohttp-committers please share your opinions. |
Very often? I don't think so. Use dict means no code completion and limited ability, so I prefer to a class. Or just support change proxy during the session, then add another api to set |
The mine idea is: specify proxies and do any requests over the session.
Evolving your idea I can say that you don't need to pass proxy info into constructor at all: just provide corresponding proxy parameters for every HTTP request. |
Actually I wrote some code like that: def new_session(connector=None, cookie_jar=None, cookies=None, headers=None):
# set cookies, headers, timeout, etc.
cookie_jar = cookie_jar if cookie_jar else CookieJar(unsafe=True)
return ClientSession(conn_timeout=5, read_timeout=10, connector=connector, cookie_jar=cookie_jar, cookies=cookies, headers=headers)
# `new_session` used by hundreds of files
async def fetch():
async with new_session(headers=get_headers()) as session:
async with session.post('http://xxxx', data=data) as resp:
text = await resp.text() Obviously modify global settings is much better than rewrite hundreds of local settings. I thought keep simple and flexible is very important: We just write general code for general case, it can easily works. If we need more, after add options or do something, it still works for unusual cases. My suggestion: sess = ClientSession(proxy='http/https/socks://...')
sess.set_proxy('http/https/socks://...')
proxy: [str, ProxyProvider]
class ProxyProvider: # Provider/Feeder/Switcher ...
def pick(self, sess, url, method):
return { headers: {}, url: {}, auth: {} }
class OSEnvProxyProvider(ProxyProvider):
def __init__(self):
self.http = read_from_env('http_proxy')
self.https = read_from_env('https_proxy')
def pick(...):
ret = url_parse ...
if ret.schema == 'http': return self.http
if ret.schema == 'https': return self.https
class SimpleProxyProvider(ProxyProvider):
def __init__(url, auth, headers):
self.default = {...}
def pick(...):
return self.default |
already 10 days |
My main objection is that session constructor is complicated already, with PR it becomes even more complicated. |
I agree with @asvetlov . Personally, I see proxy configuration as a sort of middleware for sessions. Could it be implemented in such fashion? Something like:
A bit more code to write, but proxy thing becomes completely decoupled from session one. Thoughts? |
I liked the first idea: async with ClientSession(proxy=proxy) as session:
async with session.get('http://test.com') as resp:
print(await resp.text()) Simple to use, optional to use... Sounds cool. But then @asvetlov made a good point about having multiple proxies. About the alternatives: session.set_proxy(....) Yes I agree with @asvetlov that this will introduce a state to the application. Imagine you run 2 HTTP calls using 2 different proxies in parallel (asynchronously), you don't know what's going to happen. session = ClientSession(...)
session = ProxySession(session, auth=..., headers=...) It looks awful to use, sorry @kxepal 😁 Now why not having a proxy object that actually has all the information to connect using any scheme and the headers to use, etc...? So you merge You can still write this: async with ClientSession(proxy=proxy) as session:
async with session.get('http://test.com') as resp:
print(await resp.text()) But you need to create first your proxy object: proxy = Proxy(http="some_url", http_headers={...}, http_auth=("user", "pass"),
https="other_url", ...)
# or
proxy = Proxy(all="some_url", all_headers={...}, all_auth=("user", "pass")) |
I like @kxepal idea. but in slightly different way proxy = Proxy(...)
async def main():
with proxy.with(ClientSession()).get(url='') as resp:
... |
I think @cecton idea about Actual implementation of proxy support is not so flexible, some issues are:
With separate Using
I can imagine even In this design more advanced proxy use can be easily implemented like e.g. |
It seems Travis has forgotten about this PR, I can send a new after resolving the merge conflict. |
@RatanShreshtha Travis CI didn't forget about it. It's just that it has |
It's really a long time. Since the pr was sent, I was busied with works for some days. It's about two months later when I was free, and I nearly forgot it. I thought it's must be someone solved the problem in these two months, so my PR was already finished. One year past, there still no proxy api for ClientSession, really? I must say origin PR is too simple, api about proxies must be redesigned. |
@fy0 are you working on new PR ? |
@RatanShreshtha No, not now. I suggest that you could use a temporary local patch if you are in a hurry. Even if someone works on it today, merged can not be so quickly. |
@fy0 Should I send a new PR with your changes after resolving the merge conflicts? |
@RatanShreshtha OK, of course. |
Overtaken #3405 |
What do these changes do?
Added proxy parameters for ClientSession
Are there changes in behavior for the user?
New parameters of ClientSession():
Related issue number
#2580
Checklist
CONTRIBUTORS.txt
CHANGES
folder<issue_id>.<type>
for example (588.bug)issue_id
change it to the pr id after creating the pr.feature
: Signifying a new feature..bugfix
: Signifying a bug fix..doc
: Signifying a documentation improvement..removal
: Signifying a deprecation or removal of public API..misc
: A ticket has been closed, but it is not of interest to users.