From 8caa642dda158d749945d4c2da6a22d53d1aa5c3 Mon Sep 17 00:00:00 2001 From: nercone-dev Date: Wed, 8 Apr 2026 18:14:11 +0900 Subject: [PATCH] -- --- public/error.html | 4 ++-- src/nercone_website/database.py | 1 + src/nercone_website/error.py | 35 +++++++++++++++++++++++++++---- src/nercone_website/logger.py | 1 + src/nercone_website/middleware.py | 1 - src/nercone_website/proxy.py | 7 ++----- src/nercone_website/server.py | 8 +++---- 7 files changed, 41 insertions(+), 16 deletions(-) diff --git a/public/error.html b/public/error.html index c4bd5d7..45cee6c 100644 --- a/public/error.html +++ b/public/error.html @@ -1,7 +1,7 @@ {% extends "/base.html" %} {% block title %}{{ status_code }} {{ status_code_name }} - Nercone{% endblock %} -{% block extra_title %}Error{% endblock %} -{% block header_desc %}{{ status_code }} {{ status_code_name }}{% endblock %} +{% block extra_title %}{{ status_code }}{% endblock %} +{% block header_desc %}{{ joke_message }}{% endblock %} {% block content %}

{{ status_code }} {{ status_code_name }}

{{ message }}

