One bounded HTTP client for every server-side fetch; uploads refused while streaming
Every outbound fetch - Gitea content at boot and on reload, the raw asset proxy, the repo-info endpoint, the content-declared url resource - built its own reqwest client with no timeout and read whole bodies with .text(). `crate::http` is now the one client (5 s connect, 20 s per request, 5 redirects) with capped body readers: 2 MB for a url resource, 8 MB for a Gitea reply, 32 MB for a proxied asset; one byte over is an error, never a truncated document. The upload handler read a whole field into memory before comparing it to the 20 MB cap, and axum's 2 MB default body limit had made that cap unreachable anyway. It now reads chunk by chunk and refuses the moment the cap is crossed; the /upload route raises the body limit to match. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L4jrCgLiKKHAEFuZUJjckH
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
d7f60eaa31
commit
c91bf59946
+7
-1
@@ -145,7 +145,13 @@ async fn main() -> anyhow::Result<()> {
|
||||
.route("/auth/callback", get(oidc::callback))
|
||||
.route("/auth/logout", get(oidc::logout))
|
||||
.route("/api/{*fn_name}", any(server_fn_handler))
|
||||
.route("/upload", post(upload::upload))
|
||||
// axum caps request bodies at 2 MB by default, which had made the
|
||||
// 20 MB upload limit unreachable; raise the fence on this route only,
|
||||
// with room for the multipart framing.
|
||||
.route(
|
||||
"/upload",
|
||||
post(upload::upload).layer(axum::extract::DefaultBodyLimit::max(upload::MAX_UPLOAD_BYTES + 64 * 1024)),
|
||||
)
|
||||
.route("/gitea-repo", get(content::gitea_repo_handler))
|
||||
// Content-shipped assets (hero module etc.), same-origin.
|
||||
.route("/site/{*path}", get(content::site_asset_handler))
|
||||
|
||||
Reference in New Issue
Block a user