Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/julian-nash/respond
A fast, effective & efficient way to return JSON, text and XML in Flask with the correct HTTP status code & headers.
https://github.com/julian-nash/respond
api flask http json python rest
Last synced: about 1 month ago
JSON representation
A fast, effective & efficient way to return JSON, text and XML in Flask with the correct HTTP status code & headers.
- Host: GitHub
- URL: https://github.com/julian-nash/respond
- Owner: Julian-Nash
- License: mit
- Created: 2020-05-03T17:22:57.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2020-09-11T20:52:53.000Z (over 4 years ago)
- Last Synced: 2024-11-15T05:56:56.750Z (about 2 months ago)
- Topics: api, flask, http, json, python, rest
- Language: Python
- Homepage: https://pypi.org/project/respond/
- Size: 54.7 KB
- Stars: 7
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# respond
![Python package](https://github.com/Julian-Nash/respond/workflows/Python%20package/badge.svg?branch=master)
`respond` is a small, lightweight wrapper around Flask's `make_response` and `jsonify`, providing a fast and convenient
way to return JSON, XML or plaintext data with the right HTTP status code and headers.`respond` utilizes the RFC HTTP status code descriptions as methods, you simply call a static method
such as `ok`, `not_found` or `internal_server_error` against the data type you with to return, optionally passing in
a dictionary of headers to set on the response.__Python v3.6 + (100% coverage)__
```shell script
Name Stmts Miss Cover Missing
------------------------------------------------------------
respond/__init__.py 4 0 100%
respond/abs_http_response.py 188 0 100%
respond/json_response.py 11 0 100%
respond/responder.py 7 0 100%
respond/text_response.py 12 0 100%
respond/xml_response.py 12 0 100%
------------------------------------------------------------
TOTAL 234 0 100%```
## Installation
```shell script
pip install respond
```## Usage
Import the `Responder` class
```py3
from respond import Responder
```You can now call one of many staticmethods of the class
Return a `200 OK` status code and a list
```py3
@app.route("/")
def example():
""" Returns a list with an HTTP 200 OK status code """
return Responder.json.ok([1, 2, 3])
```Return a `400 BAD REQUEST` status code and a dict
```py3
@app.route("/")
def example():
""" Returns a dict with an HTTP 400 BAD REQUEST status code """
return Responder.json.bad_request({"error": {"message": "You did something wrong"}})
```Return a `500 INTERNAL SERVER ERROR` status code
```py3
@app.route("/")
def example():
""" Returns a dict with an HTTP 500 INTERNAL SERVER ERROR status code """
return Responder.json.internal_server_error({"error": {"message": "We did something wrong"}})
```Passing no data to the method returns an empty string
```py3
@app.route("/")
def ok():
""" Return an empty HTTP 204 NO CONTENT response """
return Responder.json.no_content()
```You can optionally pass in a headers dict if required
```py3
@app.route("/")
def example():
""" Return a dict with custom headers """
return Responder.json.ok(data={"message": "ok"}, headers={"X-Custom-Header": "hello!"})
```On inspecting the response, we can see our custom header:
```shell script
Content-Length: 17
Date: Sun, 03 May 2020 16:49:41 GMT
Content-Type: application/json
Server: Werkzeug/1.0.1 Python/3.8.2
X-Custom-Header: hello!
```The `Responder` class has methods for all HTTP status codes defined by the ietf - https://tools.ietf.org/html/rfc7231
Common status codes include, `404 NOT FOUND`, here being used in a Flask error handler
```py3
def handle_not_found_error(e):
""" Handler for not found errors """
app.logger.warning(e)
return Responder.json.not_found(data={"message": "Not found"})app.register_error_handler(404, handle_not_found_error)
```And `500 INTERNAL SERVER ERROR`
```py3
@app.route("/internal-server-error")
def internal_server_error():
data: dict = {"error": {"message": "Whoops, we did something wrong"}}
return Responder.json.internal_server_error(data)
```Visiting this URL in the browser returns
```shell script
{"error": {"message": "Whoops, we did something wrong"}
```You may also import individual classes for the specific data types JSON, XML and text using `JSONResponse`,
`XMLResponse` and `TextResponse` respectively.```py3
from respond import JSONResponse@app.route("/internal-server-error")
def internal_server_error():
data: dict = {"error": {"message": "Whoops, we did something wrong"}}
return JSONResponse.internal_server_error(data)
```## Extending
The `HTTPResponse` abstract base class provides an interface for all of the HTTP status codes and defines a single
abstract method called `_make_response`.
Users can implement their own class by inheriting from `HTTPResponse` and implementing the `_make_response` method
, accepting 4 parameters `status`, `data`, `headers` and `**kwargs`.```py3
class HTTPResponse(abc.ABC):
""" HTTPResponse abstract base class """@classmethod
@abc.abstractmethod
def _make_response(cls, status: int, data: Optional[Any] = None, headers: Optional[dict] = None, **kwargs):
raise NotImplementedError
```## Methods available
**100 range (informational)**
| method | HTTP Status code |
| ------ | ---------------- |
| `continue` | `100 `|
| `switching_protocol` | `101 `|
| `processing` | `102 `|
| `early_hints` | `103 `|**200 range (success)**
| method | HTTP Status code |
| ------ | ---------------- |
| `ok` | `200 `|
| `created` | `201 `|
| `accepted` | `202 `|
| `non_authoritative_information` | `203 `|
| `no_content` | `204 `|
| `reset_content` | `205 `|
| `partial_content` | `206 `|
| `multi_status` | `207 `|
| `already_reported` | `208 `|
| `im_used` | `226 `|**300 range (redirection)**
| method | HTTP Status code |
| ------ | ---------------- |
| `multiple_choice` | `300 `|
| `moved_permanently` | `301 `|
| `found` | `302 `|
| `see_other` | `303 `|
| `not_modified` | `304 `|
| `use_proxy` | `305 `|
| `unused` | `306 `|
| `temporary_redirect` | `307 `|
| `permanent_redirect` | `308 `|**400 range (client error)**
| method | HTTP Status code |
| ------ | ---------------- |
| `bad_request` | `400 `|
| `unauthorized` | `401 `|
| `payment_required` | `402 `|
| `forbidden` | `403 `|
| `not_found` | `404 `|
| `method_not_allowed` | `405 `|
| `not_acceptable` | `406 `|
| `proxy_authentication_required` | `407 `|
| `request_timeout` | `408 `|
| `conflict` | `409 `|
| `gone` | `410 `|
| `length_required` | `411 `|
| `precondition_failed` | `412 `|
| `payload_too_large` | `413 `|
| `uri_too_long` | `414 `|
| `unsupported_media_type` | `415 `|
| `requested_range_not_satisfiable` | `416 `|
| `expectation_failed` | `417 `|
| `im_a_teapot` | `418 `|
| `misdirected_request` | `421 `|
| `unprocessable_entity` | `422 `|
| `locked` | `423 `|
| `failed_dependency` | `424 `|
| `too_early` | `425 `|
| `upgrade_required` | `426 `|
| `precondition_required` | `428 `|
| `too_many_requests` | `429 `|
| `request_header_fields_too_large` | `431 `|
| `unavailable_for_legal_reasons` | `451 `|**500 range (server error)**
| method | HTTP Status code |
| ------ | ---------------- |
| `internal_server_error` | `500 `|
| `not_implemented` | `501 `|
| `bad_gateway` | `502 `|
| `service_unavailable` | `503 `|
| `gateway_timeout` | `504 `|
| `http_version_not_supported` | `505 `|
| `variant_also_negotiates` | `506 `|
| `insufficient_storage` | `507 `|
| `loop_detected` | `508 `|
| `not_extended` | `510 `|
| `network_authentication_required` | `511 `|