|
1 | | -# python-http-client |
| 1 | +# Python HTTP Client |
| 2 | + |
| 3 | +## Introduction |
| 4 | + |
| 5 | +This library serves as tool to work effectively when sending requests to external services. The library wraps on top of the `requests` library and implements a couple useful method, such as in-built retry, exception raising, etc. |
| 6 | + |
| 7 | +It is being developed by the Keboola Data Services team and officially supported by Keboola. It aims to simplify the Keboola Component creation process, by removing the necessity to write complicated code to work with the APIs effectively. |
| 8 | + |
| 9 | +## Links |
| 10 | + |
| 11 | +- API Documentation: [API Docs](https://github.com/keboola/python-http-client/blob/main) |
| 12 | +- Source code: [https://github.com/keboola/python-http-client](https://github.com/keboola/python-http-client) |
| 13 | +- PYPI project code: [https://test.pypi.org/project/keboola.http-client](https://test.pypi.org/project/keboola.http-client) |
| 14 | +- Documentation: [https://developers.keboola.com/extend/component/python-component-library](https://developers.keboola.com/extend/component/python-component-library) |
| 15 | + |
| 16 | +## Quick Start |
| 17 | + |
| 18 | +### Installation |
| 19 | + |
| 20 | +The package may be installed via PIP: |
| 21 | + |
| 22 | +``` |
| 23 | +pip install keboola.http-client |
| 24 | +``` |
| 25 | + |
| 26 | +### Structure and Functionality |
| 27 | + |
| 28 | +The package contains a single core module: |
| 29 | +- `keboola.http_client` - Contains the `HttpClient` class for easy manipulation with APIs and external services |
| 30 | + |
| 31 | +### `HttpClient` |
| 32 | + |
| 33 | +The core class that serves as a tool to communicate with external services. The class is a wrapper around the `requests` library with implemented retry mechanism, and automatic error handling in case of HTTP error returned. |
| 34 | + |
| 35 | +For each HTTP method, following methods are implemented in the `HttpClient`: |
| 36 | +- GET - `get()`, `get_raw()` |
| 37 | +- POST - `post()`, `post_raw()` |
| 38 | +- PATCH - `patch()`, `patch_raw()` |
| 39 | +- UPDATE - `update()`, `update_raw()` |
| 40 | +- PUT - `put()`, `put_raw()` |
| 41 | +- DELETE - `delete()`, `delete_raw()` |
| 42 | + |
| 43 | +The difference between `_raw()` methods and their non-`_raw()` counterparts is, that raw methods will return `requests.Response` object, while non-raw methods will return a json body if the request is successful and raise an error if an HTTP error is encountered. |
| 44 | + |
| 45 | +All abovementioned methods support all parameters supported by `requests.request()` functions - as described in the [documentation](https://requests.readthedocs.io/en/latest/api/#main-interface). |
| 46 | + |
| 47 | +#### Initialization |
| 48 | + |
| 49 | +The core class is `keboola.http_client.HttpClient`, which can be initialized by specifying the `base_url` parameter: |
| 50 | + |
| 51 | +```python |
| 52 | +from keboola.http_client import HttpClient |
| 53 | + |
| 54 | +BASE_URL = 'https://connection.keboola.com/v2/storage/' |
| 55 | +cl = HttpClient(BASE_URL) |
| 56 | +``` |
| 57 | + |
| 58 | +#### Default arguments |
| 59 | + |
| 60 | +For `HttpClient`, it is possible to define default arguments, which will be sent with every request. It's possible to define `default_http_header`, `auth_header` and `default_params` - a default header, a default authentication header and default parameters, respectively. |
| 61 | + |
| 62 | +```python |
| 63 | +from keboola.http_client import HttpClient |
| 64 | + |
| 65 | +BASE_URL = 'https://connection.keboola.com/v2/storage/' |
| 66 | +AUTH_HEADER = { |
| 67 | + 'x-storageapi-token': '1234-STORAGETOKENSTRING' |
| 68 | +} |
| 69 | +DEFAULT_PARAMS = { |
| 70 | + 'include': 'columns' |
| 71 | +} |
| 72 | +DEFAULT_HEADER = { |
| 73 | + 'Content-Type': 'application/json' |
| 74 | +} |
| 75 | + |
| 76 | +cl = HttpClient(BASE_URL, default_http_header=DEFAULT_HEADER, |
| 77 | + auth_header=AUTH_HEADER, default_params=DEFAULT_PARAMS) |
| 78 | +``` |
| 79 | + |
| 80 | +#### Basic authentication |
| 81 | + |
| 82 | +By specifying the `auth` argument, the `HttpClient` will utilize the basic authentication. |
| 83 | + |
| 84 | +```python |
| 85 | +from keboola.http_client import HttpClient |
| 86 | + |
| 87 | +BASE_URL = 'https://connection.keboola.com/v2/storage/' |
| 88 | +USERNAME = 'TestUser' |
| 89 | +PASSWORD = '@bcd1234' |
| 90 | + |
| 91 | +cl = HttpClient(BASE_URL, auth=(USERNAME, PASSWORD)) |
| 92 | +``` |
| 93 | + |
| 94 | +#### Simple POST request |
| 95 | + |
| 96 | +Making a simple POST request using `post_raw()` method. |
| 97 | + |
| 98 | +```python |
| 99 | +from keboola.http_client import HttpClient |
| 100 | + |
| 101 | +BASE_URL = 'https://www.example.com/change' |
| 102 | +cl = HttpClient(BASE_URL) |
| 103 | + |
| 104 | +data = {'attr_1': 'value_1', 'attr_2': 'value_2'} |
| 105 | +header = {'content-type': 'application/json'} |
| 106 | +response = cl.post_raw(data=data, headers=header) |
| 107 | + |
| 108 | +if response.ok is not True: |
| 109 | + raise ValueError(response.json()) |
| 110 | +else: |
| 111 | + print(response.json()) |
| 112 | +``` |
| 113 | + |
| 114 | +Making a simple POST request using `post()` method. |
| 115 | + |
| 116 | +```python |
| 117 | +from keboola.http_client import HttpClient |
| 118 | + |
| 119 | +BASE_URL = 'https://www.example.com/change' |
| 120 | +cl = HttpClient(BASE_URL) |
| 121 | + |
| 122 | +data = {'attr_1': 'value_1', 'attr_2': 'value_2'} |
| 123 | +header = {'content-type': 'application/json'} |
| 124 | +response = cl.post(data=data, headers=header) |
| 125 | +``` |
| 126 | + |
| 127 | +#### Working with URL paths |
| 128 | + |
| 129 | +Each of the methods takes an optional positional argument `endpoint_path`. If specified, the value of the `endpoint_path` will be appended to the URL specified in the `base_url` parameter, when initializing the class. When appending the `endpoint_path`, the [`urllib.parse.urljoin()`](https://docs.python.org/3/library/urllib.parse.html#urllib.parse.urljoin) function is used. |
| 130 | + |
| 131 | +The below code will send a POST request to the URL `https://example.com/api/v1/events`: |
| 132 | + |
| 133 | +```python |
| 134 | +from keboola.http_client import HttpClient |
| 135 | + |
| 136 | +BASE_URL = 'https://example.com/api/v1' |
| 137 | +cl = HttpClient(BASE_URL) |
| 138 | + |
| 139 | +header = {'token': 'token_value'} |
| 140 | +cl.post_raw('events', headers=header) |
| 141 | +``` |
| 142 | + |
| 143 | +It is also possible to override this behavior by using parameter `is_absolute_path=True`. If specified, the value of `endpoint_path` will not be appended to the `base_url` parameter, but will rather be used as an absolute URL to which the HTTP request will be made. |
| 144 | + |
| 145 | +In the below code, the `base_url` parameter is set to `https://example.com/api/v1`, but the base URL will be overriden by specifying `is_absolute_path=True` and the HTTP request will be made to the URL specified in the `post()` request - `https://anothersite.com/v2`. |
| 146 | + |
| 147 | +```python |
| 148 | +from keboola.http_client import HttpClient |
| 149 | + |
| 150 | +BASE_URL = 'https://example.com/api/v1' |
| 151 | +cl = HttpClient(BASE_URL) |
| 152 | + |
| 153 | +header = {'token': 'token_value'} |
| 154 | +cl.post_raw('https://anothersite.com/v2', headers=header, is_absolute_path=True) |
| 155 | +``` |
| 156 | + |
| 157 | +#### Raw request Example |
| 158 | + |
| 159 | +A simple request made with default authentication header and parameters. |
| 160 | + |
| 161 | +```python |
| 162 | +import os |
| 163 | +from keboola.http_client import HttpClient |
| 164 | + |
| 165 | +BASE_URL = 'https://connection.keboola.com/v2/' |
| 166 | +TOKEN = os.environ['TOKEN'] |
| 167 | + |
| 168 | +cl = HttpClient(BASE_URL, auth_header={'x-storageapi-token': TOKEN}) |
| 169 | + |
| 170 | +request_params = {'exclude': 'components'} |
| 171 | +response = cl.get_raw('storage', params=request_params) |
| 172 | + |
| 173 | +if response.ok is True: |
| 174 | + print(response.json()) |
| 175 | +``` |
| 176 | + |
| 177 | +#### Building HTTP client based on HTTPClient Example |
| 178 | + |
| 179 | +This example demonstrates the default use of the HTTPClient as a base for REST API clients. |
| 180 | + |
| 181 | +```python |
| 182 | +from keboola.http_client import HttpClient |
| 183 | + |
| 184 | +BASE_URL = 'https://connection.eu-central-1.keboola.com/v2/storage' |
| 185 | +MAX_RETRIES = 10 |
| 186 | + |
| 187 | + |
| 188 | +class KBCStorageClient(HttpClient): |
| 189 | + |
| 190 | + def __init__(self, storage_token): |
| 191 | + HttpClient.__init__(self, base_url=BASE_URL, max_retries=MAX_RETRIES, backoff_factor=0.3, |
| 192 | + status_forcelist=(429, 500, 502, 504), |
| 193 | + auth_header={"X-StorageApi-Token": storage_token}) |
| 194 | + |
| 195 | + def get_files(self, show_expired=False): |
| 196 | + params = {"showExpired": show_expired} |
| 197 | + return self.get('files', params=params) |
| 198 | + |
| 199 | +cl = KBCStorageClient("my_token") |
| 200 | + |
| 201 | +print(cl.get_files()) |
| 202 | +``` |
0 commit comments