Deprecated Low-level Server

Note

This topic describes the low-level HTTP support. For high-level interface please take a look on aiohttp.web.

Deprecated since version 1.2: The module has been deprecated and will be eventually removed. Use Low Level Server instead.

The new solution provides much more user friendly API.

Run a basic server

Start implementing the basic server by inheriting the ServerHttpProtocol object. Your class should implement the only method ServerHttpProtocol.handle_request() which must be a coroutine to handle requests asynchronously:

from urllib.parse import urlparse, parse_qsl

import aiohttp
import aiohttp.server
from aiohttp import MultiDict


import asyncio

class HttpRequestHandler(aiohttp.server.ServerHttpProtocol):

  async def handle_request(self, message, payload):
      response = aiohttp.Response(
          self.writer, 200, http_version=message.version
      )
      response.add_header('Content-Type', 'text/html')
      response.add_header('Content-Length', '18')
      response.send_headers()
      response.write(b'<h1>It Works!</h1>')
      await response.write_eof()

The next step is to create a loop and register your handler within a server. KeyboardInterrupt exception handling is necessary so you can stop your server with Ctrl+C at any time:

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    f = loop.create_server(
        lambda: HttpRequestHandler(debug=True, keep_alive=75),
        '0.0.0.0', '8080')
    srv = loop.run_until_complete(f)
    print('serving on', srv.sockets[0].getsockname())
    try:
        loop.run_forever()
    except KeyboardInterrupt:
        pass

Headers

Data is passed to the handler in the message, while request body is passed in payload param. HTTP headers are accessed through headers member of the message. To check what the current method of the request is use the method member of the message. It should be one of GET, POST, PUT or DELETE strings.

Handling GET params

Currently aiohttp does not provide automatic parsing of incoming GET params. However aiohttp does provide a nice MulitiDict wrapper for already parsed params:

from urllib.parse import urlparse, parse_qsl

from aiohttp import MultiDict

class HttpRequestHandler(aiohttp.server.ServerHttpProtocol):

    async def handle_request(self, message, payload):
        response = aiohttp.Response(
            self.writer, 200, http_version=message.version
        )
        get_params = MultiDict(parse_qsl(urlparse(message.path).query))
        print("Passed in GET", get_params)

Sending pre-compressed data

To include data in the response that is already compressed, do not call enable_compression. Instead, set the Content-Encoding header explicitly:

@asyncio.coroutine
def handler(request):
    headers = {'Content-Encoding': 'gzip'}
    deflated_data = zlib.compress(b'mydata')
    return web.Response(body=deflated_data, headers=headers)

Handling POST data

POST data is accessed through the payload.read() generator method. If you have form data in the request body, you can parse it in the same way as GET params:

from urllib.parse import urlparse, parse_qsl

from aiohttp import MultiDict

class HttpRequestHandler(aiohttp.server.ServerHttpProtocol):

    async def handle_request(self, message, payload):
        response = aiohttp.Response(
            self.writer, 200, http_version=message.version
        )
        data = await payload.read()
        post_params = MultiDict(parse_qsl(data))
        print("Passed in POST", post_params)

SSL

To use asyncio’s SSL support, just pass an SSLContext object to the asyncio.AbstractEventLoop.create_server() method of the loop:

import ssl

sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
sslcontext.load_cert_chain('sample.crt', 'sample.key')

loop = asyncio.get_event_loop()
loop.create_server(lambda: handler, "0.0.0.0", "8080", ssl=sslcontext)

Reference

simple HTTP server.

class aiohttp.server.ServerHttpProtocol(*, loop=None, time_service=None, keepalive_timeout=75, tcp_keepalive=True, slow_request_timeout=0, logger=<logging.Logger object>, access_log=<logging.Logger object>, access_log_format='%a %l %u %t "%r" %s %b "%{Referrer}i" "%{User-Agent}i"', debug=False, max_line_size=8190, max_headers=32768, max_field_size=8190, lingering_time=30.0, lingering_timeout=5.0, **kwargs)[source]

Bases: aiohttp.parsers.StreamProtocol

Simple HTTP protocol implementation.

ServerHttpProtocol handles incoming HTTP request. It reads request line, request headers and request payload and calls handle_request() method. By default it always returns with 404 response.

ServerHttpProtocol handles errors in incoming request, like bad status line, bad headers or incomplete payload. If any error occurs, connection gets closed.

Parameters:
  • time_service – Low resolution time service
  • keepalive_timeout (int or None) – number of seconds before closing keep-alive connection
  • tcp_keepalive (bool) – TCP keep-alive is on, default is on
  • slow_request_timeout (int) – slow request timeout
  • debug (bool) – enable debug mode
  • logger (aiohttp.log.server_logger) – custom logger object
  • access_log (aiohttp.log.server_logger) – custom logging object
  • access_log_format (str) – access log format string
  • loop – Optional event loop
  • max_line_size (int) – Optional maximum header line size
  • max_field_size (int) – Optional maximum header field size
  • max_headers (int) – Optional maximum header size
connection_lost(exc)[source]
connection_made(transport)[source]
data_received(data)[source]
handle_error(status=500, message=None, payload=None, exc=None, headers=None, reason=None)[source]

Handle errors.

Returns HTTP response with specific status code. Logs additional information. It always closes current connection.

handle_request(message, payload)[source]

Handle a single HTTP request.

Subclass should override this method. By default it always returns 404 response.

Parameters:
  • message (aiohttp.protocol.HttpRequestParser) – Request headers
  • payload (aiohttp.streams.FlowControlStreamReader) – Request payload
keep_alive(val)[source]

Set keep-alive connection mode.

Parameters:val (bool) – new state.
keep_alive_timeout
keepalive_timeout
log_access(message, environ, response, time)[source]
log_debug(*args, **kw)[source]
log_exception(*args, **kw)[source]
coroutine shutdown(timeout=15.0)[source]

Worker process is about to exit, we need cleanup everything and stop accepting requests. It is especially important for keep-alive connections.

coroutine start()[source]

Start processing of incoming requests.

It reads request line, request headers and request payload, then calls handle_request() method. Subclass has to override handle_request(). start() handles various exceptions in request or response handling. Connection is being closed always unless keep_alive(True) specified.

time_service
blog comments powered by Disqus