Ich habe einen einfachen HTTPS-Server eingerichtet, um das Asyncio-Modul für Ereignisschleifen und Uvloop zu üben. uvloop ist ein Modul, das auf asyncio und libuv basiert. Seit 2016 sind neue Mikroframeworks wie Sanic und Japronto mit Uvloop entstanden.
Angenommen, Python 3.6. In Python 3.6 wurde der Standardwert von SSLContext des SSL-Moduls geändert und Konstanten wurden konsolidiert.
uvloop implementiert asyncio.AbstractEventLoop
und bietet eine mit uvloop kompatible API. Aufgrund von libuv-Einschränkungen unterstützt uvloop Windows nicht, daher ist asyncio für den Fallback von uvloop verantwortlich.
Sie können ein selbstsigniertes Zertifikat mit dem folgenden Einzeiler erstellen.
# 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
Richten wir einen Echoserver ein, der unabhängig von der HTTP-Methode eine Zeichenfolge zurückgibt.
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()
Jetzt erstellen wir einen 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 ist ein auf asyncio basierendes HTTP-Modul, das auch über Funktionen zur Anwendungsentwicklung verfügt. Die Installation ist wie folgt:
pip3 install aiohttp
Lassen Sie uns einen Server einrichten, auf dem HTML-Dateien angezeigt werden.
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)