Simple REST¶
This example sends and receives data using REST. You will need something like postman to try it out.
We use hypercorn as the ASGI server.
The source code can be found here (and here here with typing).
import asyncio
import json
from hypercorn.asyncio import serve
from hypercorn.config import Config
from bareasgi import Application, text_reader, text_writer
import bareutils.header as header
async def get_info(request):
accept = header.find(b'accept', request.scope['headers'])
if accept != b'application/json':
return 500
# Get the info
text = json.dumps(request.info)
headers = [
(b'content-type', b'application/json')
]
return HttpResponse(200, headers, text_writer(text))
async def set_info(request):
content_type = header.find(b'content-type', request.scope['headers'])
if content_type != b'application/json':
return 500
text = await text_reader(request.body)
data = json.loads(text)
# Set the info
request.info.update(data)
return HttpResponse(204)
app = Application(info={'name': 'Michael Caine'})
app.http_router.add({'GET'}, '/info', get_info)
app.http_router.add({'POST'}, '/info', set_info)
# Start hypercorn
config = Config()
config.bind = ["0.0.0.0:9009"]
asyncio.run(serve(app, config))
To try this out make a GET request to http://localhost:9009/info with the
accept header set to application/json. It should respond with a
content-type of application/json and body of {“name": “Michael Caine"}.
Sending a POST to the same endpoint with the body {“name": “Peter Sellers"}
and a content-type of application/json should respond with a 204 status
code. A subsequent GET should return {“name": “Peter Sellers"}.
Request Parameters¶
In this example we start to use some of the request fields.
scope¶
The scope is passed directly from the ASGI server. It is a dictionary of
values describing the request. We use it here to inspect the headers.
Looking at the ASGI cconnection-scope documentation we can see it contains everything the ASGI server knows about the request, including the scheme, the query string, etc.
info¶
The info is a dict which is supplied to the Application on construction
(or automatically generated if not). It is the means of the application sharing
data.
In this example it is created with a name entry.
app = Application(info={'name': 'Michael Caine'})
The GET handler retrieves the info and returns it as a string.
text = json.dumps(info)
headers = [
(b'content-type', b'application/json')
]
return HttpResponse(200, headers, text_writer(text))
The POST handler reads the new data from the request body and updates the
info with whatever was sent.
text = await text_reader(request.body)
data = json.loads(text)
request.info.update(data)
A subsequent GET will return the new content of info.
body¶
The content is the complement of the body in the response. It is another
asynchronous generator and is used to read the body of the request. The
text_reader helper function is used to retrieve the body (note this is
awaited).
Response¶
The handlers respond with 500 if the request was incorrect.
if content_type != b'application/json':
return HttpResponse(500)
We can see that it is not necessary to provide all the elements of the response,
where all elements to the right would be None.
What next?¶
Either go back to the table of contents or go to the lifespan tutorial.