Asynchronous Server Gateway Interface


two components

  • protocol server: terminates socket and translates them into connections and per-connection event messages
  • application: lives in inside a server, is instantiated once per connection, and handles event messages as they happen

difference between two components

  • applications are instant objects that are fed events rather than simple callable, and must run as asyncio-compativle corountines
  • two separate parts of a connection: a connection scope; events


Connection Scope

  • Under HTTP, the connection scope lasts just one request. it contains most of the request data(apart from the request body)
  • Under WebSocket, the connection scope lasts for as long as the socket is connected. the scope contains information like the WebSocket’s path, but details like incoming messages come through as events instead.
  • Each protocol definition must contain information about how long its connection scope lasts, and what information you will get inside it
  • Applications cannot communicate with the client when they are initialized and given their connection scope, they must wait until their event loop is entered


  • for HTTP, 2 evens in order - http.requst and http.disconnect
  • for WebSocket, it could more like websocket.connect, websocket.send, websocket.receive, and finally websocket.disconnect
  • each event is a dict


Applications should be a single async callable:

coroutine application(scope, receive, send)
  • scope: The connection scope, a dict that contains as least a type key specifying the protocol that is incoming
  • receive: an awaitable callable that will yield a new event dict when one is available
  • send: an awaitable callable taking a single event dict as positional argument that will return once the send has been completed or the connection has been closed

Message Format

  • Connection Scope: type(http), asgi, method, path, scheme, query_string, client, server
  • Request: the body message serves as a way to stream incoming HTTP bodies in chunks. keys include type(http.request), body(bytes), more_body(bool)
  • Response Start: start sending a response. keys include type(http.response.start), status(int), headers
  • Response Body: continues sending a response to the client. keys include type(http.response,body), body(bytes), more_body(bool)
  • Disconnect: sent to the application when a connection is closed . keys include type(http.disconnect)
  • Connection Scope: keys include type(websocket), asgi, http_version, headers…
  • Connection: sent when the client initially opens a connection and is about to finish the WebSocket handshake. keys include type(websocket.connect)
  • Accept: keys include type(websocket.accept), headers
  • Receive: sent when a message is received from the client. keys include type(websocket.receive), bytes(bytes), text(str)
  • Send: keys include type(websocket.send), bytes, text
  • Disconnection: keys include type(websocket.disconnect), code(int)
  • Close: tell the server to close the connection. keys include type(websocket.close), code(int)
  • Scope: exists for the duration of the event loop. keys include type(lifespan)
  • Startup: send when the server is ready to startup and receive connections, but before it has started to do so. keys include type(lifespan,startup)
  • Start Complete: sent by the application when it has completed its startup. a server must wait for this message before it starts processing connections. keys include type(lifespan.startup.complete)
  • Startup Failed: if a server sees this it should log the message proved and then exit. keys include type(lifespan.startup.failed), message(str)
  • Shutdown: sent when the server has stopped accepting connections and closed all active connections. keys include type(lifespan.shutdown)
  • Shutdown Complete: sent by the application when it has completed its cleanup. keys include type(lifespan.shutdown.complete)
  • Shutdown Failed: sent by the application when it has failed to complete its cleanup. keys include type(life.shutdown.failed), message