Package: lowhaio
lowhaioA lightweight Python asyncio HTTP/1.1 client. No additional tasks are created; all code is in a single module; and other than the standard library only a single dependency is required,aiodnsresolverLowhaio has a deliberately limited scope: it includes just enough code to be a useful HTTP client and allow more complex behaviour to be added on top if required.Connections are DNS-aware, in that they are only re-used if they match a current A record for the domain.InstallationpipinstalllowhaioUsageThe API is streaming-first: for both request and response bodies, asynchronous iterators are used.importasynciofromlowhaioimportPoolasyncdefmain():request,close=Pool()asyncdefrequest_body():yieldb'a'yieldb'bc'code,headers,response_body=awaitrequest(b'POST','https://postman-echo.com/post',headers=((b'content-length',b'3'),(b'content-type',b'text/plain'),),body=request_body,)asyncforchunkinresponse_body:print(chunk)awaitclose()loop=asyncio.get_event_loop()loop.run_until_complete(main())However, there are helper functionsstreamedandbufferedwhen this isn't required or possible.importasynciofromlowhaioimportPool,streamed,bufferedasyncdefmain():request,close=Pool()request_body=streamed(b'abc')code,headers,response_body=awaitrequest(b'POST','https://postman-echo.com/post',headers=((b'content-length',b'3'),(b'content-type',b'text/plain'),),body=request_body,)print(awaitbuffered(response_body))awaitclose()loop=asyncio.get_event_loop()loop.run_until_complete(main())HeadersThe only header automatically added to requests is thehostheader, which is the idna/punycode-encoded domain name from the requested URL.ExceptionsExceptions are usually subclasses ofHttpError. If a lower-level exception caused this, it is set in the__cause__attribute of theHttpError. Specifically, before any data is sentHttpConnectionErroris raised, and after data is sent,HttpDataErroris raised. This difference is to make it possible to know if non-idempotent requests can be retried.However,asyncio.CancelledErrorand exceptions that do not directive fromException, such asSystemExit, are allowed to bubble up.Custom SSL contextLowhaio can be used with an custom SSL context through through theget_ssl_contextparameter toPool. For example, to use the certifi CA bundle, you can install it bypipinstallcertifiand use it as below.importasyncioimportsslimportcertififromlowhaioimportPool,buffered,streamedasyncdefmain():request,close=Pool(get_ssl_context=lambda:ssl.create_default_context(cafile=certifi.where()),)request_body=streamed(b'abc')code,headers,response_body=awaitrequest(b'POST','https://postman-echo.com/post',headers=((b'content-length',b'3'),(b'content-type',b'text/plain'),),body=request_body,)print(awaitbuffered(response_body))awaitclose()loop=asyncio.get_event_loop()loop.run_until_complete(main())ScopeThe scope of the core functions is restricted to:(TLS) connection opening, closing and pooling;passing and receiving HTTP headers and streaming bodies;decoding chunked responses;raising exceptions on timeouts.This is to make the core behaviour useful to a reasonable range of uses, but tonotinclude what can be added by layer(s) on top. Specifically not included:following redirects, implemented bylowhaio-redirect;retrying failed requests, implemented bylowhaio-retry;encoding chunked requests, implemented bylowhaio-chunked;authentication, such as AWS Signature Version 4 implemented bylowhaio-aws-sigv4, or AWS Signature Version 4 with unsigned payload implemented bylowhaio-aws-sigv4-unsigned-payload;compressing/decompressing requests/responses;cookies.