Skip to content

Commit 1b2e769

Browse files
authored
Merge pull request #29 from yoshuawuyts/http-types-update
Update http-types
2 parents 7c7a176 + 525726d commit 1b2e769

File tree

5 files changed

+56
-32
lines changed

5 files changed

+56
-32
lines changed

examples/server.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
use std::pin::Pin;
2+
use std::str::FromStr;
23
use std::sync::Arc;
34

45
use async_h1::server;
56
use async_std::io::{self, Read, Write};
67
use async_std::net::{self, TcpStream};
78
use async_std::prelude::*;
89
use async_std::task::{self, Context, Poll};
10+
use http_types::headers::{HeaderName, HeaderValue};
911
use http_types::{Response, StatusCode};
1012

1113
async fn accept(addr: String, stream: TcpStream) -> Result<(), async_h1::Exception> {
@@ -16,9 +18,12 @@ async fn accept(addr: String, stream: TcpStream) -> Result<(), async_h1::Excepti
1618

1719
server::accept(&addr, stream.clone(), stream, |_| {
1820
async {
19-
let resp = Response::new(StatusCode::Ok)
20-
.set_header("Content-Type", "text/plain")?
21-
.set_body_string("Hello".into())?;
21+
let mut resp = Response::new(StatusCode::Ok);
22+
resp.insert_header(
23+
HeaderName::from_str("Content-Type")?,
24+
HeaderValue::from_str("text/plain")?,
25+
)?;
26+
resp.set_body("Hello");
2227
// To try chunked encoding, replace `set_body_string` with the following method call
2328
// .set_body(io::Cursor::new(vec![
2429
// 0x48u8, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x21,

src/client.rs

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@ use async_std::prelude::*;
55
use async_std::task::{Context, Poll};
66
use futures_core::ready;
77
use futures_io::AsyncRead;
8-
use http_types::{Request, Response, StatusCode};
8+
use http_types::{
9+
headers::{HeaderName, HeaderValue, CONTENT_LENGTH},
10+
Body, Request, Response, StatusCode,
11+
};
912

1013
use std::pin::Pin;
14+
use std::str::FromStr;
1115

1216
use crate::{Exception, MAX_HEADERS};
1317

@@ -58,8 +62,10 @@ pub async fn encode(req: Request) -> Result<Encoder, std::io::Error> {
5862
// See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding
5963
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Trailer
6064
}
61-
for (header, value) in req.headers().iter() {
62-
write!(&mut buf, "{}: {}\r\n", header, value).await?;
65+
for (header, values) in req.iter() {
66+
for value in values.iter() {
67+
write!(&mut buf, "{}: {}\r\n", header, value).await?;
68+
}
6369
}
6470

6571
write!(&mut buf, "\r\n").await?;
@@ -107,22 +113,23 @@ where
107113
use std::convert::TryFrom;
108114
let mut res = Response::new(StatusCode::try_from(code)?);
109115
for header in httparse_res.headers.iter() {
110-
res = res.set_header(header.name, std::str::from_utf8(header.value)?)?;
116+
let name = HeaderName::from_str(header.name)?;
117+
let value = HeaderValue::from_str(std::str::from_utf8(header.value)?)?;
118+
res.insert_header(name, value)?;
111119
}
112120

113121
// Process the body if `Content-Length` was passed.
114-
if let Some(content_length) = httparse_res
115-
.headers
116-
.iter()
117-
.find(|h| h.name.eq_ignore_ascii_case("Content-Length"))
118-
{
119-
let length = std::str::from_utf8(content_length.value)
120-
.ok()
121-
.and_then(|s| s.parse::<usize>().ok());
122-
123-
if let Some(_len) = length {
124-
// TODO: set size
125-
res = res.set_body(reader);
122+
if let Some(content_length) = res.header(&CONTENT_LENGTH) {
123+
let length = content_length
124+
.last()
125+
.unwrap()
126+
.as_str()
127+
.parse::<usize>()
128+
.ok();
129+
130+
if let Some(len) = length {
131+
res.set_body(Body::from_reader(reader));
132+
res.set_len(len);
126133
} else {
127134
return Err("Invalid value for Content-Length".into());
128135
}

src/server.rs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ 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::{Method, Request, Response};
9+
use http_types::{
10+
headers::{HeaderName, HeaderValue, CONTENT_TYPE},
11+
Body, Method, Request, Response,
12+
};
1013
use std::fmt;
1114
use std::str::FromStr;
1215
use std::time::Duration;
@@ -140,11 +143,10 @@ impl Encoder {
140143
let date = fmt_http_date(std::time::SystemTime::now());
141144
std::io::Write::write_fmt(&mut head, format_args!("Date: {}\r\n", date))?;
142145

143-
for (header, value) in self.res.headers().iter() {
144-
std::io::Write::write_fmt(
145-
&mut head,
146-
format_args!("{}: {}\r\n", header.as_str(), value),
147-
)?
146+
for (header, values) in self.res.iter() {
147+
for value in values.iter() {
148+
std::io::Write::write_fmt(&mut head, format_args!("{}: {}\r\n", header, value))?
149+
}
148150
}
149151

150152
std::io::Write::write_fmt(&mut head, format_args!("\r\n"))?;
@@ -384,22 +386,28 @@ where
384386
let method = httparse_req.method.ok_or_else(|| "No method found")?;
385387
let uri = httparse_req.path.ok_or_else(|| "No uri found")?;
386388
let uri = url::Url::parse(&format!("{}{}", addr, uri))?;
389+
387390
let version = httparse_req.version.ok_or_else(|| "No version found")?;
388391
if version != HTTP_1_1_VERSION {
389392
return Err("Unsupported HTTP version".into());
390393
}
394+
391395
let mut req = Request::new(Method::from_str(method)?, uri);
392396
for header in httparse_req.headers.iter() {
393-
req = req.set_header(header.name, std::str::from_utf8(header.value)?)?;
397+
let name = HeaderName::from_str(header.name)?;
398+
let value = HeaderValue::from_str(std::str::from_utf8(header.value)?)?;
399+
req.insert_header(name, value)?;
394400
}
395401

396402
// Check for content-length, that determines determines whether we can parse
397403
// it with a known length, or need to use chunked encoding.
398-
let len = match req.header("Content-Length") {
399-
Some(len) => len.parse::<usize>()?,
404+
let len = match req.header(&CONTENT_TYPE) {
405+
Some(len) => len.last().unwrap().as_str().parse::<usize>()?,
400406
None => return Ok(Some(DecodedRequest::WithoutBody(req, Box::new(reader)))),
401407
};
402-
req = req.set_body_reader(reader).set_len(len);
408+
req.set_body(Body::from_reader(reader));
409+
req.set_len(len);
410+
403411
Ok(Some(DecodedRequest::WithBody(req)))
404412
}
405413

@@ -436,7 +444,7 @@ impl DecodedRequest {
436444
/// When it does not, the underlying body has been passed alongside the request.
437445
fn into_reader(self) -> Box<dyn BufRead + Unpin + Send + 'static> {
438446
match self {
439-
DecodedRequest::WithBody(r) => r.into_body_reader(),
447+
DecodedRequest::WithBody(r) => r.into_body().into_reader(),
440448
DecodedRequest::WithoutBody(_, s) => s,
441449
}
442450
}

tests/fixtures/response1.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
HTTP/1.1 200 OK
22
Content-Length: 0
33
Date: {DATE}
4-
Content-Type: text/plain; charset=utf-8
4+
content-type: text/plain; charset=utf-8
55

tests/server.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ fn test_basic_request() {
1616
actual,
1717
expected,
1818
server::accept(addr, Cursor::new(request), &mut actual, |_req| {
19-
async { Ok(Response::new(StatusCode::Ok).set_body_string("".to_owned())?) }
19+
async {
20+
let mut resp = Response::new(StatusCode::Ok);
21+
resp.set_body("");
22+
Ok(resp)
23+
}
2024
})
2125
);
2226
}

0 commit comments

Comments
 (0)