@@ -2,6 +2,8 @@ use std::mem::MaybeUninit;
22
33#[ cfg( feature = "client" ) ]
44use std:: fmt:: { self , Write as _} ;
5+ #[ cfg( feature = "server" ) ]
6+ use std:: sync:: Arc ;
57
68use bytes:: Bytes ;
79use bytes:: BytesMut ;
@@ -16,6 +18,8 @@ use smallvec::{smallvec, smallvec_inline, SmallVec};
1618use crate :: body:: DecodedLength ;
1719#[ cfg( feature = "server" ) ]
1820use crate :: common:: date;
21+ #[ cfg( feature = "server" ) ]
22+ use crate :: error:: Kind ;
1923use crate :: error:: Parse ;
2024use crate :: ext:: HeaderCaseMap ;
2125#[ cfg( feature = "ffi" ) ]
@@ -27,6 +31,8 @@ use crate::proto::h1::{
2731#[ cfg( feature = "client" ) ]
2832use crate :: proto:: RequestHead ;
2933use crate :: proto:: { BodyLength , MessageHead , RequestLine } ;
34+ #[ cfg( feature = "server" ) ]
35+ use crate :: server:: conn:: http1:: Http1ErrorResponder ;
3036
3137pub ( crate ) const DEFAULT_MAX_HEADERS : usize = 100 ;
3238const AVERAGE_HEADER_SIZE : usize = 30 ; // totally scientific
@@ -127,6 +133,30 @@ pub(crate) enum Client {}
127133#[ cfg( feature = "server" ) ]
128134pub ( crate ) enum Server { }
129135
136+ #[ cfg( feature = "server" ) ]
137+ pub ( crate ) fn default_error_response ( kind : & Kind ) -> Option < crate :: Response < ( ) > > {
138+ use crate :: error:: Kind ;
139+ use crate :: error:: Parse ;
140+ use http:: StatusCode ;
141+ let status = match kind {
142+ Kind :: Parse ( Parse :: Method )
143+ | Kind :: Parse ( Parse :: Header ( _) )
144+ | Kind :: Parse ( Parse :: Uri )
145+ | Kind :: Parse ( Parse :: Version ) => StatusCode :: BAD_REQUEST ,
146+ Kind :: Parse ( Parse :: TooLarge ) => StatusCode :: REQUEST_HEADER_FIELDS_TOO_LARGE ,
147+ Kind :: Parse ( Parse :: UriTooLong ) => StatusCode :: URI_TOO_LONG ,
148+ _ => return None ,
149+ } ;
150+
151+ debug ! ( "building automatic response ({}) for parse error" , status) ;
152+ let msg = MessageHead {
153+ subject : status,
154+ ..Default :: default ( )
155+ }
156+ . into_response ( ( ) ) ;
157+ Some ( msg)
158+ }
159+
130160#[ cfg( feature = "server" ) ]
131161impl Http1Transaction for Server {
132162 type Incoming = RequestLine ;
@@ -460,24 +490,19 @@ impl Http1Transaction for Server {
460490 ret. map ( |( ) | encoder)
461491 }
462492
463- fn on_error ( err : & crate :: Error ) -> Option < MessageHead < Self :: Outgoing > > {
464- use crate :: error:: Kind ;
465- let status = match * err. kind ( ) {
466- Kind :: Parse ( Parse :: Method )
467- | Kind :: Parse ( Parse :: Header ( _) )
468- | Kind :: Parse ( Parse :: Uri )
469- | Kind :: Parse ( Parse :: Version ) => StatusCode :: BAD_REQUEST ,
470- Kind :: Parse ( Parse :: TooLarge ) => StatusCode :: REQUEST_HEADER_FIELDS_TOO_LARGE ,
471- Kind :: Parse ( Parse :: UriTooLong ) => StatusCode :: URI_TOO_LONG ,
472- _ => return None ,
473- } ;
474-
475- debug ! ( "sending automatic response ({}) for parse error" , status) ;
476- let msg = MessageHead {
477- subject : status,
478- ..Default :: default ( )
479- } ;
480- Some ( msg)
493+ fn on_error (
494+ err : & crate :: Error ,
495+ responder : & Option < Arc < dyn Http1ErrorResponder > > ,
496+ ) -> Option < MessageHead < Self :: Outgoing > > {
497+ use crate :: server:: conn:: http1:: Http1ErrorReason ;
498+ let reason = Http1ErrorReason :: from_kind ( err. kind ( ) ) ;
499+ responder
500+ . as_ref ( )
501+ . map_or_else (
502+ || default_error_response ( err. kind ( ) ) ,
503+ |er| er. respond ( & reason) ,
504+ )
505+ . map ( |rsp| MessageHead :: from_response ( rsp) )
481506 }
482507
483508 fn is_server ( ) -> bool {
@@ -1216,7 +1241,10 @@ impl Http1Transaction for Client {
12161241 Ok ( body)
12171242 }
12181243
1219- fn on_error ( _err : & crate :: Error ) -> Option < MessageHead < Self :: Outgoing > > {
1244+ fn on_error (
1245+ _err : & crate :: Error ,
1246+ #[ cfg( feature = "server" ) ] _responder : & Option < Arc < dyn Http1ErrorResponder > > ,
1247+ ) -> Option < MessageHead < Self :: Outgoing > > {
12201248 // we can't tell the server about any errors it creates
12211249 None
12221250 }
0 commit comments