-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Urequests updates #500
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
Urequests updates #500
Conversation
c2d4661 to
0300b45
Compare
python-ecosys/urequests/urequests.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the socket always closed correctly? Should we use a context manager to control the lifetime of the socket?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how this should be handled to be honest. It needs to be left open at the return of the request() function as the caller will generally read the content later.
The Response() object has the close function, it probably should be updated with enter and exit so it can be used as a context manager the same as in cpython requests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ref: #278
python-ecosys/urequests/metadata.txt
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems a more significant that a patch release.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah yep, this came in with one of the branches, I'll filter it back out into a new commit to update the overall version
python-ecosys/urequests/urequests.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is neat but does make me think that we should have at least some documentation (since it's not that obvious). I'll pull together a README, or at least suggestions what should be in it.
Basic auth appears to work correctly 👍 :
>>> import urequests >>> r = urequests.get('http://httpbin.org/basic-auth/user/pass', auth=('user', 'pass')) >>> r.status_code 200 >>> r.text '{\n "authenticated": true, \n "user": "user"\n}\n'
>>> r = urequests.get('http://httpbin.org/basic-auth/user/pass', auth=('user', 'fail')) >>> r.status_code 401
We should probably also make accessing headers case insensitive to match requests. It's inexpensive and will make documenting easier.
ff5190f to
22e4f23
Compare
We should probably also make accessing headers case insensitive to match requests. It's inexpensive and will make documenting easier.
I'm not too sure just how inexpensive it is to be honest.... it depends on how far you want to take it: https://stackoverflow.com/questions/2082152/case-insensitive-dictionary
One of the more basic versions from here would likely be fine though.
d5dc912 to
e33d845
Compare
Tested redirects (GET google.com generates a 301) and basic auth on the unix port (in the published v1.19 container). Tested with and without SSL. All good! ✔️
> # pwd is a clone of micropython-lib with this PR active (gh pr checkout 500) > docker run -ti --rm -v $(pwd):/code -w /code micropython/unix bash -c 'MICROPYPATH="python-ecosys/urequests" micropython-dev' MicroPython v1.19-dirty on 2022年06月16日; linux [GCC 8.3.0] version Use Ctrl-D to exit, Ctrl-E for paste mode >>> import urequests >>> urequests.get("http://google.com").status_code 200 >>> urequests.get("https://google.com").status_code 200 >>> urequests.get('http://httpbin.org/basic-auth/user/pass', auth=('user', 'pass')).status_code 200 >>> urequests.get('https://httpbin.org/basic-auth/user/pass', auth=('user', 'pass')).status_code 200 >>> urequests.get('https://httpbin.org/basic-auth/user/pass', auth=('user', 'fail')).status_code 401
Timeouts look good too, though a different exception is raised to requests. It could be a good idea to raise the same requests.exceptions.ReadTimeout so that code can be ported more easily? Certainly not urgent.
>>> # httpstat.us can be configured to delay for a sleep period in milliseconds. requests timeout is in seconds. >>> r = urequests.get('http://httpstat.us/200?sleep=5000', timeout=1) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "python-ecosys/urequests/urequests.py", line 176, in get File "python-ecosys/urequests/urequests.py", line 121, in request OSError: [Errno 110] ETIMEDOUT
> python Python 3.8.10 (default, Mar 15 2022, 12:22:08) [GCC 9.4.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import requests >>> r = requests.get('http://httpstat.us/200?sleep=5000', timeout=1) Traceback (most recent call last): File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 421, in _make_request six.raise_from(e, None) File "<string>", line 3, in raise_from File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 416, in _make_request httplib_response = conn.getresponse() File "/usr/lib/python3.8/http/client.py", line 1348, in getresponse response.begin() File "/usr/lib/python3.8/http/client.py", line 316, in begin version, status, reason = self._read_status() File "/usr/lib/python3.8/http/client.py", line 277, in _read_status line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1") File "/usr/lib/python3.8/socket.py", line 669, in readinto return self._sock.recv_into(b) socket.timeout: timed out During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/usr/lib/python3/dist-packages/requests/adapters.py", line 439, in send resp = conn.urlopen( File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 719, in urlopen retries = retries.increment( File "/usr/lib/python3/dist-packages/urllib3/util/retry.py", line 400, in increment raise six.reraise(type(error), error, _stacktrace) File "/usr/lib/python3/dist-packages/six.py", line 703, in reraise raise value File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 665, in urlopen httplib_response = self._make_request( File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 423, in _make_request self._raise_timeout(err=e, url=url, timeout_value=read_timeout) File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 330, in _raise_timeout raise ReadTimeoutError( urllib3.exceptions.ReadTimeoutError: HTTPConnectionPool(host='httpstat.us', port=80): Read timed out. (read timeout=1) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python3/dist-packages/requests/api.py", line 75, in get return request('get', url, params=params, **kwargs) File "/usr/lib/python3/dist-packages/requests/api.py", line 60, in request return session.request(method=method, url=url, **kwargs) File "/usr/lib/python3/dist-packages/requests/sessions.py", line 533, in request resp = self.send(prep, **send_kwargs) File "/usr/lib/python3/dist-packages/requests/sessions.py", line 646, in send r = adapter.send(request, **kwargs) File "/usr/lib/python3/dist-packages/requests/adapters.py", line 529, in send raise ReadTimeout(e, request=request) requests.exceptions.ReadTimeout: HTTPConnectionPool(host='httpstat.us', port=80): Read timed out. (read timeout=1)
I think OSError(ETIMEDOUT) is good enough for now (and maybe good enough forever!).
python-ecosys/urequests/urequests.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this need to be a separate function? It would be more efficient and smaller bytecode if it were inlined at its point of use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minimising the overhead of extra functions is a good goal. I've done this here as well as the is_chunked_data() one.
python-ecosys/urequests/urequests.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use str(..., "ascii") instead of decode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, fixed here as well as one other usage of decode in a different commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change doesn't seem to have anything to do with urequests, but otherwise it's OK to have here (it's a separate commit, which is good).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I'd thought it was related - was in the same original PR as the redirect/chunked change. Can confirm it was not actually used there, though looks like a clean change anyway.
python-ecosys/urequests/urequests.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this need to be a separate function? Smaller code if it's not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inlined now
python-ecosys/urequests/urequests.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use str(..., "utf-8").
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done thanks
python-ecosys/urequests/urequests.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use str(..., "utf-8")
python-ecosys/urequests/urequests.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it makes sense to convert the error string. It'll already raise a sensible message.
e33d845 to
537bd45
Compare
This is controlled by parse_headers param to request(), which defaults to True for compatibility with upstream requests. In this case, headers are available as .headers of Response objects. They are however normal (not case-insensitive) dict. If parse_headers=False, old behavior of ignore response headers is used, which saves memory on the dict. Finally, parse_headers can be a custom function which can e.g. parse only subset of headers (again, to save memory).
Even though we use HTTP 1.0, where closing connection after sending response should be the default, some servers ignore this requirement and keep connection open. So, explicitly send corresponding header to get the expected behavior. This follow a similar change done previosuly to uaiohttpclient module (8c1e077).
Would lead to recursive TypeError because of str + bytes.
Usage matches the shorthand version described in https://requests.readthedocs.io/en/latest/user/authentication/#basic-authentication
On the ESP32, socket.getaddrinfo() might return SOCK_DGRAM instead of SOCK_STREAM, eg with ".local" adresses. As a HTTP request is always a TCP stream, we don't need to rely on the values returned by getaddrinfo.
537bd45 to
be094ae
Compare
I think
OSError(ETIMEDOUT)is good enough for now (and maybe good enough forever!).
For now, for sure. Forever? Not so convinced... 😛 Two reasons: a) It makes it harder to port libraries that have error handling expecting that exception and b) That's quite a general exception for an error condition that's very specific.
Anyway, I agree it's unimportant...for now!
Thanks @andrewleech! LGTM
Uh oh!
There was an error while loading. Please reload this page.
In the spirit of #488 I've started to pull together a number of updates to the
urequestslibrary. So far I haven't contributed any new features myself, simply rebased (past the restructuring), merged together and applied black to all commits.Inspired by a similar change in pycopy, but updated to be more compatible. Also closes #394
From #398 (Note I manually split this into the two separate urequest commits)
See: https://docs.python.org/3/library/binascii.html#binascii.b2a_base64
From #311
Usage matches the shorthand version described in
https://requests.readthedocs.io/en/latest/user/authentication/#basic-authentication
From: #469
Inspired by: #276:
From #263:
From pycopy:
For reference, the rebase & black on each branch (pre-merge) has been done in a single command:
Testing TBD - none of the above commits include any unit tests.