{"id":17151232,"url":"https://github.com/soda480/rest3client","last_synced_at":"2025-04-13T12:03:37.450Z","repository":{"id":39882117,"uuid":"260625386","full_name":"soda480/rest3client","owner":"soda480","description":"An abstraction of the requests library providing a simpler API for consuming HTTP REST APIs","archived":false,"fork":false,"pushed_at":"2024-03-22T20:32:19.000Z","size":154,"stargazers_count":9,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-02-05T17:24:17.818Z","etag":null,"topics":["docker","pybuilder","python","rest","restclient"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/soda480.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2020-05-02T06:08:08.000Z","updated_at":"2024-04-17T18:16:06.000Z","dependencies_parsed_at":"2024-03-22T00:48:41.019Z","dependency_job_id":null,"html_url":"https://github.com/soda480/rest3client","commit_stats":{"total_commits":49,"total_committers":3,"mean_commits":"16.333333333333332","dds":"0.12244897959183676","last_synced_commit":"4e3a3744e96f4a8d725ab035a3772bcc48a50164"},"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soda480%2Frest3client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soda480%2Frest3client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soda480%2Frest3client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soda480%2Frest3client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/soda480","download_url":"https://codeload.github.com/soda480/rest3client/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240018686,"owners_count":19734872,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","pybuilder","python","rest","restclient"],"created_at":"2024-10-14T21:37:33.730Z","updated_at":"2025-02-23T10:32:04.555Z","avatar_url":"https://github.com/soda480.png","language":"Python","readme":"# rest3client\n[![GitHub Workflow Status](https://github.com/soda480/rest3client/workflows/build/badge.svg)](https://github.com/soda480/rest3client/actions)\n[![coverage](https://img.shields.io/badge/coverage-99%25-brightgreen)](https://pybuilder.io/)\n[![complexity](https://img.shields.io/badge/complexity-A-brightgreen)](https://radon.readthedocs.io/en/latest/api.html#module-radon.complexity)\n[![vulnerabilities](https://img.shields.io/badge/vulnerabilities-None-brightgreen)](https://pypi.org/project/bandit/)\n[![PyPI version](https://badge.fury.io/py/rest3client.svg)](https://badge.fury.io/py/rest3client)\n[![python](https://img.shields.io/badge/python-3.8%20%7C%203.9%20%7C%203.10%20%7C%203.11%20%7C%203.12-teal)](https://www.python.org/downloads/)\n\nrest3client is an abstraction of the HTTP requests library (https://pypi.org/project/requests/) providing a simpler API for consuming HTTP REST APIs.\n\nThe library further abstracts the underlying HTTP requests methods providing equivalent methods for GET, POST, PATCH, PUT and DELETE. The library includes a RESTclient class that implements a consistent approach for processing request responses, extracting error messages from responses, providing standard headers to request methods, and enabling resiliency through integration with the retrying library. It also supports paging for REST APIs that leverage link headers. The abstraction enables the consumer to focus on their business logic and less on the complexites of setting up requests and processing request responses.\n\nA subclass inheriting RESTclient can override the base methods providing further customization and flexibility including the ability to automatically retry on exceptions.\n\n\n### Supported Authentication Schemes\nThe library supports most popular authentication schemes:\n- No authentication\n- Basic authentication\n- API Key-based authentication\n- Bearer token authentication\n- Token authentication\n- Certificate-based authentication\n- JWT authentication\n\n### Installation\n```bash\npip install rest3client\n```\n\n### API Usage\nThe examples below show how RESTclient can be used to consume the GitHub REST API. However RESTclient can be used to consume just about any REST API.\n\n```python\n\u003e\u003e\u003e from rest3client import RESTclient\n```\n\n`RESTclient` Authentication\n```python\n# no authentication\n\u003e\u003e\u003e client = RESTclient('api.github.com')\n\n# basic authentication\n\u003e\u003e\u003e client = RESTclient('my-api.my-company.com', username='--my-user--', password='--my-password--')\n\n# bearer token authentication\n\u003e\u003e\u003e client = RESTclient('api.github.com', bearer_token='--my-token--')\n\n# token authentication\n\u003e\u003e\u003e client = RESTclient('codecov.io', token='--my-token--')\n\n# certificate-based authentication using certificate and password\n\u003e\u003e\u003e client = RESTclient('my-api.my-company.com', certfile='/path/to/my-certificate.pem', certpass='--my-certificate-password--')\n\n# certificate-based authentication using certificate and private key\n\u003e\u003e\u003e client = RESTclient('my-api.my-company.com', certfile='/path/to/my-certificate.pem', certkey='/path/to/my-certificate-private.key')\n\n# jwt authentication\n\u003e\u003e\u003e client = RESTclient('my-api.my-company.com', jwt='--my-jwt--')\n\n# api key authentication\n\u003e\u003e\u003e client = RESTclient('my-api.my-company.com', api_key='--my-api-key--')\n# or some systems use apikey header\n\u003e\u003e\u003e client = RESTclient('my-api.my-company.com', apikey='--my-api-key--')\n```\n\n`GET` request\n```python\n# return json response\n\u003e\u003e\u003e client.get('/rate_limit')['resources']['core']\n{'limit': 60, 'remaining': 37, 'reset': 1588898701}\n\n# return raw resonse\n\u003e\u003e\u003e client.get('/rate_limit', raw_response=True)\n\u003cResponse [200]\u003e\n```\n\n`POST` request\n```python\n\u003e\u003e\u003e client.post('/user/repos', json={'name': 'test-repo1'})['full_name']\n'soda480/test-repo1'\n\n\u003e\u003e\u003e client.post('/repos/soda480/test-repo1/labels', json={'name': 'label1'})['url']\n'https://api.github.com/repos/soda480/test-repo1/labels/label1'\n```\n\n`PATCH` request\n```python\n\u003e\u003e\u003e client.patch('/repos/soda480/test-repo1/labels/label1', json={'description': 'my label'})['url']\n'https://api.github.com/repos/soda480/test-repo1/labels/label1'\n```\n\n`PUT` request\n```python\n\u003e\u003e\u003e client.put(endpoint, data=None, json=None, **kwargs)\n```\n\n`DELETE` request\n```python\n\u003e\u003e\u003e client.delete('/repos/soda480/test-repo1')\n```\n\n`HEAD` request\n```python\n\u003e\u003e\u003e response = client.head('/user/repos', raw_response=True)\n\u003e\u003e\u003e response.headers\n```\n\n#### Paging\nPaging is provided for REST APIs that make use of [link headers](https://docs.python-requests.org/en/latest/user/advanced/#link-headers).\n\n`GET all` directive - Get all pages from an endpoint and return list containing only matching attributes\n```python\nfor repo in client.get('/orgs/edgexfoundry/repos', _get='all', _attributes=['full_name']):\n    print(repo['full_name'])\n```\n\n`GET page` directive - Yield a page from endpoint\n```python\nfor page in client.get('/user/repos', _get='page'):\n    for repo in page:\n        print(repo['full_name'])\n```\n\n\n#### Retries\nAdd support for retry using the `retrying` library: https://pypi.org/project/retrying/\n\nInstantiating RESTclient with a `retries` key word argument will decorate all request methods (`get`, `put`, `post`, `delete` and `patch`) with a retry decorator using the provided arguments. For example, to retry on any error waiting 2 seconds between retries and limiting retry attempts to 3.\n```python\n\u003e\u003e\u003e client = RESTclient('api.github.com', retries=[{'wait_fixed': 2000, 'stop_max_attempt_number': 3}])\n```\nMultiple retry specifications can be provided, however the arguments provided **must** adhere to the retrying specification.\n\nSpecifying retries for specific exceptions in subclasses is simple. RESTclient will automatically discover all retry methods defined in subclasses and decorate all request methods accordingly. Arguments for the retry decorator must be provided in the docstring for the respective retry method. Retry methods must begin with `retry_`.\n\nFor example:\n\n```python\n@staticmethod\ndef retry_connection_error(exception):\n    \"\"\" return True if exception is ProxyError False otherwise\n         retry:\n            wait_random_min:10000\n            wait_random_max:20000\n            stop_max_attempt_number:6\n    \"\"\"\n    if isinstance(exception, ProxyError):\n        return True\n    return False\n```\n\nAdding the method above to a subclass of RESTclient will have the affect of decorating all the request methods with the following decorator:\n\n```python\n@retry(retry_on_exception=retry_connection_error, 'wait_random_min'=10000, 'wait_random_max'=20000, 'stop_max_attempt_number'=6)\n```\n\nYou also have the option of overriding any of the retry argument with environment variables. The environment variable must be of the form `${retry_method_name}_${argument}` in all caps. For example, setting the following environment variables will override the static settings in the `retry_connection_error` method docstring:\n\n```bash\nexport RETRY_CONNECTION_ERROR_WAIT_RANDOM_MIN = 5000\nexport RETRY_CONNECTION_ERROR_WAIT_RANDOM_MAX = 15000\n```\n\n#### Certificate Authority (CA) Bundle\n\nThe `rest3client` module's default location for the CA Bundle is `/etc/ssl/certs/ca-certificates.crt`. This location can be overridden in two different ways:\n\n* setting the `REQUESTS_CA_BUNDLE` environment variable to the desired location\n* specifying the `cabundle` parameter to the RESTclient constructor:\n```Python\nclient = RESTclient(bearer_token=\"--token--\", cabundle='/location/to/your/cabundle')\n```\n\n#### Real Eamples\nSee [GitHub3API](https://github.com/soda480/github3api) for an example of how RESTclient can be subclassed to provide further custom functionality for a specific REST API (including retry on exceptions). \n\n### CLI Usage\nRESTclient comes packaged with a command line interace (CLI) that can be used to consume REST APIs using the RESTclient class. To consume the CLI simply build and run the Docker container as described below, except when building the image exclude the `--target build-image` argument.\n```bash\nusage: rest [-h] [--address ADDRESS] [--json JSON_DATA]\n            [--headers HEADERS_DATA] [--attributes ATTRIBUTES] [--debug]\n            [--raw] [--key]\n            method endpoint\n\nA CLI for rest3client\n\npositional arguments:\n  method                HTTP request method\n  endpoint              REST API endpoint\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --address ADDRESS     HTTP request web address\n  --json JSON_DATA      string representing JSON serializable object to send\n                        to HTTP request method\n  --headers HEADERS_DATA\n                        string representing headers dictionary to send to HTTP\n                        request method\n  --attributes ATTRIBUTES\n                        attributes to filter from response - if used with\n                        --raw will filter from headers otherwise will filter\n                        from JSON response\n  --debug               display debug messages to stdout\n  --raw                 return raw response from HTTP request method\n  --key                 return key value in response - only if response is a\n                        dictionary containing a single key value\n```\n\nSet environment variables prefixed with `R3C_`.\n\nTo set the web address of the API:\n```bash\nexport R3C_ADDRESS=my-api.my-company.com\n```\n\nFor bearer token authentication:\n```bash\nexport R3C_BEARER_TOKEN=--my-token--\n```\n\nFor token authentication:\n```bash\nexport R3C_TOKEN=--my-token--\n```\n\nFor basic authentication:\n```bash\nexport R3C_USERNAME='--my-username--'\nexport R3C_PASSWORD='--my-password--'\n```\n\nFor certificate-based authentication:\n```bash\nexport R3C_CERTFILE='/path/to/my-certificate.pem'\nexport R3C_CERTPASS='--certificate-password--'\n```\n\nFor jwt-based authentication:\n```bash\nexport R3C_JWT=--my-jwt--\n```\n\nSome examples for how to execute the CLI to consume the GitHUB API:\n\n```bash\nrest POST /user/repos --json \"{'name': 'test-repo1'}\" --attributes \"name, private, description, permissions\"\n\nrest GET /user/repos --attributes \"name, full_name, private, description, permissions\"\n\nrest POST /repos/soda480/test-repo1/labels --json \"{'name': 'label1', 'color': 'C7EFD5'}\" --attributes url\n\nrest PATCH /repos/soda480/test-repo1/labels/label1 --json \"{'description': 'my label'}\" --attributes url\n\nrest DELETE /repos/soda480/test-repo1/labels/label1\n\nrest GET /repos/soda480/test-repo1/labels --attributes name\n\nrest DELETE /repos/soda480/test-repo1 --debug\n\nrest GET /rate_limit --raw\n```\n\n### Development\n\nEnsure the latest version of Docker is installed on your development server. Fork and clone the repository.\n\nBuild the Docker image:\n```sh\ndocker image build \\\n--target build-image \\\n--build-arg http_proxy \\\n--build-arg https_proxy \\\n-t \\\nrest3client:latest .\n```\n\nRun the Docker container:\n```sh\ndocker container run \\\n--rm \\\n-it \\\n-e http_proxy \\\n-e https_proxy \\\n-v $PWD:/code \\\nrest3client:latest \\\nbash\n```\n\nExecute the build:\n```sh\npyb -X\n```\n\nNOTE: commands above assume working behind a proxy, if not then the proxy arguments to both the docker build and run commands can be removed.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoda480%2Frest3client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsoda480%2Frest3client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoda480%2Frest3client/lists"}