From 5854ae1286af2d06e61feea65cfe11a352506dc6 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sun, 5 Aug 2018 13:27:18 +0300 Subject: [PATCH 01/11] urequests: Add ability to parse response headers. 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). --- python-ecosys/urequests/urequests.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/python-ecosys/urequests/urequests.py b/python-ecosys/urequests/urequests.py index 75a145702..1dc379bcf 100644 --- a/python-ecosys/urequests/urequests.py +++ b/python-ecosys/urequests/urequests.py @@ -33,7 +33,7 @@ def json(self): return ujson.loads(self.content) -def request(method, url, data=None, json=None, headers={}, stream=None): +def request(method, url, data=None, json=None, headers={}, stream=None, parse_headers=True): try: proto, dummy, host, path = url.split("/", 3) except ValueError: @@ -55,6 +55,10 @@ def request(method, url, data=None, json=None, headers={}, stream=None): ai = usocket.getaddrinfo(host, port, 0, usocket.SOCK_STREAM) ai = ai[0] + resp_d = None + if parse_headers is not False: + resp_d = {} + s = usocket.socket(ai[0], ai[1], ai[2]) try: s.connect(ai[-1]) @@ -98,6 +102,14 @@ def request(method, url, data=None, json=None, headers={}, stream=None): raise ValueError("Unsupported " + l) elif l.startswith(b"Location:") and not 200 <= status <= 299: raise NotImplementedError("Redirects not yet supported") + if parse_headers is False: + pass + elif parse_headers is True: + l = str(l, "utf-8") + k, v = l.split(":", 1) + resp_d[k] = v.strip() + else: + parse_headers(l, resp_d) except OSError: s.close() raise @@ -105,6 +117,8 @@ def request(method, url, data=None, json=None, headers={}, stream=None): resp = Response(s) resp.status_code = status resp.reason = reason + if resp_d is not None: + resp.headers = resp_d return resp From 924c207f8064f5408a3c0e7674ec99ee9b3650a9 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Fri, 10 Aug 2018 07:41:54 +0300 Subject: [PATCH 02/11] urequests: Explicitly add "Connection: close" to request headers. 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 (8c1e077fc0cd). --- python-ecosys/urequests/urequests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python-ecosys/urequests/urequests.py b/python-ecosys/urequests/urequests.py index 1dc379bcf..4aa2935c7 100644 --- a/python-ecosys/urequests/urequests.py +++ b/python-ecosys/urequests/urequests.py @@ -81,7 +81,7 @@ def request(method, url, data=None, json=None, headers={}, stream=None, parse_he s.write(b"Content-Type: application/json\r\n") if data: s.write(b"Content-Length: %d\r\n" % len(data)) - s.write(b"\r\n") + s.write(b"Connection: close\r\n\r\n") if data: s.write(data) From 32eb7bca44544f201292acf7cac0a8e9ef7a61d0 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Sat, 7 Mar 2020 16:16:39 +0200 Subject: [PATCH 03/11] urequests: Fix raising unsupported Transfer-Encoding exception. Would lead to recursive TypeError because of str + bytes. --- python-ecosys/urequests/urequests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python-ecosys/urequests/urequests.py b/python-ecosys/urequests/urequests.py index 4aa2935c7..11de10bbc 100644 --- a/python-ecosys/urequests/urequests.py +++ b/python-ecosys/urequests/urequests.py @@ -99,7 +99,7 @@ def request(method, url, data=None, json=None, headers={}, stream=None, parse_he # print(l) if l.startswith(b"Transfer-Encoding:"): if b"chunked" in l: - raise ValueError("Unsupported " + l) + raise ValueError("Unsupported " + str(l, "utf-8")) elif l.startswith(b"Location:") and not 200 <= status <= 299: raise NotImplementedError("Redirects not yet supported") if parse_headers is False: From b4a3329d501122b9bee41ce7e694c9fbf5a2c30e Mon Sep 17 00:00:00 2001 From: Fabian Schmitt Date: Tue, 28 Jun 2022 16:44:33 +1000 Subject: [PATCH 04/11] urequests: Added Basic Authentication support. Usage matches the shorthand version described in https://requests.readthedocs.io/en/latest/user/authentication/#basic-authentication --- python-ecosys/urequests/urequests.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/python-ecosys/urequests/urequests.py b/python-ecosys/urequests/urequests.py index 11de10bbc..3a69e0994 100644 --- a/python-ecosys/urequests/urequests.py +++ b/python-ecosys/urequests/urequests.py @@ -33,7 +33,17 @@ def json(self): return ujson.loads(self.content) -def request(method, url, data=None, json=None, headers={}, stream=None, parse_headers=True): +def request( + method, url, data=None, json=None, headers={}, stream=None, parse_headers=True, auth=None +): + if auth is not None: + import ubinascii + + username, password = auth + formated = b"{}:{}".format(username, password) + formated = str(ubinascii.b2a_base64(formated)[:-1], "ascii") + headers["Authorization"] = "Basic {}".format(formated) + try: proto, dummy, host, path = url.split("/", 3) except ValueError: @@ -144,3 +154,4 @@ def patch(url, **kw): def delete(url, **kw): return request("DELETE", url, **kw) + From 82a2afb2b48d066ff438a316213a102a97fe8620 Mon Sep 17 00:00:00 2001 From: Diefesson de Sousa SIlva Date: Mon, 5 Oct 2020 16:50:55 -0300 Subject: [PATCH 05/11] binascii: newline param in function b2a_base64 See: https://docs.python.org/3/library/binascii.html#binascii.b2a_base64 --- python-stdlib/binascii/binascii.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python-stdlib/binascii/binascii.py b/python-stdlib/binascii/binascii.py index 430b1132b..f2ec39e84 100644 --- a/python-stdlib/binascii/binascii.py +++ b/python-stdlib/binascii/binascii.py @@ -331,7 +331,7 @@ def a2b_base64(ascii): table_b2a_base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" -def b2a_base64(bin): +def b2a_base64(bin, newline=True): "Base64-code line of data." newlength = (len(bin) + 2) // 3 @@ -357,5 +357,6 @@ def b2a_base64(bin): elif leftbits == 4: res.append(table_b2a_base64[(leftchar & 0xF) << 2]) res.append(PAD) - res.append("\n") + if newline: + res.append("\n") return "".join(res).encode("ascii") From 1b8507d2d652b40ce80f376f594f95ec305d4e4b Mon Sep 17 00:00:00 2001 From: Diefesson de Sousa SIlva Date: Sun, 19 Jun 2022 09:58:14 +1000 Subject: [PATCH 06/11] urequests: Add support for requests with chunked upload data. --- python-ecosys/urequests/urequests.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/python-ecosys/urequests/urequests.py b/python-ecosys/urequests/urequests.py index 3a69e0994..61605f3b2 100644 --- a/python-ecosys/urequests/urequests.py +++ b/python-ecosys/urequests/urequests.py @@ -36,6 +36,8 @@ def json(self): def request( method, url, data=None, json=None, headers={}, stream=None, parse_headers=True, auth=None ): + chunked_data = data and getattr(data, "__iter__", None) and not getattr(data, "__len__", None) + if auth is not None: import ubinascii @@ -90,10 +92,20 @@ def request( data = ujson.dumps(json) s.write(b"Content-Type: application/json\r\n") if data: - s.write(b"Content-Length: %d\r\n" % len(data)) + if chunked_data: + s.write(b"Transfer-Encoding: chunked\r\n") + else: + s.write(b"Content-Length: %d\r\n" % len(data)) s.write(b"Connection: close\r\n\r\n") if data: - s.write(data) + if chunked_data: + for chunk in data: + s.write(b"%x\r\n" % len(chunk)) + s.write(chunk) + s.write(b"\r\n") + s.write("0\r\n\r\n") + else: + s.write(data) l = s.readline() # print(l) @@ -154,4 +166,3 @@ def patch(url, **kw): def delete(url, **kw): return request("DELETE", url, **kw) - From 5f48288b742703a0a0cb79236fbca7e1d38a67a2 Mon Sep 17 00:00:00 2001 From: Diefesson de Sousa SIlva Date: Sun, 19 Jun 2022 09:58:45 +1000 Subject: [PATCH 07/11] urequests: Added support for redirects. --- python-ecosys/urequests/urequests.py | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/python-ecosys/urequests/urequests.py b/python-ecosys/urequests/urequests.py index 61605f3b2..e52c6d2a2 100644 --- a/python-ecosys/urequests/urequests.py +++ b/python-ecosys/urequests/urequests.py @@ -36,6 +36,7 @@ def json(self): def request( method, url, data=None, json=None, headers={}, stream=None, parse_headers=True, auth=None ): + redirect = None # redirection url, None means no redirection chunked_data = data and getattr(data, "__iter__", None) and not getattr(data, "__len__", None) if auth is not None: @@ -123,7 +124,10 @@ def request( if b"chunked" in l: raise ValueError("Unsupported " + str(l, "utf-8")) elif l.startswith(b"Location:") and not 200 <= status <= 299: - raise NotImplementedError("Redirects not yet supported") + if status in [301, 302, 303, 307, 308]: + redirect = str(l[10:-2], "utf-8") + else: + raise NotImplementedError("Redirect %d not yet supported" % status) if parse_headers is False: pass elif parse_headers is True: @@ -136,12 +140,19 @@ def request( s.close() raise - resp = Response(s) - resp.status_code = status - resp.reason = reason - if resp_d is not None: - resp.headers = resp_d - return resp + if redirect: + s.close() + if status in [301, 302, 303]: + return request("GET", redirect, None, None, headers, stream) + else: + return request(method, redirect, data, json, headers, stream) + else: + resp = Response(s) + resp.status_code = status + resp.reason = reason + if resp_d is not None: + resp.headers = resp_d + return resp def head(url, **kw): From b07b2f4c544c97b1a6cec5c232d732df81089fa8 Mon Sep 17 00:00:00 2001 From: karfas Date: Sat, 27 Nov 2021 12:01:55 +0100 Subject: [PATCH 08/11] urequests: Always open sockets in SOCK_STREAM mode. 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. --- python-ecosys/urequests/urequests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python-ecosys/urequests/urequests.py b/python-ecosys/urequests/urequests.py index e52c6d2a2..eb33e2618 100644 --- a/python-ecosys/urequests/urequests.py +++ b/python-ecosys/urequests/urequests.py @@ -72,7 +72,7 @@ def request( if parse_headers is not False: resp_d = {} - s = usocket.socket(ai[0], ai[1], ai[2]) + s = usocket.socket(ai[0], usocket.SOCK_STREAM, ai[2]) try: s.connect(ai[-1]) if proto == "https:": From fa9c8523bec409b1e4feb1ab76a0e37a88a7bf31 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 20 Jun 2022 13:11:35 +1000 Subject: [PATCH 09/11] urequests: Provide error message when server doesn't respond with valid http. --- python-ecosys/urequests/urequests.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/python-ecosys/urequests/urequests.py b/python-ecosys/urequests/urequests.py index eb33e2618..42e912977 100644 --- a/python-ecosys/urequests/urequests.py +++ b/python-ecosys/urequests/urequests.py @@ -111,6 +111,9 @@ def request( l = s.readline() # print(l) l = l.split(None, 2) + if len(l) < 2: + # Invalid response + raise ValueError("HTTP error: BadStatusLine:\n%s" % l) status = int(l[1]) reason = "" if len(l) > 2: From c7e90c4a0966f9967c34f127987f8e1faf1821f1 Mon Sep 17 00:00:00 2001 From: Bogdan Date: Sun, 18 Mar 2018 12:51:38 +0200 Subject: [PATCH 10/11] urequests: Add timeout, passed to underlying socket if supported. --- python-ecosys/urequests/urequests.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/python-ecosys/urequests/urequests.py b/python-ecosys/urequests/urequests.py index 42e912977..e1998711d 100644 --- a/python-ecosys/urequests/urequests.py +++ b/python-ecosys/urequests/urequests.py @@ -34,7 +34,15 @@ def json(self): def request( - method, url, data=None, json=None, headers={}, stream=None, parse_headers=True, auth=None + method, + url, + data=None, + json=None, + headers={}, + stream=None, + auth=None, + timeout=None, + parse_headers=True, ): redirect = None # redirection url, None means no redirection chunked_data = data and getattr(data, "__iter__", None) and not getattr(data, "__len__", None) @@ -73,6 +81,12 @@ def request( resp_d = {} s = usocket.socket(ai[0], usocket.SOCK_STREAM, ai[2]) + + if timeout is not None: + # Note: settimeout is not supported on all platforms, will raise + # an AttributeError if not available. + s.settimeout(timeout) + try: s.connect(ai[-1]) if proto == "https:": From be094ae93a78eebd2c4fda62d6d0bc90f30f3645 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 20 Jun 2022 13:23:13 +1000 Subject: [PATCH 11/11] urequests: Release 0.7.0. --- python-ecosys/urequests/metadata.txt | 3 +-- python-ecosys/urequests/setup.py | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/python-ecosys/urequests/metadata.txt b/python-ecosys/urequests/metadata.txt index 8cd156c39..04861d96f 100644 --- a/python-ecosys/urequests/metadata.txt +++ b/python-ecosys/urequests/metadata.txt @@ -1,4 +1,3 @@ srctype = micropython-lib type = module -version = 0.6 -author = Paul Sokolovsky +version = 0.7.0 diff --git a/python-ecosys/urequests/setup.py b/python-ecosys/urequests/setup.py index 65ee5da8b..51f1158e0 100644 --- a/python-ecosys/urequests/setup.py +++ b/python-ecosys/urequests/setup.py @@ -10,11 +10,11 @@ setup( name="micropython-urequests", - version="0.6", + version="0.7", description="urequests module for MicroPython", long_description="This is a module reimplemented specifically for MicroPython standard library,\nwith efficient and lean design in mind. Note that this module is likely work\nin progress and likely supports just a subset of CPython's corresponding\nmodule. Please help with the development if you are interested in this\nmodule.", url="https://github.com/micropython/micropython-lib", - author="Paul Sokolovsky", + author="micropython-lib Developers", author_email="micro-python@googlegroups.com", maintainer="micropython-lib Developers", maintainer_email="micro-python@googlegroups.com", pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy