Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/dutradda/apidaora
HTTP/REST API using dataclasses and TypedDict annotation for python
https://github.com/dutradda/apidaora
Last synced: 2 days ago
JSON representation
HTTP/REST API using dataclasses and TypedDict annotation for python
- Host: GitHub
- URL: https://github.com/dutradda/apidaora
- Owner: dutradda
- License: mit
- Created: 2019-09-17T02:19:00.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2020-11-27T22:34:36.000Z (almost 4 years ago)
- Last Synced: 2024-10-27T22:09:38.893Z (15 days ago)
- Language: Python
- Homepage: https://dutradda.github.io/apidaora/
- Size: 1.45 MB
- Stars: 149
- Watchers: 5
- Forks: 7
- Open Issues: 15
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
README
# apidaora
OpenAPI / HTTP / REST API using dataclasses and TypedDict annotation for python---
**Documentation**: https://dutradda.github.io/apidaora
**Source Code**: https://github.com/dutradda/apidaora
---
## Key Features
- Declaration of request/response as dataclasses and dicts using typing annotations
- Input data validation with [jsondaora](https://github.com/dutradda/jsondaora)
- One of the [fastest](#benchmark) python api framework
- Can run on any asgi server## Requirements
- Python 3.8+
- [jsondaora](https://github.com/dutradda/jsondaora) for json validation/parsing
- [orjson](https://github.com/ijl/orjson) for json/bytes serialization (jsondaora dependency)## Instalation
```
$ pip install apidaora
```## Simple example
```python
from apidaora import appdaora, route@route.get('/hello')
def hello_controller(name: str) -> str:
return f'Hello {name}!'app = appdaora(hello_controller)
```
Running the server (needs uvicorn [installed](https://www.uvicorn.org)):
```bash
uvicorn myapp:app
``````
INFO: Started server process [16220]
INFO: Waiting for application startup.
INFO: ASGI 'lifespan' protocol appears unsupported.
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)```
Quering the server (needs curl [installed](https://curl.haxx.se/docs/install.html)):
```bash
curl -i localhost:8000/hello?name=World```
```
HTTP/1.1 200 OK
date: Thu, 1st January 1970 00:00:00 GMT
server: uvicorn
content-type: application/json
content-length: 14"Hello World!"
```
## Basic example
```python
from typing import TypedDictfrom jsondaora import IntegerField, StringField, jsondaora
from apidaora import Header, appdaora, route
class Integer(IntegerField, minimum=18):
...class String(StringField, max_length=100):
...class Age(Header, type=Integer):
...@jsondaora
class You(TypedDict):
name: str
last_name: str
location: str
age: int@jsondaora
class ReqBody(TypedDict):
last_name: str@jsondaora
class HelloOutput(TypedDict):
hello_message: str
about_you: You@route.put('/hello/{name}')
async def hello_controller(
name: str, location: String, age: Age, body: ReqBody
) -> HelloOutput:
you = You(
name=name,
location=location.value,
age=age.value.value,
last_name=body['last_name'],
)
return HelloOutput(
hello_message=await hello_message(name, location.value), about_you=you
)async def hello_message(name: str, location: str) -> str:
return f'Hello {name}! Welcome to {location}!'app = appdaora(hello_controller)
```
Running the server:
```bash
uvicorn myapp:app
``````
INFO: Started server process [16220]
INFO: Waiting for application startup.
INFO: ASGI 'lifespan' protocol appears unsupported.
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)```
Quering the server:
```bash
curl -i -X PUT localhost:8000/hello/Me?location=World \
-H 'x-age: 32' \
-d '{"last_name":"My Self"}'```
```
HTTP/1.1 200 OK
date: Thu, 1st January 1970 00:00:00 GMT
server: uvicorn
content-type: application/json
content-length: 123{"hello_message":"Hello Me! Welcome to World!","about_you":{"name":"Me","location":"World","age":32,"last_name":"My Self"}}
```
## Example for more request/response details
```python
from http import HTTPStatus
from typing import Dictfrom jsondaora import jsondaora
from apidaora import BadRequestError, Header, Response, appdaora, json, route
# Domain layer, here are the domain related definitions
# it is apidaora/framework/http independent@jsondaora
class You:
name: str
last_name: str
age: intDB: Dict[str, You] = {}
def add_you(you: You) -> None:
if you.name in DB:
raise YouAlreadyBeenAddedError(you.name)
DB[you.name] = youdef get_you(name: str) -> You:
try:
return DB[name]
except KeyError:
raise YouWereNotFoundError(name)class DBError(Exception):
@property
def info(self) -> Dict[str, str]:
return {'name': self.args[0]}class YouAlreadyBeenAddedError(DBError):
name = 'you-already-been-added'class YouWereNotFoundError(DBError):
name = 'you-were-not-found'# Application layer, here are the http related definitions
# See: https://dutrdda.github.io/apidaora/tutorial/headers/
class ReqID(Header, type=str, http_name='http_req_id'):
...@route.post('/you/')
async def add_you_controller(req_id: ReqID, body: You) -> Response:
try:
add_you(body)
except YouAlreadyBeenAddedError as error:
raise BadRequestError(name=error.name, info=error.info) from errorreturn json(body, HTTPStatus.CREATED, headers=(req_id,))
@route.get('/you/{name}')
async def get_you_controller(name: str, req_id: ReqID) -> Response:
try:
return json(get_you(name), headers=(req_id,))
except YouWereNotFoundError as error:
raise BadRequestError(name=error.name, info=error.info) from errorapp = appdaora([add_you_controller, get_you_controller])
```
Running the server:
```bash
uvicorn myapp:app
``````
INFO: Started server process [16220]
INFO: Waiting for application startup.
INFO: ASGI 'lifespan' protocol appears unsupported.
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)```
Quering the server:
```bash
curl -X POST -i localhost:8000/you/ -H 'http_req_id: 1a2b3c4d' -d '{"name":"Me","last_name":"Myself","age":32}'```
```
HTTP/1.1 201 Created
date: Thu, 1st January 1970 00:00:00 GMT
server: uvicorn
content-type: application/json
content-length: 43
http_req_id: 1a2b3c4d{"name":"Me","last_name":"Myself","age":32}
```
```bash
curl -i localhost:8000/you/Me -H 'http_req_id: 4d3c2b1a'```
```
HTTP/1.1 200 OK
date: Thu, 1st January 1970 00:00:00 GMT
server: uvicorn
content-type: application/json
content-length: 43
http_req_id: 4d3c2b1a{"name":"Me","last_name":"Myself","age":32}
```
## Benchmark
![techempower benchmark](https://dutradda.github.io/apidaora/benchmark.png "TechEmpower Frameworks Benchmark")
The full results can be found [here](https://www.techempower.com/benchmarks/#section=test&runid=76bbd357-a161-42eb-a203-051bdd949006&hw=ph&test=query&l=zijzen-v)