codekingpro/portable-devtools
114k
1"""This module documents the minimal http behaviors used by this package.2 3Its interface is influenced by, and similar to a subset of some popular,4real-world http libraries, such as requests, aiohttp and httpx.5"""6 7 8class HttpClient(object):9 """This describes a minimal http request interface used by this package."""10 11 def post(self, url, params=None, data=None, headers=None, **kwargs):12 """HTTP post.13 14 :param dict params: A dict to be url-encoded and sent as query-string.15 :param dict headers: A dict representing headers to be sent via request.16 :param data:17 Implementation needs to support 2 types.18 19 * A dict, which will need to be urlencode() before being sent.20 * (Recommended) A string, which will be sent in request as-is.21 22 It returns an :class:`~Response`-like object.23 24 Note: In its async counterpart, this method would be defined as async.25 """26 return Response()27 28 def get(self, url, params=None, headers=None, **kwargs):29 """HTTP get.30 31 :param dict params: A dict to be url-encoded and sent as query-string.32 :param dict headers: A dict representing headers to be sent via request.33 34 It returns an :class:`~Response`-like object.35 36 Note: In its async counterpart, this method would be defined as async.37 """38 return Response()39 40 41class Response(object):42 """This describes a minimal http response interface used by this package.43 44 :var int status_code:45 The status code of this http response.46 47 Our async code path would also accept an alias as "status".48 49 :var string text:50 The body of this http response.51 52 Our async code path would also accept an awaitable with the same name.53 """54 status_code = 200 # Our async code path would also accept a name as "status"55 56 text = "body as a string" # Our async code path would also accept an awaitable57 # We could define a json() method instead of a text property/method,58 # but a `text` would be more generic,59 # when downstream packages would potentially access some XML endpoints.60 61 headers = {} # Duplicated headers are expected to be combined into one header62 # with its value as a comma-separated string.63 # https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.264 # Popular HTTP libraries model it as a case-insensitive dict.65 66 def raise_for_status(self):67 """Raise an exception when http response status contains error"""68 raise NotImplementedError("Your implementation should provide this")69 70 71def _get_status_code(resp):72 # RFC defines and some libraries use "status_code", others use "status"73 return getattr(resp, "status_code", None) or resp.status74 75 