1
1
//! Process HTTP connections on the server.
2
2
3
+ use async_std:: future:: Future ;
3
4
use async_std:: io:: { self , BufReader } ;
5
+ use async_std:: io:: { Read , Write } ;
4
6
use async_std:: prelude:: * ;
5
7
use async_std:: task:: { Context , Poll } ;
6
8
use futures_core:: ready;
7
- use futures_io:: AsyncRead ;
8
9
use http:: { Request , Response , Version } ;
10
+ use std:: time:: { Duration , Instant } ;
9
11
10
12
use std:: pin:: Pin ;
11
13
12
14
use crate :: { Body , Exception , MAX_HEADERS } ;
13
15
16
+ pub async fn connect < ' a , F , Fut , R , W , O : ' a > (
17
+ reader : & ' a mut R ,
18
+ writer : & ' a mut W ,
19
+ callback : F ,
20
+ ) -> Result < ( ) , Exception >
21
+ where
22
+ R : Read + Unpin + Send ,
23
+ W : Write + Unpin ,
24
+ F : Fn ( & mut Request < Body < BufReader < & ' a mut R > > > ) -> Fut ,
25
+ Fut : Future < Output = Result < Response < Body < O > > , Exception > > ,
26
+ O : Read + Unpin + Send ,
27
+ {
28
+ let req = decode ( reader) . await ?;
29
+ if let RequestOrReader :: Request ( mut req) = req {
30
+ let headers = req. headers ( ) ;
31
+ let timeout = match ( headers. get ( "Connection" ) , headers. get ( "Keep-Alive" ) ) {
32
+ ( Some ( connection) , Some ( _v) )
33
+ if connection == http:: header:: HeaderValue :: from_static ( "Keep-Alive" ) =>
34
+ {
35
+ // TODO: parse timeout
36
+ Duration :: from_secs ( 5 )
37
+ }
38
+ _ => Duration :: from_secs ( 5 ) ,
39
+ } ;
40
+
41
+ let beginning = Instant :: now ( ) ;
42
+ loop {
43
+ // TODO: what to do when the callback returns Err
44
+ let mut res = encode ( callback ( & mut req) . await ?) . await ?;
45
+ io:: copy ( & mut res, writer) . await ?;
46
+ let mut stream = req. into_body ( ) . into_reader ( ) . into_inner ( ) ;
47
+ req = loop {
48
+ match decode ( stream) . await ? {
49
+ RequestOrReader :: Request ( r) => break r,
50
+ RequestOrReader :: Reader ( r) => {
51
+ let now = Instant :: now ( ) ;
52
+ if now - beginning > timeout {
53
+ return Ok ( ( ) ) ;
54
+ }
55
+ stream = r;
56
+ }
57
+ }
58
+ } ;
59
+ }
60
+ }
61
+
62
+ Ok ( ( ) )
63
+ }
64
+
14
65
/// A streaming HTTP encoder.
15
66
///
16
67
/// This is returned from [`encode`].
17
68
#[ derive( Debug ) ]
18
- pub struct Encoder < R : AsyncRead > {
69
+ pub struct Encoder < R : Read > {
19
70
/// Keep track how far we've indexed into the headers + body.
20
71
cursor : usize ,
21
72
/// HTTP headers to be sent.
@@ -30,7 +81,7 @@ pub struct Encoder<R: AsyncRead> {
30
81
body_bytes_read : usize ,
31
82
}
32
83
33
- impl < R : AsyncRead > Encoder < R > {
84
+ impl < R : Read > Encoder < R > {
34
85
/// Create a new instance.
35
86
pub ( crate ) fn new ( headers : Vec < u8 > , body : Body < R > ) -> Self {
36
87
Self {
@@ -44,7 +95,7 @@ impl<R: AsyncRead> Encoder<R> {
44
95
}
45
96
}
46
97
47
- impl < R : AsyncRead + Unpin > AsyncRead for Encoder < R > {
98
+ impl < R : Read + Unpin > Read for Encoder < R > {
48
99
fn poll_read (
49
100
mut self : Pin < & mut Self > ,
50
101
cx : & mut Context < ' _ > ,
@@ -81,43 +132,49 @@ impl<R: AsyncRead + Unpin> AsyncRead for Encoder<R> {
81
132
// TODO: return a reader in the response
82
133
pub async fn encode < R > ( res : Response < Body < R > > ) -> io:: Result < Encoder < R > >
83
134
where
84
- R : AsyncRead ,
135
+ R : Read + Send ,
85
136
{
86
137
let mut buf: Vec < u8 > = vec ! [ ] ;
87
138
88
139
let reason = res. status ( ) . canonical_reason ( ) . unwrap ( ) ;
89
140
let status = res. status ( ) ;
90
- write ! ( & mut buf, "HTTP/1.1 {} {}\r \n " , status. as_str( ) , reason) . await ?;
141
+ std:: io:: Write :: write_fmt (
142
+ & mut buf,
143
+ format_args ! ( "HTTP/1.1 {} {}\r \n " , status. as_str( ) , reason) ,
144
+ ) ?;
91
145
92
146
// If the body isn't streaming, we can set the content-length ahead of time. Else we need to
93
147
// send all items in chunks.
94
148
if let Some ( len) = res. body ( ) . len ( ) {
95
- write ! ( & mut buf, "Content-Length: {}\r \n " , len) . await ?;
149
+ std :: io :: Write :: write_fmt ( & mut buf, format_args ! ( "Content-Length: {}\r \n " , len) ) ?;
96
150
} else {
97
- write ! ( & mut buf, "Transfer-Encoding: chunked\r \n " ) . await ?;
151
+ std :: io :: Write :: write_fmt ( & mut buf, format_args ! ( "Transfer-Encoding: chunked\r \n " ) ) ?;
98
152
panic ! ( "chunked encoding is not implemented yet" ) ;
99
153
// See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding
100
154
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Trailer
101
155
}
102
156
103
157
for ( header, value) in res. headers ( ) {
104
- write ! (
158
+ std :: io :: Write :: write_fmt (
105
159
& mut buf,
106
- "{}: {}\r \n " ,
107
- header. as_str( ) ,
108
- value. to_str( ) . unwrap( )
109
- )
110
- . await ?;
160
+ format_args ! ( "{}: {}\r \n " , header. as_str( ) , value. to_str( ) . unwrap( ) ) ,
161
+ ) ?
111
162
}
112
163
113
- write ! ( & mut buf, "\r \n " ) . await ?;
164
+ std :: io :: Write :: write_fmt ( & mut buf, format_args ! ( "\r \n " ) ) ?;
114
165
Ok ( Encoder :: new ( buf, res. into_body ( ) ) )
115
166
}
116
167
168
+ #[ derive( Debug ) ]
169
+ pub enum RequestOrReader < R : Read > {
170
+ Request ( Request < Body < BufReader < R > > > ) ,
171
+ Reader ( R ) ,
172
+ }
173
+
117
174
/// Decode an HTTP request on the server.
118
- pub async fn decode < R > ( reader : R ) -> Result < Option < Request < Body < BufReader < R > > > > , Exception >
175
+ pub async fn decode < R > ( reader : R ) -> Result < RequestOrReader < R > , Exception >
119
176
where
120
- R : AsyncRead + Unpin + Send ,
177
+ R : Read + Unpin + Send ,
121
178
{
122
179
let mut reader = BufReader :: new ( reader) ;
123
180
let mut buf = Vec :: new ( ) ;
@@ -129,7 +186,7 @@ where
129
186
let bytes_read = reader. read_until ( b'\n' , & mut buf) . await ?;
130
187
// No more bytes are yielded from the stream.
131
188
if bytes_read == 0 {
132
- return Ok ( None ) ;
189
+ return Ok ( RequestOrReader :: Reader ( reader . into_inner ( ) ) ) ;
133
190
}
134
191
135
192
// We've hit the end delimiter of the stream.
@@ -171,9 +228,9 @@ where
171
228
. find ( |h| h. name == "Content-Length" )
172
229
{
173
230
Some ( _header) => Body :: new ( reader) , // TODO: use the header value
174
- None => Body :: empty ( ) ,
231
+ None => Body :: empty ( reader ) ,
175
232
} ;
176
233
177
234
// Return the request.
178
- Ok ( Some ( req. body ( body) ?) )
235
+ Ok ( RequestOrReader :: Request ( req. body ( body) ?) )
179
236
}
0 commit comments