Bye Bye Moore

PoCソルジャーな零細事業主が作業メモを残すブログ

http.cookiesを使ってみる その1:簡単にフォームに表示

実際のところ

shuzo-kino.hateblo.jp
のThreadつきCGIをベースに、index.htmlにcookieの内容を反映するサンプルを考えてみます。

index.html

<html>
    <body>
        <p>Name from cookie: {name}</p>
        <p>Value from cookie: {value}</p>
        <form action="/setcookie" method="post">
                Name: <input type="text" name="name"><br>
                Value: <input type="text" name="value"><br>
                <input type="submit" value="Set Cookie">
        </form>
    </body>
</html>

server.py

import http.server
import socketserver
import threading
from http import cookies

class ThreadedHTTPServer(socketserver.ThreadingMixIn, http.server.HTTPServer):
    daemon_threads = True

class CookieHandler(http.server.SimpleHTTPRequestHandler):

    def do_GET(self):
        # Cookieを読む
        if "Cookie" in self.headers:
            c = cookies.SimpleCookie(self.headers["Cookie"])
            name = c["name"].value if "name" in c else ""
            value = c["value"].value if "value" in c else ""
        else:
            name = ""
            value = ""

        # index.htmlにアクセスした場合
        if self.path == "/index.html":
            self.send_response(200)
            self.send_header("Content-type", "text/html")
            self.end_headers()
            with open("index.html", "r") as f:
                content = f.read()
                # .format()を使用して{name}と{value}を置き換える
                content = content.format(name=name, value=value)
                self.wfile.write(content.encode("utf-8"))
            return

        # その他のリクエストへの対応
        super().do_GET()

    def do_POST(self):
        if self.path == "/setcookie":
            length = int(self.headers.get('content-length'))
            field_data = self.rfile.read(length).decode('utf-8')
            fields = dict(qc.split("=") for qc in field_data.split("&"))

            # クッキーを設定
            c = cookies.SimpleCookie()
            c["name"] = fields["name"]
            c["value"] = fields["value"]

            self.send_response(303)  # Redirect
            self.send_header("Location", "/index.html")
            for morsel in c.values():
                self.send_header("Set-Cookie", morsel.OutputString())
            self.end_headers()
        else:
            super().do_POST()

with ThreadedHTTPServer(("", 8000), CookieHandler) as httpd:
    print("serving at port", 8000)
    httpd.serve_forever()