Introduction
=======
Service Request Helper is a Python library designed to abstract http requests with shared properties.
It contains minimal amount of external dependencies, and supports both sync and async modes of operation.
Installation
=========
Install locally via pip:
```commandline
pip install service-request-helper[sync]
```
or
```
pip install service-request-helper[async]
```
Basic usage
==========
Depending on the execution context (sync or async), some import statements will differ. For async requests,
the response must also be awaited:
Sync
------
```python
from servic_request_helper.syncs.clients import RequestHelper
from servic_request_helper.utils import MethodWrapper
api = MethodWrapper(RequestHelper(
host='https://example.com'
))
response = api.get('/example')
```
Async
------
```python
from servic_request_helper.asyncs.clients import RequestHelper
from servic_request_helper.utils import MethodWrapper
api = MethodWrapper(RequestHelper(
host='https://example.com'
))
async def main():
response = await api.get('/example')
```
Classes such as RequestHelper are doubled in _.syncs_ and _.asyncs_ subpackages. Such classes will be marked with
(sync/async) note in this documentation. They have the same name, same constructor
arguments and serve the same purpose. The only difference is in the execution context (sync or async).
All HTTP methods are exposed via the MethodWrapper instance methods:
- GET - .get
- POST - .post
- PUT - .put
- PATCH - .patch
- DELETE - .delete
- HEAD - .head
MethodWrapper constructor accepts RequestHelper (see the "RequestHelper class" section) instance as its one and
only argument, which contains shared properties for all http requests that will be made with the
given MethodWrapper instance.
RequestHelper class (sync/async)
=====
RequestHelper class contains settings that will be applied to each http request that will be made
with the corresponding MethodWrapper instance. Depending on the context (sync or async), RequestHelper can be imported
from _.asyncs_ subpackage for async requests or _.syncs_ subpackage for sync requests.
RequestHelper class constructor accepts the following required arguments:
- **host** - A host part of the url where each individual request will be sent
and the following optional arguments:
- **default_request_formatter** - A formatter applied to request query parameters and body, if any are provided,
before the request is sent. Can be overriden on per-request basis via _request_formatter_ kwarg
(see "Making HTTP requests" section). If not provided, the DefaultRequestFormatter instance is used (see "Request formatters" section).
- **default_response_formatter** - A formatter applied to response body, after the request is successfully completed.
Can be overriden on per-request basis via _response_formatter_ kwarg (see "Making HTTP requests" section).
If not provided, the FullResponseFormatter instance is used (see "Request formatters" section).
- **request_header_managers** - A list or tuple of header manager instances (see "Request header managers" section) for generating headers during request execution.
Each header manager corresponds to single header key:value pair sent with each individual request. An empty tuple is used by default.
- **default_response_error_builder** - A class, which maps unsuccessful response to error class by response status code
(see "Response error builder" section).
Request header managers
======
Request header managers provide additional request headers to the request before it is sent.
Each header manager must be an inheritor of the AbstractRequestHeaderManager class and implement .get_header_name()
and .get_header_value() methods. Method .get_header_name() provides header key and method .get_header_value()
provides header value.
During the request execution, any existing request headers will be supplemented by
headers retrieved from header managers passed to corresponding RequestHelper instance.
**Each header manager is responsible for one header only**.
Passing Authorization to http request
==========
Authorization is set via AuthByServiceHeaderManager (sync/async) request header manager instance, which is passed to
RequestHelper constructor as a member of the _request_header_managers_ list or tuple.
```python
from servic_request_helper.syncs.auth import AuthByServiceHeaderManager
from servic_request_helper.syncs.clients import RequestHelper
from servic_request_helper.utils import MethodWrapper
auth_manager = AuthByServiceHeaderManager(
host='https://example.com',
auth_uri='/auth/example',
credential={'login': '***', 'password': '***'},
access_token_field='accessToken',
)
api = MethodWrapper(RequestHelper(
host='https://example.com',
request_header_managers=[auth_manager],
))
```
AuthByServiceHeaderManager accepts the following required arguments:
- **host** - A host part of the url for authorization request
- **auth_uri** - A uri path component of the authorization endpoint url
- **credential** - A dict of authorization credentials, which is passed as request body to the authorization endpoint
and the following optional arguments:
- **access_token_field** - A name of the field in the response body of the authorization endpoint,
which contains the bearer token to be used for authorization for requests to the API. Default value is 'access_token'.
- **access_expire_at_field** - A name of the field in the response body of the authorization endpoint,
which contains the string representation of token expiry date and time. Default value is None.
- **datetime_converter** - A function to convert the string representation of token expiry date and time, retrieved
from the response body, to the python datetime object. Default value is datetime.fromisoformat.
Making HTTP requests
=======
All HTTP requests are made through the corresponding methods of the MethodWrapper instance. Each method has
the same set of required and optional arguments as its input:
Required arguments:
- **uri** - A uri path component of the endpoint url where the request will be sent
Optional arguments:
- **request_formatter** - An instance of the inheritor of AbstractRequestFormatter class. Used to format request query params
and body before the request is sent. Overrides _default_request_formatter_ of the RequestHelper.
- **response_formatter** - An instance of the inheritor of AbstractResponseFormatter class. Used to format response body
after successful response to the request. Overrides _default_response_formatter_ of the RequestHelper.
- **response_error_builder** - An instance of the inheritor of AbstractResponseErrorBuilder class. Used to map
unsuccessful response to error class by response status code. Overrides _default_response_error_builder_ of the
RequestHelper class.
- **params** - A dict of the query params to be sent with the request
- **data** - A dict to be added to request body. Either _data_ or _json_ argument can be set, not both.
- **json** - A dict to be added to request body in json format. Either _data_ or _json_ argument can be set, not both.
- **files** - A dict of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload.
``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')``
or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a string
defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers
to add for the file.
- **headers** - A dict of additional headers to add to headers generated by _request_header_managers_ of the
RequestHelper class.
- **\*\*kwargs** - Any additional keyword arguments to be passed to underlying request method.
All optional arguments are None by default.
Request formatters
======
Request formatters are used to modify request query params or body before the request is sent. Each request formatter
must inherit from AbstractRequestFormatter and implement _.format_ method, which accepts dict and must return dict.
Library provides the following request formatters:
- **DefaultRequestFormatter()** - Does not perform formatting on the data
- **CamelizeRequestFormatter()** - Transforms dict keys of the data to be formatted to camelCase
Response formatters (sync/async)
=======
Response formatters are used to modify response body after the successful execution of the request and before
it is returned to client. Each response formatter must inherit from AbstractResponseFormatter
and implement _.format_ method, which accepts response object and must return processed response body.
Async response object's methods must be awaited before they are returned to client.
Library provides the following response formatters for sync and async:
- **FullResponseFormatter()** - Does not perform formatting on the response, response object will be passed to client
- **JsonResponseFormatter()** - Retrieves json body of the response without modifying it
- **JsonDecamelizeResponseFormatter()** - Retrieves json body of the response with keys formatted to snake_notation
- **ContentResponseFormatter()** - Retrieves the file content of the response
Response error builder (sync/async)
=======
Response error builder is used to map unsuccessful response to relevant exception class by response status code and
raise its exception. Each response error builder must inherit from AbstractResponseErrorBuilder class and implement its
_build_error_ method, which accepts url, request method and response object, and raises suitable exception from .errors
module.
Async response object's methods must be awaited before they are returned to client.
Library provides the following response error builders for sync and async:
- **ResponseStatusErrorBuilder()** - Handles most common response status codes for unsuccessful requests
Raw data
{
"_id": null,
"home_page": "https://github.com/endpointuz/service-request-helper-lib",
"name": "service-request-helper",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": null,
"author": "ksinn",
"author_email": "ksinnd@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/57/47/da91c4dda68f3c400bca3da2786637a2a2f7c9a0bf65b9e233b70440cb0e/service-request-helper-1.0.0.tar.gz",
"platform": null,
"description": "Introduction\n=======\nService Request Helper is a Python library designed to abstract http requests with shared properties.\nIt contains minimal amount of external dependencies, and supports both sync and async modes of operation.\n\n\nInstallation\n=========\nInstall locally via pip:\n```commandline\npip install service-request-helper[sync]\n```\nor\n```\npip install service-request-helper[async]\n```\n\n\nBasic usage\n==========\nDepending on the execution context (sync or async), some import statements will differ. For async requests,\nthe response must also be awaited:\n\nSync\n------\n```python\nfrom servic_request_helper.syncs.clients import RequestHelper\nfrom servic_request_helper.utils import MethodWrapper\n\napi = MethodWrapper(RequestHelper(\n host='https://example.com'\n))\n\nresponse = api.get('/example')\n```\n\nAsync\n------\n```python\nfrom servic_request_helper.asyncs.clients import RequestHelper\nfrom servic_request_helper.utils import MethodWrapper\n\napi = MethodWrapper(RequestHelper(\n host='https://example.com'\n))\n\n\nasync def main():\n response = await api.get('/example')\n```\n\nClasses such as RequestHelper are doubled in _.syncs_ and _.asyncs_ subpackages. Such classes will be marked with\n(sync/async) note in this documentation. They have the same name, same constructor\narguments and serve the same purpose. The only difference is in the execution context (sync or async).\n\nAll HTTP methods are exposed via the MethodWrapper instance methods:\n- GET - .get\n- POST - .post\n- PUT - .put\n- PATCH - .patch\n- DELETE - .delete\n- HEAD - .head\n\nMethodWrapper constructor accepts RequestHelper (see the \"RequestHelper class\" section) instance as its one and\nonly argument, which contains shared properties for all http requests that will be made with the \ngiven MethodWrapper instance.\n\n\nRequestHelper class (sync/async)\n=====\nRequestHelper class contains settings that will be applied to each http request that will be made \nwith the corresponding MethodWrapper instance. Depending on the context (sync or async), RequestHelper can be imported\nfrom _.asyncs_ subpackage for async requests or _.syncs_ subpackage for sync requests.\n\nRequestHelper class constructor accepts the following required arguments:\n- **host** - A host part of the url where each individual request will be sent\n\nand the following optional arguments:\n- **default_request_formatter** - A formatter applied to request query parameters and body, if any are provided,\nbefore the request is sent. Can be overriden on per-request basis via _request_formatter_ kwarg \n(see \"Making HTTP requests\" section). If not provided, the DefaultRequestFormatter instance is used (see \"Request formatters\" section).\n- **default_response_formatter** - A formatter applied to response body, after the request is successfully completed. \nCan be overriden on per-request basis via _response_formatter_ kwarg (see \"Making HTTP requests\" section). \nIf not provided, the FullResponseFormatter instance is used (see \"Request formatters\" section).\n- **request_header_managers** - A list or tuple of header manager instances (see \"Request header managers\" section) for generating headers during request execution. \nEach header manager corresponds to single header key:value pair sent with each individual request. An empty tuple is used by default.\n- **default_response_error_builder** - A class, which maps unsuccessful response to error class by response status code\n (see \"Response error builder\" section). \n\n\nRequest header managers\n======\nRequest header managers provide additional request headers to the request before it is sent.\n\nEach header manager must be an inheritor of the AbstractRequestHeaderManager class and implement .get_header_name() \nand .get_header_value() methods. Method .get_header_name() provides header key and method .get_header_value()\nprovides header value. \n\nDuring the request execution, any existing request headers will be supplemented by \nheaders retrieved from header managers passed to corresponding RequestHelper instance. \n**Each header manager is responsible for one header only**.\n\n\nPassing Authorization to http request\n==========\nAuthorization is set via AuthByServiceHeaderManager (sync/async) request header manager instance, which is passed to \nRequestHelper constructor as a member of the _request_header_managers_ list or tuple.\n\n```python\nfrom servic_request_helper.syncs.auth import AuthByServiceHeaderManager\nfrom servic_request_helper.syncs.clients import RequestHelper\nfrom servic_request_helper.utils import MethodWrapper\n\nauth_manager = AuthByServiceHeaderManager(\n host='https://example.com',\n auth_uri='/auth/example',\n credential={'login': '***', 'password': '***'},\n access_token_field='accessToken',\n)\n\napi = MethodWrapper(RequestHelper(\n host='https://example.com',\n request_header_managers=[auth_manager],\n))\n```\n\nAuthByServiceHeaderManager accepts the following required arguments:\n- **host** - A host part of the url for authorization request\n- **auth_uri** - A uri path component of the authorization endpoint url\n- **credential** - A dict of authorization credentials, which is passed as request body to the authorization endpoint\n\nand the following optional arguments:\n- **access_token_field** - A name of the field in the response body of the authorization endpoint, \nwhich contains the bearer token to be used for authorization for requests to the API. Default value is 'access_token'.\n- **access_expire_at_field** - A name of the field in the response body of the authorization endpoint, \nwhich contains the string representation of token expiry date and time. Default value is None.\n- **datetime_converter** - A function to convert the string representation of token expiry date and time, retrieved \nfrom the response body, to the python datetime object. Default value is datetime.fromisoformat.\n\n\nMaking HTTP requests\n=======\nAll HTTP requests are made through the corresponding methods of the MethodWrapper instance. Each method has\nthe same set of required and optional arguments as its input:\n\nRequired arguments:\n- **uri** - A uri path component of the endpoint url where the request will be sent\n\nOptional arguments:\n- **request_formatter** - An instance of the inheritor of AbstractRequestFormatter class. Used to format request query params\nand body before the request is sent. Overrides _default_request_formatter_ of the RequestHelper.\n- **response_formatter** - An instance of the inheritor of AbstractResponseFormatter class. Used to format response body\nafter successful response to the request. Overrides _default_response_formatter_ of the RequestHelper.\n- **response_error_builder** - An instance of the inheritor of AbstractResponseErrorBuilder class. Used to map \nunsuccessful response to error class by response status code. Overrides _default_response_error_builder_ of the\nRequestHelper class.\n- **params** - A dict of the query params to be sent with the request\n- **data** - A dict to be added to request body. Either _data_ or _json_ argument can be set, not both.\n- **json** - A dict to be added to request body in json format. Either _data_ or _json_ argument can be set, not both.\n- **files** - A dict of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload.\n ``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')``\n or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a string\n defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers\n to add for the file.\n- **headers** - A dict of additional headers to add to headers generated by _request_header_managers_ of the \nRequestHelper class.\n- **\\*\\*kwargs** - Any additional keyword arguments to be passed to underlying request method.\n\nAll optional arguments are None by default.\n\n\nRequest formatters\n======\nRequest formatters are used to modify request query params or body before the request is sent. Each request formatter \nmust inherit from AbstractRequestFormatter and implement _.format_ method, which accepts dict and must return dict.\n\nLibrary provides the following request formatters:\n- **DefaultRequestFormatter()** - Does not perform formatting on the data\n- **CamelizeRequestFormatter()** - Transforms dict keys of the data to be formatted to camelCase\n\n\nResponse formatters (sync/async)\n=======\nResponse formatters are used to modify response body after the successful execution of the request and before \nit is returned to client. Each response formatter must inherit from AbstractResponseFormatter \nand implement _.format_ method, which accepts response object and must return processed response body.\n\nAsync response object's methods must be awaited before they are returned to client.\n\nLibrary provides the following response formatters for sync and async:\n- **FullResponseFormatter()** - Does not perform formatting on the response, response object will be passed to client\n- **JsonResponseFormatter()** - Retrieves json body of the response without modifying it\n- **JsonDecamelizeResponseFormatter()** - Retrieves json body of the response with keys formatted to snake_notation\n- **ContentResponseFormatter()** - Retrieves the file content of the response\n\n\nResponse error builder (sync/async)\n=======\nResponse error builder is used to map unsuccessful response to relevant exception class by response status code and \nraise its exception. Each response error builder must inherit from AbstractResponseErrorBuilder class and implement its\n_build_error_ method, which accepts url, request method and response object, and raises suitable exception from .errors\nmodule. \n\nAsync response object's methods must be awaited before they are returned to client.\n\nLibrary provides the following response error builders for sync and async:\n- **ResponseStatusErrorBuilder()** - Handles most common response status codes for unsuccessful requests\n",
"bugtrack_url": null,
"license": null,
"summary": "Helper for client request to rest api",
"version": "1.0.0",
"project_urls": {
"Homepage": "https://github.com/endpointuz/service-request-helper-lib"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "f35d855a089c7214434028aef3ede9c3117512e20a6a74c454e1748779e393c2",
"md5": "c295ae8887e69b2b9c6fce549b3a90b6",
"sha256": "c46007bcbd901b5a6f9c19841270012aaa7e74ee2f1ae18b8ceaea4f292fb5a4"
},
"downloads": -1,
"filename": "service_request_helper-1.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "c295ae8887e69b2b9c6fce549b3a90b6",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 22999,
"upload_time": "2024-12-23T12:52:25",
"upload_time_iso_8601": "2024-12-23T12:52:25.429595Z",
"url": "https://files.pythonhosted.org/packages/f3/5d/855a089c7214434028aef3ede9c3117512e20a6a74c454e1748779e393c2/service_request_helper-1.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "5747da91c4dda68f3c400bca3da2786637a2a2f7c9a0bf65b9e233b70440cb0e",
"md5": "ebc5a31a2771f60c60588be5136c0183",
"sha256": "8f6b9108efc0445108d5eed92dba72bf80862d8abc46d74b1b83b72f5e88e7e3"
},
"downloads": -1,
"filename": "service-request-helper-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "ebc5a31a2771f60c60588be5136c0183",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 15446,
"upload_time": "2024-12-23T12:52:28",
"upload_time_iso_8601": "2024-12-23T12:52:28.348411Z",
"url": "https://files.pythonhosted.org/packages/57/47/da91c4dda68f3c400bca3da2786637a2a2f7c9a0bf65b9e233b70440cb0e/service-request-helper-1.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-12-23 12:52:28",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "endpointuz",
"github_project": "service-request-helper-lib",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"test_requirements": [
{
"name": "requests",
"specs": []
},
{
"name": "aiohttp",
"specs": []
},
{
"name": "httpretty",
"specs": []
},
{
"name": "aioresponses",
"specs": []
},
{
"name": "packaging",
"specs": []
}
],
"lcname": "service-request-helper"
}