11//! Process HTTP connections on the server.
22
3- use std:: time:: Duration ;
4-
53use async_std:: future:: { timeout, Future , TimeoutError } ;
64use async_std:: io:: { self , Read , Write } ;
75use http_types:: headers:: { CONNECTION , UPGRADE } ;
86use http_types:: upgrade:: Connection ;
97use http_types:: { Request , Response , StatusCode } ;
10-
8+ use std:: { marker:: PhantomData , time:: Duration } ;
9+ mod body_reader;
1110mod decode;
1211mod encode;
1312
@@ -38,14 +37,14 @@ where
3837 F : Fn ( Request ) -> Fut ,
3938 Fut : Future < Output = http_types:: Result < Response > > ,
4039{
41- accept_with_opts ( io, endpoint, Default :: default ( ) ) . await
40+ Server :: new ( io, endpoint) . accept ( ) . await
4241}
4342
4443/// Accept a new incoming HTTP/1.1 connection.
4544///
4645/// Supports `KeepAlive` requests by default.
4746pub async fn accept_with_opts < RW , F , Fut > (
48- mut io : RW ,
47+ io : RW ,
4948 endpoint : F ,
5049 opts : ServerOptions ,
5150) -> http_types:: Result < ( ) >
@@ -54,35 +53,99 @@ where
5453 F : Fn ( Request ) -> Fut ,
5554 Fut : Future < Output = http_types:: Result < Response > > ,
5655{
57- loop {
56+ Server :: new ( io, endpoint) . with_opts ( opts) . accept ( ) . await
57+ }
58+
59+ /// struct for server
60+ #[ derive( Debug ) ]
61+ pub struct Server < RW , F , Fut > {
62+ io : RW ,
63+ endpoint : F ,
64+ opts : ServerOptions ,
65+ _phantom : PhantomData < Fut > ,
66+ }
67+
68+ /// An enum that represents whether the server should accept a subsequent request
69+ #[ derive( Debug , Copy , Clone , Eq , PartialEq ) ]
70+ pub enum ConnectionStatus {
71+ /// The server should not accept another request
72+ Close ,
73+
74+ /// The server may accept another request
75+ KeepAlive ,
76+ }
77+
78+ impl < RW , F , Fut > Server < RW , F , Fut >
79+ where
80+ RW : Read + Write + Clone + Send + Sync + Unpin + ' static ,
81+ F : Fn ( Request ) -> Fut ,
82+ Fut : Future < Output = http_types:: Result < Response > > ,
83+ {
84+ /// builds a new server
85+ pub fn new ( io : RW , endpoint : F ) -> Self {
86+ Self {
87+ io,
88+ endpoint,
89+ opts : Default :: default ( ) ,
90+ _phantom : PhantomData ,
91+ }
92+ }
93+
94+ /// with opts
95+ pub fn with_opts ( mut self , opts : ServerOptions ) -> Self {
96+ self . opts = opts;
97+ self
98+ }
99+
100+ /// accept in a loop
101+ pub async fn accept ( & mut self ) -> http_types:: Result < ( ) > {
102+ while ConnectionStatus :: KeepAlive == self . accept_one ( ) . await ? { }
103+ Ok ( ( ) )
104+ }
105+
106+ /// accept one request
107+ pub async fn accept_one ( & mut self ) -> http_types:: Result < ConnectionStatus >
108+ where
109+ RW : Read + Write + Clone + Send + Sync + Unpin + ' static ,
110+ F : Fn ( Request ) -> Fut ,
111+ Fut : Future < Output = http_types:: Result < Response > > ,
112+ {
58113 // Decode a new request, timing out if this takes longer than the timeout duration.
59- let fut = decode ( io. clone ( ) ) ;
114+ let fut = decode ( self . io . clone ( ) ) ;
60115
61- let req = if let Some ( timeout_duration) = opts. headers_timeout {
116+ let ( req, mut body ) = if let Some ( timeout_duration) = self . opts . headers_timeout {
62117 match timeout ( timeout_duration, fut) . await {
63118 Ok ( Ok ( Some ( r) ) ) => r,
64- Ok ( Ok ( None ) ) | Err ( TimeoutError { .. } ) => break , /* EOF or timeout */
119+ Ok ( Ok ( None ) ) | Err ( TimeoutError { .. } ) => return Ok ( ConnectionStatus :: Close ) , /* EOF or timeout */
65120 Ok ( Err ( e) ) => return Err ( e) ,
66121 }
67122 } else {
68123 match fut. await ? {
69124 Some ( r) => r,
70- None => break , /* EOF */
125+ None => return Ok ( ConnectionStatus :: Close ) , /* EOF */
71126 }
72127 } ;
73128
74129 let has_upgrade_header = req. header ( UPGRADE ) . is_some ( ) ;
75- let connection_header_is_upgrade = req
130+ let connection_header_as_str = req
76131 . header ( CONNECTION )
77- . map ( |connection| connection. as_str ( ) . eq_ignore_ascii_case ( "upgrade" ) )
78- . unwrap_or ( false ) ;
132+ . map ( |connection| connection. as_str ( ) )
133+ . unwrap_or ( "" ) ;
134+
135+ let connection_header_is_upgrade = connection_header_as_str. eq_ignore_ascii_case ( "upgrade" ) ;
136+ let mut close_connection = connection_header_as_str. eq_ignore_ascii_case ( "close" ) ;
79137
80138 let upgrade_requested = has_upgrade_header && connection_header_is_upgrade;
81139
82140 let method = req. method ( ) ;
83141
84142 // Pass the request to the endpoint and encode the response.
85- let mut res = endpoint ( req) . await ?;
143+ let mut res = ( self . endpoint ) ( req) . await ?;
144+
145+ close_connection |= res
146+ . header ( CONNECTION )
147+ . map ( |c| c. as_str ( ) . eq_ignore_ascii_case ( "close" ) )
148+ . unwrap_or ( false ) ;
86149
87150 let upgrade_provided = res. status ( ) == StatusCode :: SwitchingProtocols && res. has_upgrade ( ) ;
88151
@@ -94,14 +157,22 @@ where
94157
95158 let mut encoder = Encoder :: new ( res, method) ;
96159
97- // Stream the response to the writer.
98- io:: copy ( & mut encoder, & mut io) . await ?;
160+ let bytes_written = io:: copy ( & mut encoder, & mut self . io ) . await ?;
161+ log:: trace!( "wrote {} response bytes" , bytes_written) ;
162+
163+ let body_bytes_discarded = io:: copy ( & mut body, & mut io:: sink ( ) ) . await ?;
164+ log:: trace!(
165+ "discarded {} unread request body bytes" ,
166+ body_bytes_discarded
167+ ) ;
99168
100169 if let Some ( upgrade_sender) = upgrade_sender {
101- upgrade_sender. send ( Connection :: new ( io. clone ( ) ) ) . await ;
102- return Ok ( ( ) ) ;
170+ upgrade_sender. send ( Connection :: new ( self . io . clone ( ) ) ) . await ;
171+ return Ok ( ConnectionStatus :: Close ) ;
172+ } else if close_connection {
173+ Ok ( ConnectionStatus :: Close )
174+ } else {
175+ Ok ( ConnectionStatus :: KeepAlive )
103176 }
104177 }
105-
106- Ok ( ( ) )
107178}
0 commit comments