I've set up a simple HTTPS server to practice the asyncio module for event loops and the uvloop. uvloop is a module based on asyncio and libuv. Since 2016, new micro-frameworks such as Sanic and japronto that have adopted uvloop have emerged.
It assumes Python 3.6. In Python 3.6, the SSLContext default values for the ssl module have been changed and constants have been consolidated.
uvloop implements ʻasyncio.AbstractEventLoop` and provides an API compatible with uvloop. Due to libuv constraints, uvloop does not support Windows, so asyncio is responsible for the uvloop fallback.
You can create a self-signed certificate with the following one-liner.
# https://stackoverflow.com/a/41366949/531320
openssl req -x509 -newkey rsa:4096 -sha256 \
-nodes -keyout server.key -out server.crt \
-subj "/CN=example.com" -days 3650
Let's set up an echo server that returns a string regardless of the HTTP method.
server.py
import asyncio
import ssl
async def request_handler(reader, writer):
msg = (
'HTTP/1.1 200 OK\r\n'
'Content-Type: text/plain; charset=utf-8\r\n'
'\r\n'
'hello\r\n'
)
writer.write(msg.encode())
await writer.drain()
writer.close()
host = '127.0.0.1'
port = 8000
ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
ctx.load_cert_chain('server.crt', keyfile='server.key')
ctx.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
loop = asyncio.get_event_loop()
coro = asyncio.start_server(
request_handler,
host, port, ssl=ctx, loop=loop
)
server = loop.run_until_complete(coro)
print('Serving on {}'.format(server.sockets[0].getsockname()))
try:
loop.run_forever()
except KeyboardInterrupt:
pass
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()
Now let's create an HTTPS client.
client.py
import asyncio
import ssl
async def http_client(host, port, msg, ctx, loop):
reader, writer = await asyncio.open_connection(
host, port, ssl=ctx, loop=loop
)
writer.write(msg.encode())
data = await reader.read()
print("Received: %r" % data.decode())
writer.close()
host = '127.0.0.1'
port = 8000
msg = (
'GET / HTTP/1.1\r\n'
'Host: localhost:8000\r\n'
'\r\n'
'\r\n'
)
ctx = ssl.create_default_context()
ctx.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
loop = asyncio.get_event_loop()
loop.run_until_complete(http_client(host, port, msg, ctx, loop))
loop.close()
aiohttp
aiohttp is an HTTP module developed based on asyncio, and also comes with application development functions. The installation is as follows:
pip3 install aiohttp
Let's set up a server that displays HTML files.
server.py
from aiohttp import web
from pathlib import Path
import ssl
host='localhost'
port=8000
ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
ctx.load_cert_chain('server.crt', keyfile='server.key')
ctx.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
app = web.Application()
app.router.add_static('/static', path=str(Path.cwd().joinpath('static')), show_index=True)
web.run_app(app, host=host, port=port, ssl_context=ctx)
Recommended Posts