1+ use brotli:: enc:: BrotliEncoderParams ;
2+ use brotli:: BrotliCompress ;
13use std:: collections:: HashMap ;
24use std:: net:: SocketAddr ;
35use std:: path:: Path ;
@@ -313,6 +315,19 @@ async fn serve_req(server: Server, req: Request) -> Result<Response, ServerError
313315 let path = req. uri ( ) . path ( ) . to_owned ( ) ;
314316 let path = path. as_str ( ) ;
315317
318+ let allow_compression = req
319+ . headers ( )
320+ . get ( hyper:: header:: ACCEPT_ENCODING )
321+ . map_or ( false , |e| e. to_str ( ) . unwrap ( ) . contains ( "br" ) ) ;
322+
323+ let compression = if allow_compression {
324+ let mut brotli = BrotliEncoderParams :: default ( ) ;
325+ brotli. quality = 4 ;
326+ Some ( brotli)
327+ } else {
328+ None
329+ } ;
330+
316331 if let Some ( response) = handle_fs_path ( path) {
317332 return Ok ( response) ;
318333 }
@@ -404,6 +419,7 @@ async fn serve_req(server: Server, req: Request) -> Result<Response, ServerError
404419 crate :: comparison:: handle_compare ( check ! ( parse_body( & body) ) , & ctxt)
405420 . await
406421 . map_err ( |e| e. to_string ( ) ) ,
422+ & compression,
407423 ) ) ,
408424 "/perf/collected" => {
409425 if !server. check_auth ( & req) {
@@ -412,7 +428,10 @@ async fn serve_req(server: Server, req: Request) -> Result<Response, ServerError
412428 . body ( hyper:: Body :: empty ( ) )
413429 . unwrap ( ) ) ;
414430 }
415- Ok ( to_response ( request_handlers:: handle_collected ( ) . await ) )
431+ Ok ( to_response (
432+ request_handlers:: handle_collected ( ) . await ,
433+ & compression,
434+ ) )
416435 }
417436 "/perf/github-hook" => {
418437 if !verify_gh ( & ctxt. config , & req, & body) {
@@ -435,6 +454,7 @@ async fn serve_req(server: Server, req: Request) -> Result<Response, ServerError
435454 match event. as_str ( ) {
436455 "issue_comment" => Ok ( to_response (
437456 request_handlers:: handle_github ( check ! ( parse_body( & body) ) , ctxt. clone ( ) ) . await ,
457+ & compression,
438458 ) ) ,
439459 _ => Ok ( http:: Response :: builder ( )
440460 . status ( StatusCode :: OK )
@@ -444,9 +464,11 @@ async fn serve_req(server: Server, req: Request) -> Result<Response, ServerError
444464 }
445465 "/perf/self-profile" => Ok ( to_response (
446466 request_handlers:: handle_self_profile ( check ! ( parse_body( & body) ) , & ctxt) . await ,
467+ & compression,
447468 ) ) ,
448469 "/perf/self-profile-raw" => Ok ( to_response (
449470 request_handlers:: handle_self_profile_raw ( check ! ( parse_body( & body) ) , & ctxt) . await ,
471+ & compression,
450472 ) ) ,
451473 "/perf/bootstrap" => Ok (
452474 match request_handlers:: handle_bootstrap ( check ! ( parse_body( & body) ) , & ctxt) . await {
@@ -594,7 +616,7 @@ fn verify_gh_sig(cfg: &Config, header: &str, body: &[u8]) -> Option<bool> {
594616 Some ( false )
595617}
596618
597- fn to_response < S > ( result : ServerResult < S > ) -> Response
619+ fn to_response < S > ( result : ServerResult < S > , compression : & Option < BrotliEncoderParams > ) -> Response
598620where
599621 S : Serialize ,
600622{
@@ -604,7 +626,7 @@ where
604626 . header_typed ( ContentType :: octet_stream ( ) )
605627 . header_typed ( CacheControl :: new ( ) . with_no_cache ( ) . with_no_store ( ) ) ;
606628 let body = rmp_serde:: to_vec_named ( & result) . unwrap ( ) ;
607- response. body ( hyper :: Body :: from ( body ) ) . unwrap ( )
629+ maybe_compressed_response ( response, body, compression )
608630 }
609631 Err ( err) => http:: Response :: builder ( )
610632 . status ( StatusCode :: INTERNAL_SERVER_ERROR )
@@ -615,6 +637,30 @@ where
615637 }
616638}
617639
640+ fn maybe_compressed_response (
641+ response : http:: response:: Builder ,
642+ body : Vec < u8 > ,
643+ compression : & Option < BrotliEncoderParams > ,
644+ ) -> Response {
645+ match compression {
646+ None => response. body ( hyper:: Body :: from ( body) ) . unwrap ( ) ,
647+ Some ( brotli_params) => {
648+ let compressed = compress_bytes ( & body, brotli_params) ;
649+ let response = response. header (
650+ hyper:: header:: CONTENT_ENCODING ,
651+ hyper:: header:: HeaderValue :: from_static ( "br" ) ,
652+ ) ;
653+ response. body ( hyper:: Body :: from ( compressed) ) . unwrap ( )
654+ }
655+ }
656+ }
657+
658+ fn compress_bytes ( mut bytes : & [ u8 ] , brotli_params : & BrotliEncoderParams ) -> Vec < u8 > {
659+ let mut compressed = Vec :: with_capacity ( bytes. len ( ) ) ;
660+ BrotliCompress ( & mut bytes, & mut compressed, brotli_params) . unwrap ( ) ;
661+ compressed
662+ }
663+
618664fn to_triage_response ( result : ServerResult < api:: triage:: Response > ) -> Response {
619665 match result {
620666 Ok ( result) => {
0 commit comments