Low-level HTTP Server¶
Note
This topic describes the low-level HTTP support. For high-level
interface please take a look on aiohttp.web
.
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)
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.BaseEventLoop.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)