.. _aiohttp-server:
Low-level HTTP Server
=====================
.. currentmodule:: aiohttp.server
.. note::
This topic describes the low-level HTTP support. For high-level
interface please take a look on :mod:`aiohttp.web`.
Run a basic server
------------------
Start implementing the basic server by inheriting the
:class:`ServerHttpProtocol` object. Your class should
implement the only method :meth:`ServerHttpProtocol.handle_request`
which must be a coroutine to handle requests asynchronously
.. code-block:: python
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'
It Works!
')
await response.write_eof()
The next step is to create a loop and register your handler within a server.
:exc:`KeyboardInterrupt` exception handling is necessary so you can stop
your server with Ctrl+C at any time.
.. code-block:: python
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
:class:`MulitiDict` wrapper for already parsed params.
.. code-block:: python
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.
.. code-block:: python
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
:meth:`asyncio.BaseEventLoop.create_server` method of the loop.
.. code-block:: python
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
---------
.. automodule:: aiohttp.server
:members:
:undoc-members:
:show-inheritance:
.. disqus::