Python mini Hack-a-thon に初めて行きました。もともと Plone/Zope の hack-a-thon だったらしいのですが、最近は Plone/Zope に特化していないのということなので、こっそり参加です。何かを作り上げるっていうよりも、Python 3.2 を使うことが目的でした。が、しかし、最初の自己紹介で「Python 3 で何かつくる」って言ってしまった手前、まあなにかやろう、と。
標準ライブラリだけを使って、BaseHTTPRequestHandler を継承してフレームワークを作るというのが、どんなもんか、というのが興味あったのですよね。WSGI とかは無視で。
実は一番困ったのは、BaseHTTPRequestHandler.wfile.write() には文字列ではなくて、bytes や bytearray を渡す必要があったんですね。このへん、Python 3 の話をするときにいつも言ってるのですが、自分がやってしまうとは。
久しぶりに、どうでもいいコードを書いた。たのしぃ。やべぇ。
import sys
import http.server
import re
PORT = 8001
# --------------------------------------------------------------
# Request handler
# --------------------------------------------------------------
class Handler(http.server.BaseHTTPRequestHandler):
def do_GET(self):
return self.show()
def show(self):
view = self._find_view(self.path)
response = view(Request(self.path, self.command))
response.render(self)
def _find_view(self, path):
for pattern, view in urls:
if re.match("^"+pattern+"$", path):
break
else:
view = error_404
return view
class Request(object):
def __init__(self, path, method):
self.path = path
self.method = method
class Response(object):
def __init__(self, data,
headers={"Content-type":"text/html"}):
self.status = 200
self.headers = headers
self.data = data
def render(self, handler):
self._render_status(handler)
self._render_headers(handler)
self._render_content(handler)
def _render_status(self, handler):
handler.send_response(self.status)
def _render_headers(self, handler):
for k,v in self.headers.items():
handler.send_header(k, v)
handler.end_headers()
def _render_content(self, handler):
data = self.data
if data is not None:
handler.wfile.write(data.encode("utf8"))
# --------------------------------------------------------------
# View(s)
# --------------------------------------------------------------
def index(request):
t = "<html><head><title>Hello</title></head><body><p>Hello</p></body></html>"
return Response(t)
def error_404(request):
response = Response("404 Not Found", {})
response.status = 404
return response
# --------------------------------------------------------------
# main
# --------------------------------------------------------------
urls = [('/hoge.*', index)]
def main():
print("serving at port", PORT)
httpd = http.server.HTTPServer(("", PORT), Handler)
httpd.serve_forever()
if __name__ == "__main__":
main()