This commit is contained in:
2026-04-25 23:11:20 +09:00
parent 209b14e9f8
commit a4e31d1641
43 changed files with 14 additions and 5421 deletions
+13 -97
View File
@@ -10,28 +10,16 @@ from pathlib import Path
from bs4 import BeautifulSoup
from markitdown import MarkItDown
from datetime import datetime, timezone
from contextlib import asynccontextmanager
from fastapi import FastAPI, Request, Response, WebSocket, HTTPException
from zoneinfo import ZoneInfo
from fastapi import FastAPI, Request, Response
from fastapi.templating import Jinja2Templates
from fastapi.responses import PlainTextResponse, JSONResponse, FileResponse, RedirectResponse
from jinja2.exceptions import TemplateNotFound
from .error import error_page
from .database import AccessCounter
from .middleware import Middleware, server_version, onion_hostname
from .tools.tls_test import (
tls_test_db, tls_test_queue,
tls_submit, tls_api_submit, tls_results_context, tls_websocket_handler,
)
@asynccontextmanager
async def lifespan(app: FastAPI):
await tls_test_queue.start()
try:
yield
finally:
await tls_test_queue.stop()
app = FastAPI(docs_url=None, redoc_url=None, openapi_url=None, lifespan=lifespan)
app = FastAPI(docs_url=None, redoc_url=None, openapi_url=None)
app.add_middleware(Middleware)
templates = Jinja2Templates(directory=Path.cwd().joinpath("public"))
markitdown = MarkItDown()
@@ -46,6 +34,16 @@ class CustomHTMLRenderer(mistune.HTMLRenderer):
return f'<pre>{mistune.escape(code)}</pre>\n'
htmlitdown = mistune.create_markdown(renderer=CustomHTMLRenderer(escape=False))
@property
def this_year() -> int:
return datetime.now(ZoneInfo("Asia/Tokyo")).year
templates.env.globals["this_year"] = this_year
@property
def this_year_in_heisei() -> int: # heysay is not ended.
return datetime.now(ZoneInfo("Asia/Tokyo")).year - 1989
templates.env.globals["this_year_in_heisei"] = this_year_in_heisei
def get_daily_quote() -> str:
seed = str(datetime.now(timezone.utc).date())
with Path.cwd().joinpath("public", "quotes.txt").open("r") as f:
@@ -142,88 +140,6 @@ async def thumbnail(request: Request, path: str) -> Response:
png = resvg_py.svg_to_bytes(svg, font_files=font_files, width=1200, height=630)
return Response(content=png, media_type="image/png")
@app.api_route("/tools/tls-test/", methods=["GET"])
async def tls_test_index(request: Request) -> Response:
return templates.TemplateResponse(request=request, name="tools/tls-test/index.html")
@app.api_route("/tools/tls-test/", methods=["POST"])
async def tls_test_submit(request: Request) -> Response:
form = await request.form()
test_id, err = tls_submit(request, str(form.get("target", "")).strip(), tls_test_db, tls_test_queue, templates)
if err:
return err
return RedirectResponse(url=f"/tools/tls-test/status/{test_id}/", status_code=303)
@app.api_route("/tools/tls-test/status/{test_id}/", methods=["GET"])
async def tls_test_status_page(request: Request, test_id: str) -> Response:
job = tls_test_db.get_job(test_id)
if not job:
return error_page(templates, request, 404, "指定されたテストが見つかりません。", "…id間違ってない?")
if job.get("status") == "done":
return RedirectResponse(url=f"/tools/tls-test/results/{test_id}/", status_code=303)
return templates.TemplateResponse(
request=request,
name="tools/tls-test/status.html",
context={"test_id": test_id, "target": job.get("target", ""), "status": job.get("status", ""), "progress_entries": tls_test_db.get_progress(test_id)},
)
@app.api_route("/tools/tls-test/results/{test_id}/", methods=["GET"])
async def tls_test_results_page(request: Request, test_id: str) -> Response:
job = tls_test_db.get_job(test_id)
if not job:
return error_page(templates, request, 404, "指定されたテストが見つかりません。", "…id間違ってない?")
if job.get("status") != "done":
return RedirectResponse(url=f"/tools/tls-test/status/{test_id}/", status_code=303)
return templates.TemplateResponse(request=request, name="tools/tls-test/results.html", context=tls_results_context(job, test_id, request, tls_test_db))
@app.websocket("/tools/tls-test/ws/{test_id}")
async def tls_test_ws(websocket: WebSocket, test_id: str):
await tls_websocket_handler(websocket, test_id, tls_test_db, tls_test_queue)
@app.api_route("/api/tools/tls-test/scan", methods=["POST"])
async def tls_test_api_scan(request: Request) -> Response:
try:
payload = await request.json()
except Exception:
return JSONResponse({"error": "invalid JSON"}, status_code=400)
test_id, err = tls_api_submit(request, str(payload.get("target", "")), tls_test_db, tls_test_queue)
if err:
return JSONResponse(err[0], status_code=err[1])
return JSONResponse({
"id": test_id,
"status_url": f"/tools/tls-test/status/{test_id}/",
"results_url": f"/tools/tls-test/results/{test_id}/",
"ws_url": f"/tools/tls-test/ws/{test_id}",
})
@app.api_route("/api/tools/tls-test/status/{test_id}", methods=["GET"])
async def tls_test_api_status(request: Request, test_id: str) -> Response:
job = tls_test_db.get_job(test_id)
if not job:
return JSONResponse({"error": "not found"}, status_code=404)
progress = tls_test_db.get_progress(test_id)
return JSONResponse({
"id": test_id,
"target": job.get("target"),
"status": job.get("status"),
"rank": job.get("rank"),
"score": job.get("score"),
"created_at": job.get("created_at"),
"started_at": job.get("started_at"),
"finished_at": job.get("finished_at"),
"progress": progress,
"error": job.get("error_message"),
})
@app.api_route("/api/tools/tls-test/results/{test_id}", methods=["GET"])
async def tls_test_api_results(request: Request, test_id: str) -> Response:
job = tls_test_db.get_job(test_id)
if not job:
return JSONResponse({"error": "not found"}, status_code=404)
if job.get("status") != "done":
return JSONResponse({"error": "not ready", "status": job.get("status")}, status_code=409)
return JSONResponse(job.get("result") or {})
@app.api_route("/{full_path:path}", methods=["GET", "POST", "HEAD"])
async def default_response(request: Request, full_path: str) -> Response:
if not full_path.endswith(".html") and not full_path.endswith(".md"):