1
1
//! Process HTTP connections on the server.
2
2
3
- use std:: time:: Duration ;
4
-
5
3
use async_std:: future:: { timeout, Future , TimeoutError } ;
6
4
use async_std:: io:: { self , Read , Write } ;
7
5
use http_types:: headers:: { CONNECTION , UPGRADE } ;
8
6
use http_types:: upgrade:: Connection ;
9
7
use http_types:: { Request , Response , StatusCode } ;
10
-
8
+ use std:: { marker:: PhantomData , time:: Duration } ;
9
+ mod body_reader;
11
10
mod decode;
12
11
mod encode;
13
12
@@ -38,14 +37,14 @@ where
38
37
F : Fn ( Request ) -> Fut ,
39
38
Fut : Future < Output = http_types:: Result < Response > > ,
40
39
{
41
- accept_with_opts ( io, endpoint, Default :: default ( ) ) . await
40
+ Server :: new ( io, endpoint) . accept ( ) . await
42
41
}
43
42
44
43
/// Accept a new incoming HTTP/1.1 connection.
45
44
///
46
45
/// Supports `KeepAlive` requests by default.
47
46
pub async fn accept_with_opts < RW , F , Fut > (
48
- mut io : RW ,
47
+ io : RW ,
49
48
endpoint : F ,
50
49
opts : ServerOptions ,
51
50
) -> http_types:: Result < ( ) >
@@ -54,35 +53,99 @@ where
54
53
F : Fn ( Request ) -> Fut ,
55
54
Fut : Future < Output = http_types:: Result < Response > > ,
56
55
{
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
+ {
58
113
// 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 ( ) ) ;
60
115
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 {
62
117
match timeout ( timeout_duration, fut) . await {
63
118
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 */
65
120
Ok ( Err ( e) ) => return Err ( e) ,
66
121
}
67
122
} else {
68
123
match fut. await ? {
69
124
Some ( r) => r,
70
- None => break , /* EOF */
125
+ None => return Ok ( ConnectionStatus :: Close ) , /* EOF */
71
126
}
72
127
} ;
73
128
74
129
let has_upgrade_header = req. header ( UPGRADE ) . is_some ( ) ;
75
- let connection_header_is_upgrade = req
130
+ let connection_header_as_str = req
76
131
. 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" ) ;
79
137
80
138
let upgrade_requested = has_upgrade_header && connection_header_is_upgrade;
81
139
82
140
let method = req. method ( ) ;
83
141
84
142
// 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 ) ;
86
149
87
150
let upgrade_provided = res. status ( ) == StatusCode :: SwitchingProtocols && res. has_upgrade ( ) ;
88
151
@@ -94,14 +157,22 @@ where
94
157
95
158
let mut encoder = Encoder :: new ( res, method) ;
96
159
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
+ ) ;
99
168
100
169
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 )
103
176
}
104
177
}
105
-
106
- Ok ( ( ) )
107
178
}
0 commit comments