1- use super :: { IntoResponseParts , Response , ResponseParts } ;
1+ use super :: { ForceStatusCode , IntoResponseFailed , IntoResponseParts , Response , ResponseParts } ;
22use crate :: { body:: Body , BoxError } ;
33use bytes:: { buf:: Chain , Buf , Bytes , BytesMut } ;
44use http:: {
@@ -329,7 +329,9 @@ where
329329{
330330 fn into_response ( self ) -> Response {
331331 let mut res = self . 1 . into_response ( ) ;
332- * res. status_mut ( ) = self . 0 ;
332+ if res. extensions ( ) . get :: < IntoResponseFailed > ( ) . is_none ( ) {
333+ * res. status_mut ( ) = self . 0 ;
334+ }
333335 res
334336 }
335337}
@@ -405,18 +407,16 @@ macro_rules! impl_into_response {
405407 let ( $( $ty) ,* , res) = self ;
406408
407409 let res = res. into_response( ) ;
408- let parts = ResponseParts { res } ;
409-
410- $(
411- let parts = match $ty. into_response_parts( parts) {
410+ if res. extensions( ) . get:: <IntoResponseFailed >( ) . is_none( ) {
411+ let parts = ResponseParts { res } ;
412+ let parts = match ( $( $ty, ) * ) . into_response_parts( parts) {
412413 Ok ( parts) => parts,
413- Err ( err) => {
414- return err. into_response( ) ;
415- }
414+ Err ( err) => return err. into_response( ) ,
416415 } ;
417- ) *
418-
419- parts. res
416+ parts. res
417+ } else {
418+ res
419+ }
420420 }
421421 }
422422
@@ -430,16 +430,40 @@ macro_rules! impl_into_response {
430430 let ( status, $( $ty) ,* , res) = self ;
431431
432432 let res = res. into_response( ) ;
433- let parts = ResponseParts { res } ;
434-
435- $(
436- let parts = match $ty. into_response_parts( parts) {
433+ if res. extensions( ) . get:: <IntoResponseFailed >( ) . is_none( ) {
434+ let parts = ResponseParts { res } ;
435+ let mut parts = match ( $( $ty, ) * ) . into_response_parts( parts) {
437436 Ok ( parts) => parts,
438- Err ( err) => {
439- return err. into_response( ) ;
440- }
437+ Err ( err) => return err. into_response( ) ,
441438 } ;
442- ) *
439+
440+ // Don't call `(status, parts.res).into_response()` since that checks for
441+ // `IntoResponseFailed` and skips setting the status. We've already done that
442+ // check here so overriding the status is required if returning
443+ // `(IntoResponseFailed, StatusCode::INTERNAL_SERVER_ERROR)`
444+ * parts. res. status_mut( ) = status;
445+ parts. res
446+ } else {
447+ res
448+ }
449+ }
450+ }
451+
452+ #[ allow( non_snake_case) ]
453+ impl <R , $( $ty, ) * > IntoResponse for ( ForceStatusCode , $( $ty) ,* , R )
454+ where
455+ $( $ty: IntoResponseParts , ) *
456+ R : IntoResponse ,
457+ {
458+ fn into_response( self ) -> Response {
459+ let ( status, $( $ty) ,* , res) = self ;
460+
461+ let res = res. into_response( ) ;
462+ let parts = ResponseParts { res } ;
463+ let parts = match ( $( $ty, ) * ) . into_response_parts( parts) {
464+ Ok ( parts) => parts,
465+ Err ( err) => return err. into_response( ) ,
466+ } ;
443467
444468 ( status, parts. res) . into_response( )
445469 }
@@ -455,17 +479,22 @@ macro_rules! impl_into_response {
455479 let ( outer_parts, $( $ty) ,* , res) = self ;
456480
457481 let res = res. into_response( ) ;
458- let parts = ResponseParts { res } ;
459- $ (
460- let parts = match $ty . into_response_parts( parts) {
482+ if res. extensions ( ) . get :: < IntoResponseFailed > ( ) . is_none ( ) {
483+ let parts = ResponseParts { res } ;
484+ let mut parts = match ( $ ( $ty , ) * ) . into_response_parts( parts) {
461485 Ok ( parts) => parts,
462- Err ( err) => {
463- return err. into_response( ) ;
464- }
486+ Err ( err) => return err. into_response( ) ,
465487 } ;
466- ) *
467488
468- ( outer_parts, parts. res) . into_response( )
489+ // Don't call `(outer_parts, parts.res).into_response()` for the same reason we
490+ // don't call `(status, parts.res).into_response()` in the above impl.
491+ * parts. res. status_mut( ) = outer_parts. status;
492+ parts. res. headers_mut( ) . extend( outer_parts. headers) ;
493+ parts. res. extensions_mut( ) . extend( outer_parts. extensions) ;
494+ parts. res
495+ } else {
496+ res
497+ }
469498 }
470499 }
471500
0 commit comments