1
+ use brotli:: enc:: BrotliEncoderParams ;
2
+ use brotli:: BrotliCompress ;
1
3
use std:: collections:: HashMap ;
2
4
use std:: net:: SocketAddr ;
3
5
use std:: path:: Path ;
@@ -313,6 +315,19 @@ async fn serve_req(server: Server, req: Request) -> Result<Response, ServerError
313
315
let path = req. uri ( ) . path ( ) . to_owned ( ) ;
314
316
let path = path. as_str ( ) ;
315
317
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
+
316
331
if let Some ( response) = handle_fs_path ( path) {
317
332
return Ok ( response) ;
318
333
}
@@ -404,6 +419,7 @@ async fn serve_req(server: Server, req: Request) -> Result<Response, ServerError
404
419
crate :: comparison:: handle_compare ( check ! ( parse_body( & body) ) , & ctxt)
405
420
. await
406
421
. map_err ( |e| e. to_string ( ) ) ,
422
+ & compression,
407
423
) ) ,
408
424
"/perf/collected" => {
409
425
if !server. check_auth ( & req) {
@@ -412,7 +428,10 @@ async fn serve_req(server: Server, req: Request) -> Result<Response, ServerError
412
428
. body ( hyper:: Body :: empty ( ) )
413
429
. unwrap ( ) ) ;
414
430
}
415
- Ok ( to_response ( request_handlers:: handle_collected ( ) . await ) )
431
+ Ok ( to_response (
432
+ request_handlers:: handle_collected ( ) . await ,
433
+ & compression,
434
+ ) )
416
435
}
417
436
"/perf/github-hook" => {
418
437
if !verify_gh ( & ctxt. config , & req, & body) {
@@ -435,6 +454,7 @@ async fn serve_req(server: Server, req: Request) -> Result<Response, ServerError
435
454
match event. as_str ( ) {
436
455
"issue_comment" => Ok ( to_response (
437
456
request_handlers:: handle_github ( check ! ( parse_body( & body) ) , ctxt. clone ( ) ) . await ,
457
+ & compression,
438
458
) ) ,
439
459
_ => Ok ( http:: Response :: builder ( )
440
460
. status ( StatusCode :: OK )
@@ -444,9 +464,11 @@ async fn serve_req(server: Server, req: Request) -> Result<Response, ServerError
444
464
}
445
465
"/perf/self-profile" => Ok ( to_response (
446
466
request_handlers:: handle_self_profile ( check ! ( parse_body( & body) ) , & ctxt) . await ,
467
+ & compression,
447
468
) ) ,
448
469
"/perf/self-profile-raw" => Ok ( to_response (
449
470
request_handlers:: handle_self_profile_raw ( check ! ( parse_body( & body) ) , & ctxt) . await ,
471
+ & compression,
450
472
) ) ,
451
473
"/perf/bootstrap" => Ok (
452
474
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> {
594
616
Some ( false )
595
617
}
596
618
597
- fn to_response < S > ( result : ServerResult < S > ) -> Response
619
+ fn to_response < S > ( result : ServerResult < S > , compression : & Option < BrotliEncoderParams > ) -> Response
598
620
where
599
621
S : Serialize ,
600
622
{
@@ -604,7 +626,7 @@ where
604
626
. header_typed ( ContentType :: octet_stream ( ) )
605
627
. header_typed ( CacheControl :: new ( ) . with_no_cache ( ) . with_no_store ( ) ) ;
606
628
let body = rmp_serde:: to_vec_named ( & result) . unwrap ( ) ;
607
- response. body ( hyper :: Body :: from ( body ) ) . unwrap ( )
629
+ maybe_compressed_response ( response, body, compression )
608
630
}
609
631
Err ( err) => http:: Response :: builder ( )
610
632
. status ( StatusCode :: INTERNAL_SERVER_ERROR )
@@ -615,6 +637,30 @@ where
615
637
}
616
638
}
617
639
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
+
618
664
fn to_triage_response ( result : ServerResult < api:: triage:: Response > ) -> Response {
619
665
match result {
620
666
Ok ( result) => {
0 commit comments