diff --git a/src/nercone_website/error.py b/src/nercone_website/error.py index 4a033d7..9c89721 100644 --- a/src/nercone_website/error.py +++ b/src/nercone_website/error.py @@ -2,29 +2,28 @@ from http import HTTPStatus from fastapi import Request, Response from fastapi.templating import Jinja2Templates -# TODO: こっちは普通のメッセージにする default_messages = { - 400: "日本語でおk", - 401: "見たいのならログインすることね", - 402: "夢が欲しけりゃ金払え!", - 403: "あんたなんかに見せるもんですか!", - 404: "そんなページ知らないっ!", - 405: "そのMethodはNot Allowedだよ", - 406: "すまんがその条件ではお渡しできない。", - 407: "うちのプロキシ使うんだったらまずログインしな。", - 408: "もう用がないならさっさと帰りなさい。", - 409: "ちょっと待ったそんな話聞いてないぞ", - 410: "もう無いで。", - 411: "サイズを教えろ。話はそれからだ。", - 412: "なにその条件美味しいの", - 413: "そ、そそ、そんなの入りきらないよっ!", - 414: "もちつけ", - 415: "そんな形式知らない!", - 416: "ちっさぁ:heart:", - 417: "期待させて悪かったわね!", - 418: "ティーポット「私はコーヒーを注ぐためのものではありません!やだっ!」", - 421: "またあいつ案内先間違えてるよ...どうしよ...", - 426: "それに答えるには、まずWebSocketに移動したい。" + 400: "リクエストの構文が正しくないか、パラメータが不正です。", + 401: "このリソースにアクセスするには認証が必要です。", + 402: "このリソースへのアクセスには支払いが必要です。", + 403: "このリソースへのアクセス権がありません。", + 404: "リクエストしたページまたはリソースが見つかりません。", + 405: "このリソースではそのHTTPメソッドは許可されていません。", + 406: "リクエストのAcceptヘッダーと一致するレスポンスを生成できません。", + 407: "このリソースにアクセスするにはプロキシの認証が必要です。", + 408: "リクエストが時間内に完了しませんでした。", + 409: "現在のリソースの状態とリクエストが競合しています。", + 410: "リクエストしたリソースは恒久的に削除されました。", + 411: "リクエストにはContent-Lengthヘッダーが必要です。", + 412: "リクエストの前提条件がサーバーの状態と一致しません。", + 413: "リクエストのボディがサーバーの許容サイズを超えています。", + 414: "リクエストURIがサーバーの処理できる長さを超えています。", + 415: "リクエストのメディア形式はサポートされていません。", + 416: "リクエストしたレンジはリソースのサイズ内に存在しません。", + 417: "リクエストのExpectヘッダーの要件をサーバーが満たせません。", + 418: "このサーバーはティーポットです。コーヒーを淹れることはできません。", + 421: "リクエストが意図しないサーバーに到達しました。", + 426: "このリクエストを処理するにはプロトコルのアップグレードが必要です。", } default_joke_messages = { diff --git a/src/nercone_website/logger.py b/src/nercone_website/logger.py index 40d9e74..9d1bf8c 100644 --- a/src/nercone_website/logger.py +++ b/src/nercone_website/logger.py @@ -7,8 +7,7 @@ from datetime import datetime, timezone access_log_path = Path.cwd().joinpath("logs", "access.log") access_log_path.parent.mkdir(parents=True, exist_ok=True) -# TODO: ステータスコードとかも含めたい でもそれにはレスポンスが出来上がってからログを書く必要があるので/echoとかを残すには工夫がいりそう -def log_access(scope: Scope, write: bool = True): +def log_access(scope: Scope, write: bool = False): client = scope.get("client") or ("", 0) server = scope.get("server") or ("", 0) headers = dict(scope.get("headers", [])) @@ -33,3 +32,10 @@ def log_access(scope: Scope, write: bool = True): with access_log_path.open("a", encoding="utf-8") as f: f.write(json.dumps(log, ensure_ascii=False) + "\n") return log + +def finalize_log(log: dict, status_code: int, write: bool = True) -> None: + log["status_code"] = status_code + if write: + with access_log_path.open("a", encoding="utf-8") as f: + f.write(json.dumps(log, ensure_ascii=False) + "\n") + return log diff --git a/src/nercone_website/middleware.py b/src/nercone_website/middleware.py index 353da1c..7b3638d 100644 --- a/src/nercone_website/middleware.py +++ b/src/nercone_website/middleware.py @@ -4,7 +4,7 @@ import subprocess from fastapi import Response from fastapi.responses import PlainTextResponse from starlette.types import Scope, ASGIApp, Receive, Send -from .logger import log_access +from .logger import log_access, finalize_log server_version = subprocess.run(["/usr/bin/git", "rev-parse", "--short", "HEAD"], text=True, capture_output=True).stdout.strip() onion_hostname = "4sbb7xhdn4meuesnqvcreewk6sjnvchrsx4lpnxmnjhz2soat74finid.onion" @@ -41,6 +41,7 @@ class Middleware: if not any([hostname.endswith(candidate) for candidate in hostnames]): response = PlainTextResponse("許可されていないホスト名でのアクセスです。", status_code=400) await self._send(response, scope, receive, send) + finalize_log(scope["log"], response.status_code) return body = await self._read_body(receive) @@ -54,13 +55,16 @@ class Middleware: response = await self._get_response(scope, cached_receive, subdomain_path) if response.status_code < 400: await self._send(response, scope, cached_receive, send) + finalize_log(scope["log"], response.status_code) return response = await self._get_response(scope, cached_receive, original_path) await self._send(response, scope, cached_receive, send) + finalize_log(scope["log"], response.status_code) else: response = await self._get_response(scope, cached_receive, scope["path"]) await self._send(response, scope, cached_receive, send) + finalize_log(scope["log"], response.status_code) async def _get_response(self, scope: Scope, receive: Receive, path: str) -> Response: new_scope = dict(scope, path=path)