How it works¶
The adapter has three parts: a resource for the aiohttp router, a match info
which the router returns, and a context which bridges one request.
Part |
Task |
|---|---|
Matches the request path, builds the match info, mounts the lifespan |
|
|
Gives the handler, the application stack and the expect handler to
|
|
Builds the ASGI scope, moves the body in both directions, makes the
|
The request path¶
The
aiohttprouter asks each resource.ASGIResource.raw_match()accepts the path when it starts withroot_path, andresolve()then returns a match info for every HTTP method.aiohttpcalls the handler of the match info. The handler creates anASGIContextfor this request.The context builds the scope from the request, and calls the ASGI application with its
receiveandsendfunctions.The application reads the body through
receive, and writes the answer throughsend.The context returns the prepared
aiohttpresponse to the server.
The request body¶
The context reads the body in chunks and gives each chunk to the application
as an http.request message:
bodyholds the chunk.more_bodyisTruewhile the body continues.
An application therefore streams a large upload without the whole body in
memory. A request with the Expect: 100-continue header gets 100 Continue
before the body arrives, and an unknown Expect value gives 417.
The response¶
The application sends two kinds of messages:
http.response.startcarries the status and the headers. The context creates theaiohttpStreamResponseand prepares it.http.response.bodycarries a chunk. The context writes the chunk, andmore_bodysays whether more chunks follow.
The answer therefore streams to the client while the application works.
WebSockets¶
The context sees a WebSocket handshake, and then:
scope["type"]iswebsocket, andscope["scheme"]iswsorwss.The first
receivecall giveswebsocket.connectwith the request headers.websocket.acceptmakes theaiohttpWebSocketResponseand prepares it with the subprotocols from the scope.websocket.sendwrites a text or a binary message.A message from the client becomes
websocket.receive, withtextorbytes. A close or an error becomeswebsocket.disconnectwith the close code.
The lifespan¶
lifespan_mount() appends a cleanup context to
the aiohttp application. The context:
Puts
lifespan.startupin the receive queue, and starts the ASGI application as a task with the lifespan scope.Waits for
lifespan.startup.complete, and logs a failed startup.Gives the control back to
aiohttp, which then serves the requests.Puts
lifespan.shutdownwhen theaiohttpapplication stops, waits forlifespan.shutdown.complete, and then waits at mostSHUTDOWN_TIMEOUTseconds for the lifespan task.
The command line server¶
The command does the same work around the resource:
It checks the format of the
module:attributeargument, but it does not import the module.It binds the listening socket.
With more than one worker it forks the workers from the parent, so the workers share the socket.
Each worker imports the application, creates the event loop, registers the resource in a new
aiohttpapplication and serves the socket.A signal sets a stop event, and the worker then closes the server.
The import after the fork and the event loop after the fork keep the state of each worker correct, because a thread or an event loop from the parent does not work in a forked process.