Skip to content

Commit e16e2d4

Browse files
authored
Merge pull request #30 from yoshuawuyts/request-bug-2
Request bug 2
2 parents 1b2e769 + c9df37f commit e16e2d4

File tree

2 files changed

+21
-77
lines changed

2 files changed

+21
-77
lines changed

examples/server.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ async fn accept(addr: String, stream: TcpStream) -> Result<(), async_h1::Excepti
1616
// TODO: Delete this line when we implement `Clone` for `TcpStream`.
1717
let stream = Stream(Arc::new(stream));
1818

19-
server::accept(&addr, stream.clone(), stream, |_| {
20-
async {
19+
server::accept(&addr, stream.clone(), stream, |req| {
20+
async move {
21+
dbg!(req.method());
2122
let mut resp = Response::new(StatusCode::Ok);
2223
resp.insert_header(
2324
HeaderName::from_str("Content-Type")?,

src/server.rs

Lines changed: 18 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
//! Process HTTP connections on the server.
22
33
use async_std::future::{timeout, Future, TimeoutError};
4-
use async_std::io::{self, BufRead, BufReader};
4+
use async_std::io::{self, BufReader};
55
use async_std::io::{Read, Write};
66
use async_std::prelude::*;
77
use async_std::task::{Context, Poll};
88
use futures_core::ready;
9-
use http_types::{
10-
headers::{HeaderName, HeaderValue, CONTENT_TYPE},
11-
Body, Method, Request, Response,
12-
};
13-
use std::fmt;
9+
use http_types::headers::{HeaderName, HeaderValue, CONTENT_TYPE};
10+
use http_types::{Body, Method, Request, Response};
1411
use std::str::FromStr;
1512
use std::time::Duration;
1613

@@ -29,49 +26,34 @@ pub async fn accept<R, W, F, Fut>(
2926
endpoint: F,
3027
) -> Result<(), Exception>
3128
where
32-
R: Read + Unpin + Send + 'static,
29+
R: Read + Unpin + Send + 'static + Clone,
3330
W: Write + Unpin,
34-
F: Fn(&mut Request) -> Fut,
31+
F: Fn(Request) -> Fut,
3532
Fut: Future<Output = Result<Response, Exception>>,
3633
{
3734
// TODO: make configurable
3835
let timeout_duration = Duration::from_secs(10);
3936
const MAX_REQUESTS: usize = 200;
4037
let mut num_requests = 0;
4138

42-
// Decode a request. This may be the first of many since
43-
// the connection is Keep-Alive by default
44-
let decoded = decode(addr, reader).await?;
45-
// Decode returns one of three things;
46-
// * A request with its body reader set to the underlying TCP stream
47-
// * A request with an empty body AND the underlying stream
48-
// * No request (because of the stream closed) and no underlying stream
49-
if let Some(mut decoded) = decoded {
39+
// Decode a request. This may be the first of many since the connection is Keep-Alive by default.
40+
let r = reader.clone();
41+
let req = decode(addr, r).await?;
42+
if let Some(mut req) = req {
5043
loop {
51-
num_requests += 1;
52-
if num_requests > MAX_REQUESTS {
53-
// We've exceeded the max number of requests per connection
54-
return Ok(());
55-
}
44+
match num_requests {
45+
MAX_REQUESTS => return Ok(()),
46+
_ => num_requests += 1,
47+
};
5648

57-
// Pass the request to the user defined request handler endpoint.
58-
// Encode the response we get back.
5949
// TODO: what to do when the endpoint returns Err
60-
let res = endpoint(decoded.mut_request()).await?;
50+
let res = endpoint(req).await?;
6151
let mut encoder = Encoder::encode(res);
62-
63-
// If we have reference to the stream, unwrap it. Otherwise,
64-
// get the underlying stream from the request
65-
let to_decode = decoded.into_reader();
66-
67-
// Copy the response into the writer
68-
// TODO: don't double wrap BufReaders, but instead write a version of
69-
// io::copy that expects a BufReader.
7052
io::copy(&mut encoder, &mut writer).await?;
7153

7254
// Decode a new request, timing out if this takes longer than the
7355
// timeout duration.
74-
decoded = match timeout(timeout_duration, decode(addr, to_decode)).await {
56+
req = match timeout(timeout_duration, decode(addr, reader.clone())).await {
7557
Ok(Ok(Some(r))) => r,
7658
Ok(Ok(None)) | Err(TimeoutError { .. }) => break, /* EOF or timeout */
7759
Ok(Err(e)) => return Err(e),
@@ -352,7 +334,7 @@ impl Read for Encoder {
352334
const HTTP_1_1_VERSION: u8 = 1;
353335

354336
/// Decode an HTTP request on the server.
355-
async fn decode<R>(addr: &str, reader: R) -> Result<Option<DecodedRequest>, Exception>
337+
async fn decode<R>(addr: &str, reader: R) -> Result<Option<Request>, Exception>
356338
where
357339
R: Read + Unpin + Send + 'static,
358340
{
@@ -403,49 +385,10 @@ where
403385
// it with a known length, or need to use chunked encoding.
404386
let len = match req.header(&CONTENT_TYPE) {
405387
Some(len) => len.last().unwrap().as_str().parse::<usize>()?,
406-
None => return Ok(Some(DecodedRequest::WithoutBody(req, Box::new(reader)))),
388+
None => return Ok(Some(req)),
407389
};
408390
req.set_body(Body::from_reader(reader));
409391
req.set_len(len);
410392

411-
Ok(Some(DecodedRequest::WithBody(req)))
412-
}
413-
414-
/// A decoded request
415-
enum DecodedRequest {
416-
/// The TCP connection is inside the request already, so the lifetimes match up.
417-
WithBody(Request),
418-
/// The TCP connection is *not* inside the request body, so we need to pass
419-
/// it along with it to make the lifetimes match up.
420-
WithoutBody(Request, Box<dyn BufRead + Unpin + Send + 'static>),
421-
}
422-
423-
impl fmt::Debug for DecodedRequest {
424-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
425-
match self {
426-
DecodedRequest::WithBody(_) => write!(f, "WithBody"),
427-
DecodedRequest::WithoutBody(_, _) => write!(f, "WithoutBody"),
428-
}
429-
}
430-
}
431-
432-
impl DecodedRequest {
433-
/// Get a mutable reference to the request
434-
fn mut_request(&mut self) -> &mut Request {
435-
match self {
436-
DecodedRequest::WithBody(r) => r,
437-
DecodedRequest::WithoutBody(r, _) => r,
438-
}
439-
}
440-
441-
/// Consume self and get access to the underlying reader
442-
///
443-
/// When the request has a body, the underlying reader is the body.
444-
/// When it does not, the underlying body has been passed alongside the request.
445-
fn into_reader(self) -> Box<dyn BufRead + Unpin + Send + 'static> {
446-
match self {
447-
DecodedRequest::WithBody(r) => r.into_body().into_reader(),
448-
DecodedRequest::WithoutBody(_, s) => s,
449-
}
450-
}
393+
Ok(Some(req))
451394
}

0 commit comments

Comments
 (0)