@@ -15,19 +15,17 @@ use std::time::{Duration, Instant};
1515
1616use axum:: {
1717 body:: Body ,
18- error_handling:: HandleErrorLayer ,
1918 extract:: { Path as AxumPath , Query , State } ,
2019 http:: { header, StatusCode } ,
20+ middleware:: { from_fn, Next } ,
2121 response:: { IntoResponse , Response } ,
2222 routing:: { get, post} ,
23- BoxError ,
2423 Router ,
2524} ;
2625use base64:: Engine ;
2726use hex;
2827use serde:: Deserialize ;
2928use tokio:: process:: Command ;
30- use tower:: ServiceBuilder ;
3129use tower_http:: limit:: RequestBodyLimitLayer ;
3230use tracing:: { error, info, warn} ;
3331
@@ -1917,33 +1915,36 @@ pub fn git_router(state: Arc<AppState>) -> Router {
19171915 . route ( "/git/{owner}/{repo}/info/refs" , get ( info_refs) )
19181916 . route ( "/git/{owner}/{repo}/git-upload-pack" , post ( upload_pack) )
19191917 . route ( "/git/{owner}/{repo}/git-receive-pack" , post ( receive_pack) )
1920- . layer (
1921- ServiceBuilder :: new ( )
1922- . layer ( HandleErrorLayer :: new ( move |err : BoxError | async move {
1923- git_body_limit_response ( err, max_bytes)
1924- } ) )
1925- . layer ( RequestBodyLimitLayer :: new ( body_limit) ) ,
1926- )
1918+ . layer ( from_fn ( move |req, next| {
1919+ rewrite_git_body_limit_413 ( req, next, max_bytes)
1920+ } ) )
1921+ . layer ( RequestBodyLimitLayer :: new ( body_limit) )
19271922 . with_state ( state)
19281923}
19291924
1930- fn git_body_limit_response ( err : BoxError , max_bytes : u64 ) -> Response {
1931- let msg = err. to_string ( ) ;
1932- if msg. contains ( "length limit" ) || msg. contains ( "LengthLimitError" ) {
1925+ /// `RequestBodyLimitLayer` returns a bare 413; rewrite the body so operators
1926+ /// see which env var to raise (and so proxies don't look like TLS aborts).
1927+ async fn rewrite_git_body_limit_413 (
1928+ req : axum:: extract:: Request ,
1929+ next : Next ,
1930+ max_bytes : u64 ,
1931+ ) -> Response {
1932+ let response = next. run ( req) . await ;
1933+ if response. status ( ) == StatusCode :: PAYLOAD_TOO_LARGE {
19331934 return (
19341935 StatusCode :: PAYLOAD_TOO_LARGE ,
1935- format ! (
1936- "git pack body exceeds relay limit ({max_bytes} bytes; \
1937- self-hosted relays: BUZZ_GIT_MAX_PACK_BYTES)"
1938- ) ,
1936+ git_body_limit_message ( max_bytes) ,
19391937 )
19401938 . into_response ( ) ;
19411939 }
1942- (
1943- StatusCode :: INTERNAL_SERVER_ERROR ,
1944- "failed to read git request body" ,
1940+ response
1941+ }
1942+
1943+ fn git_body_limit_message ( max_bytes : u64 ) -> String {
1944+ format ! (
1945+ "git pack body exceeds relay limit ({max_bytes} bytes; \
1946+ self-hosted relays: BUZZ_GIT_MAX_PACK_BYTES)"
19451947 )
1946- . into_response ( )
19471948}
19481949
19491950#[ cfg( test) ]
@@ -1985,12 +1986,10 @@ mod track_c_tests {
19851986 }
19861987
19871988 #[ test]
1988- fn git_body_limit_response_maps_length_errors_to_413 ( ) {
1989- let response = git_body_limit_response (
1990- Box :: new ( std:: io:: Error :: other ( "LengthLimitError" ) ) ,
1991- 5_242_880 ,
1992- ) ;
1993- assert_eq ! ( response. status( ) , StatusCode :: PAYLOAD_TOO_LARGE ) ;
1989+ fn git_body_limit_message_names_env_var ( ) {
1990+ let msg = git_body_limit_message ( 5_242_880 ) ;
1991+ assert ! ( msg. contains( "5242880" ) ) ;
1992+ assert ! ( msg. contains( "BUZZ_GIT_MAX_PACK_BYTES" ) ) ;
19941993 }
19951994
19961995 /// Without a gzip `Content-Encoding`, the body is passed through byte
0 commit comments