😎
【Python】selectors で TLS 対応の HTTP/1 サーバーを試すも失敗
selectors の公式マニュアルのサンプルコードを少し修正して試すも curl で1回リクエスト送信するだけでクラッシュしてしまった
# https://docs.python.org/3/library/selectors.html#examples
import selectors
import socket
import ssl
sel = selectors.DefaultSelector()
def accept(sock, mask):
conn, addr = sock.accept()
sel.register(conn, selectors.EVENT_READ, read)
def read(conn, mask):
msg =(
f"HTTP/1.1 200 OK\r\n"
f"Content-Type: text/html; charset=UTF-8\r\n"
f"Content-Length: 11\r\n"
f"Connection: Close\r\n"
f"\r\n"
f"Hello World"
).encode()
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain('localhost.pem', 'localhost-key.pem')
context.set_alpn_protocols(['http/1.1'])
stream = context.wrap_socket(sock=conn, server_side=True)
data = stream.recv(1000)
if data:
stream.send(msg)
else:
print('closing', stream)
stream.close()
conn.close()
sock = socket.socket()
sock.bind(('0.0.0.0', 8000))
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.listen(100)
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, accept)
while True:
events = sel.select()
for key, mask in events:
callback = key.data
callback(key.fileobj, mask)
python server.py
Traceback (most recent call last):
File "/home/masakielastic/asyncio-project/server.py", line 46, in <module>
callback(key.fileobj, mask)
~~~~~~~~^^^^^^^^^^^^^^^^^^^
File "/home/masakielastic/asyncio-project/server.py", line 9, in accept
sel.register(conn, selectors.EVENT_READ, read)
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/masakielastic/.local/share/mise/installs/python/3.13.0b3/lib/python3.13/selectors.py", line 341, in register
key = super().register(fileobj, events, data)
File "/home/masakielastic/.local/share/mise/installs/python/3.13.0b3/lib/python3.13/selectors.py", line 245, in register
raise KeyError("{!r} (FD {}) is already registered"
.format(fileobj, key.fd))
KeyError: "<socket.socket fd=5, family=2, type=1, proto=0, laddr=('127.0.0.1', 8000), raddr=('127.0.0.1', 39402)> (FD 5) is already registered"
Discussion