From 3e8c3096f58c0cb2a2aa7fa50474162e9e1563ce Mon Sep 17 00:00:00 2001 From: Mirko Vogt Date: Wed, 29 May 2024 06:34:42 +0000 Subject: [PATCH] uaiohttpclient: Implement parsing and handling HTTP auth URLs Allows HTTP Basic Auth URLs being passed, parsed and handled correctly to authorise against a server expecting that. This is a simplification, completely ignoring if the server supports or asks for HTTP Basic Auth. We simply format and set the header if the URL indicates so. This also fixes parsing URLs containing a colon (':') /not/ indicating a custom port (but e.g. the seperation between user and password as part of the HTTP Basic Auth credentials). Previously, the lib died ungracefully when parsing an URL containing HTTP Basic Auth credentials, as it was always expecting at most only one colon (':') and also the part coming afterwards being neccesarily a number (port). --- micropython/uaiohttpclient/uaiohttpclient.py | 24 ++++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/micropython/uaiohttpclient/uaiohttpclient.py b/micropython/uaiohttpclient/uaiohttpclient.py index 6347c3371..640d08d9a 100644 --- a/micropython/uaiohttpclient/uaiohttpclient.py +++ b/micropython/uaiohttpclient/uaiohttpclient.py @@ -47,8 +47,19 @@ async def request_raw(method, url): proto, dummy, host = url.split("/", 2) path = "" + # Although we use HTTP protocol version 1.0, we still explicitly + # set the header "Connection: close", even though this should be + # default for 1.0, but some servers misbehave w/o it. + hdrs = {'Connection': "close", 'User-Agent': "compat"} + if "@" in host: + # split off potential login creds from host + auth, host = host.split("@", 1) + from binascii import b2a_base64 + #usr, pwd = auth.split(":", 1) + hdrs['Authorization'] = "Basic " + b2a_base64(auth).decode() + if ":" in host: - host, port = host.split(":") + host, port = host.rsplit(":", 1) port = int(port) else: port = 80 @@ -56,15 +67,8 @@ async def request_raw(method, url): if proto != "http:": raise ValueError("Unsupported protocol: " + proto) reader, writer = await asyncio.open_connection(host, port) - # Use protocol 1.0, because 1.1 always allows to use chunked - # transfer-encoding But explicitly set Connection: close, even - # though this should be default for 1.0, because some servers - # misbehave w/o it. - query = "%s /%s HTTP/1.0\r\nHost: %s\r\nConnection: close\r\nUser-Agent: compat\r\n\r\n" % ( - method, - path, - host, - ) + # Use protocol 1.0, because 1.1 always allows to use chunked transfer-encoding + query = "%s /%s HTTP/1.0\r\nHost: %s\r\n%s\r\n\r\n" % (method, path, host, "\r\n".join("%s: %s" % (k,v) for k,v in hdrs.items())) await writer.awrite(query.encode("latin-1")) return reader