diff --git a/src/nercone_website/database.py b/src/nercone_website/database.py index 9b5bd70..e57e346 100644 --- a/src/nercone_website/database.py +++ b/src/nercone_website/database.py @@ -1,6 +1,7 @@ import sqlite3 from pathlib import Path +# TODO: アクセスカウンターのためだけにDB必要無くね && アクセスログをDB化して行をカウントするだけで良くね && 構造的にDB設計するの面倒そうだからこのままでええかも class AccessCounter: def __init__(self, filepath: str = str(Path.cwd().joinpath("databases", "access_counter.db"))): self.filepath = filepath diff --git a/src/nercone_website/error.py b/src/nercone_website/error.py index c50e883..4a033d7 100644 --- a/src/nercone_website/error.py +++ b/src/nercone_website/error.py @@ -2,6 +2,7 @@ from http import HTTPStatus from fastapi import Request, Response from fastapi.templating import Jinja2Templates +# TODO: こっちは普通のメッセージにする default_messages = { 400: "日本語でおk", 401: "見たいのならログインすることね", @@ -19,11 +20,37 @@ default_messages = { 413: "そ、そそ、そんなの入りきらないよっ!", 414: "もちつけ", 415: "そんな形式知らない!", - 416: "そんな大きく...ない...んだ...", + 416: "ちっさぁ:heart:", 417: "期待させて悪かったわね!", - 418: "ティーポット「私はコーヒーを注ぐためのものではありません!やだっ!」" + 418: "ティーポット「私はコーヒーを注ぐためのものではありません!やだっ!」", + 421: "またあいつ案内先間違えてるよ...どうしよ...", + 426: "それに答えるには、まずWebSocketに移動したい。" } -def error_page(templates: Jinja2Templates, request: Request, status_code: int, message: str | None = None) -> Response: +default_joke_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に移動したい。" +} + +def error_page(templates: Jinja2Templates, request: Request, status_code: int, message: str | None = None, joke_message: str | None = None) -> Response: status_code_name = HTTPStatus(status_code).phrase - return templates.TemplateResponse(status_code=status_code, request=request, name="error.html", context={"status_code": status_code, "status_code_name": status_code_name, "message": message or default_messages.get(status_code, "あんのーん")}) + return templates.TemplateResponse(status_code=status_code, request=request, name="error.html", context={"status_code": status_code, "status_code_name": status_code_name, "message": message or default_messages.get(status_code, "不明なエラーが発生してしまったようです。ご迷惑をおかけし申し訳ございません..."), "joke_message": joke_message or default_joke_messages.get(status_code, "あんのーん")}) diff --git a/src/nercone_website/logger.py b/src/nercone_website/logger.py index 9f830dc..40d9e74 100644 --- a/src/nercone_website/logger.py +++ b/src/nercone_website/logger.py @@ -7,6 +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): client = scope.get("client") or ("", 0) server = scope.get("server") or ("", 0) diff --git a/src/nercone_website/middleware.py b/src/nercone_website/middleware.py index 63b167a..c75448b 100644 --- a/src/nercone_website/middleware.py +++ b/src/nercone_website/middleware.py @@ -1,5 +1,4 @@ import subprocess -from datetime import datetime, timezone from fastapi import Response from fastapi.responses import PlainTextResponse from starlette.types import Scope, ASGIApp, Receive, Send diff --git a/src/nercone_website/proxy.py b/src/nercone_website/proxy.py index e610a31..58ba7eb 100644 --- a/src/nercone_website/proxy.py +++ b/src/nercone_website/proxy.py @@ -1,4 +1,3 @@ -import re import httpx import asyncio from websockets.client import connect @@ -6,20 +5,18 @@ from fastapi import Request, Response, WebSocket hop_by_hop_headers = ["transfer-encoding", "connection", "keep-alive", "upgrade", "proxy-authenticate", "proxy-authorization", "te", "trailers", "content-encoding", "content-length"] -def to_raw_headers(str_headers: dict[str, str]) -> list[tuple[bytes, bytes]]: - return [(k.encode("latin-1"), v.encode("latin-1")) for k, v in str_headers.items()] - def make_http_proxy(base_url_http: str, headers: dict = {}, remove_prefix_path: bool = False): async def http_proxy(request: Request, path: str = "") -> Response: url = f"{base_url_http}/{path}" if remove_prefix_path else f"{base_url_http}{request.url.path}" merged_headers = dict(request.headers) merged_headers.pop("accept-encoding", None) merged_headers |= {k.lower(): v for k, v in headers.items()} + raw_headers = [(k.encode("latin-1"), v.encode("latin-1")) for k, v in merged_headers.items()] async with httpx.AsyncClient() as client: resp = await client.request( method=request.method, url=url, - headers=to_raw_headers(merged_headers), + headers=raw_headers, content=await request.body(), params=request.query_params ) diff --git a/src/nercone_website/server.py b/src/nercone_website/server.py index 4f84a2c..edef51e 100644 --- a/src/nercone_website/server.py +++ b/src/nercone_website/server.py @@ -99,7 +99,7 @@ async def default_response(request: Request, full_path: str) -> Response: if static := resolve_static_file(full_path): return FileResponse(static) except PermissionError: - return error_page(templates, request, 403, "ディレクトリトラバーサルね、知ってる。公開してないところ覗きたいの?えっt") + return error_page(templates, request, 403, "何をしてるんです?脆弱性報告のためならいいのですが、データ盗んで悪用するためなら今すぐにやめてくださいね?", "ディレクトリトラバーサルね、知ってる。公開してないところ覗きたいの?えっt") if full_path in ["", "/"]: template_candidates = ["index.html"] @@ -127,12 +127,12 @@ async def default_response(request: Request, full_path: str) -> Response: try: path = Path.cwd().joinpath("public", "shorturls.json") if not path.exists(): - return error_page(templates, request, 500, "設定ファイルぐらい用意しておけよ!") + return error_page(templates, request, 500, "短縮URLの処理のためのJSONファイルがありません。", "設定ファイルぐらい用意しておけよ!") shorturls = json.load(path.open("r", encoding="utf-8")) except Exception: - return error_page(templates, request, 500, "なにこの設定ファイル読めないじゃない!") + return error_page(templates, request, 500, "短縮URLの処理のためのJSONファイルを正常に読み込めませんでした。", "なにこの設定ファイル読めないじゃない!") if result := resolve_shorturl(shorturls, full_path): return RedirectResponse(url=result) - return error_page(templates, request, 404, "そんなページ知らないっ!") + return error_page(templates, request, 404, "リクエストしたページは現在ご利用になれません。削除/移動されたか、URLが間違っている可能性があります。", "そんなページ知らないっ!")