update http-types to master

This commit is contained in:
Jacob Rothstein 2020-04-27 12:51:41 -07:00
parent 428fb9e8c6
commit 9fd5ea0574
No known key found for this signature in database
GPG Key ID: C38BA18C6CFE15A5
13 changed files with 61 additions and 60 deletions

View File

@ -15,7 +15,7 @@ edition = "2018"
url = "2.1.0"
httparse = "1.3.3"
async-std = { version = "1.5.0", features = ["unstable"] }
http-types = "1.2.0"
http-types = { git = "https://github.com/http-rs/http-types.git", branch = "master" }
pin-project-lite = "0.1.1"
byte-pool = "0.2.1"
lazy_static = "1.4.0"

View File

@ -28,7 +28,7 @@ async fn accept(stream: TcpStream) -> http_types::Result<()> {
println!("starting new connection from {}", stream.peer_addr()?);
async_h1::accept(stream.clone(), |_req| async move {
let mut res = Response::new(StatusCode::Ok);
res.insert_header("Content-Type", "text/plain")?;
res.insert_header("Content-Type", "text/plain");
res.set_body("Hello world");
Ok(res)
})

View File

@ -7,7 +7,7 @@ use std::task::{Context, Poll};
use async_std::io::{self, Read};
use async_std::sync::Arc;
use byte_pool::{Block, BytePool};
use http_types::trailers::{Trailers, TrailersSender};
use http_types::trailers::{Sender, Trailers};
const INITIAL_CAPACITY: usize = 1024 * 4;
const MAX_CAPACITY: usize = 512 * 1024 * 1024; // 512 MiB
@ -32,11 +32,11 @@ pub(crate) struct ChunkedDecoder<R: Read> {
/// Current state.
state: State,
/// Trailer channel sender.
trailer_sender: Option<TrailersSender>,
trailer_sender: Option<Sender>,
}
impl<R: Read> ChunkedDecoder<R> {
pub(crate) fn new(inner: R, trailer_sender: TrailersSender) -> Self {
pub(crate) fn new(inner: R, trailer_sender: Sender) -> Self {
ChunkedDecoder {
inner,
buffer: POOL.alloc(INITIAL_CAPACITY),
@ -156,7 +156,7 @@ impl<R: Read + Unpin> ChunkedDecoder<R> {
let sender =
sender.expect("invalid chunked state, tried sending multiple trailers");
let fut = Box::pin(sender.send(Ok(headers)));
let fut = Box::pin(sender.send(headers));
Ok(DecodeResult::Some {
read: 0,
new_state: Some(State::TrailerSending(fut)),
@ -483,10 +483,7 @@ fn decode_trailer(buffer: Block<'static>, pos: &Range<usize>) -> io::Result<Deco
Ok(Status::Complete((used, headers))) => {
let mut trailers = Trailers::new();
for header in headers {
let value = std::string::String::from_utf8_lossy(header.value).to_string();
if let Err(err) = trailers.insert(header.name, value) {
return Err(io::Error::new(io::ErrorKind::Other, err.to_string()));
}
trailers.insert(header.name, String::from_utf8_lossy(header.value).as_ref());
}
Ok(DecodeResult::Some {
@ -527,7 +524,7 @@ mod tests {
);
let (s, _r) = async_std::sync::channel(1);
let sender = TrailersSender::new(s);
let sender = Sender::new(s);
let mut decoder = ChunkedDecoder::new(input, sender);
let mut output = String::new();
@ -553,7 +550,7 @@ mod tests {
input.extend("\r\n0\r\n\r\n".as_bytes());
let (s, _r) = async_std::sync::channel(1);
let sender = TrailersSender::new(s);
let sender = Sender::new(s);
let mut decoder = ChunkedDecoder::new(async_std::io::Cursor::new(input), sender);
let mut output = String::new();
@ -583,20 +580,30 @@ mod tests {
.as_bytes(),
);
let (s, r) = async_std::sync::channel(1);
let sender = TrailersSender::new(s);
let sender = Sender::new(s);
let mut decoder = ChunkedDecoder::new(input, sender);
let mut output = String::new();
decoder.read_to_string(&mut output).await.unwrap();
assert_eq!(output, "MozillaDeveloperNetwork");
let trailer = r.recv().await.unwrap().unwrap();
let trailers = r.recv().await.unwrap();
let as_vec = trailers.iter().collect::<Vec<_>>();
assert_eq!(as_vec.len(), 1);
let (header_name, header_values) = as_vec[0];
assert_eq!(
trailer.iter().collect::<Vec<_>>(),
vec![(
&"Expires".parse().unwrap(),
&vec!["Wed, 21 Oct 2015 07:28:00 GMT".parse().unwrap()],
)]
header_name,
&"Expires"
.parse::<http_types::headers::HeaderName>()
.unwrap()
);
assert_eq!(header_values.iter().collect::<Vec<_>>().len(), 1);
assert_eq!(
header_values.last(),
&"Wed, 21 Oct 2015 07:28:00 GMT"
.parse::<http_types::headers::HeaderValue>()
.unwrap()
);
});
}

View File

@ -2,12 +2,11 @@ use async_std::io::{BufReader, Read};
use async_std::prelude::*;
use http_types::{ensure, ensure_eq, format_err};
use http_types::{
headers::{HeaderName, HeaderValue, CONTENT_LENGTH, DATE, TRANSFER_ENCODING},
headers::{CONTENT_LENGTH, DATE, TRANSFER_ENCODING},
Body, Response, StatusCode,
};
use std::convert::TryFrom;
use std::str::FromStr;
use crate::chunked::ChunkedDecoder;
use crate::date::fmt_http_date;
@ -63,18 +62,16 @@ where
let mut res = Response::new(StatusCode::try_from(code)?);
for header in httparse_res.headers.iter() {
let name = HeaderName::from_str(header.name)?;
let value = HeaderValue::from_str(std::str::from_utf8(header.value)?)?;
res.append_header(name, value)?;
res.append_header(header.name, std::str::from_utf8(header.value)?)?;
}
if res.header(&DATE).is_none() {
if res.header(DATE).is_none() {
let date = fmt_http_date(std::time::SystemTime::now());
res.insert_header(DATE, &format!("date: {}\r\n", date)[..])?;
res.insert_header(DATE, &format!("date: {}\r\n", date)[..]);
}
let content_length = res.header(&CONTENT_LENGTH);
let transfer_encoding = res.header(&TRANSFER_ENCODING);
let content_length = res.header(CONTENT_LENGTH);
let transfer_encoding = res.header(TRANSFER_ENCODING);
ensure!(
content_length.is_none() || transfer_encoding.is_none(),
@ -82,7 +79,7 @@ where
);
if let Some(encoding) = transfer_encoding {
if !encoding.is_empty() && encoding.last().unwrap().as_str() == "chunked" {
if encoding.last().as_str() == "chunked" {
let trailers_sender = res.send_trailers();
let reader = BufReader::new(ChunkedDecoder::new(reader, trailers_sender));
res.set_body(Body::from_reader(reader, None));
@ -94,7 +91,7 @@ where
// Check for Content-Length.
if let Some(len) = content_length {
let len = len.last().unwrap().as_str().parse::<usize>()?;
let len = len.last().as_str().parse::<usize>()?;
res.set_body(Body::from_reader(reader.take(len as u64), Some(len)));
}

View File

@ -2,7 +2,7 @@ use async_std::io::{self, Read};
use async_std::prelude::*;
use async_std::task::{Context, Poll};
use http_types::format_err;
use http_types::{Method, Request};
use http_types::{headers::HOST, Method, Request};
use std::pin::Pin;
@ -54,7 +54,7 @@ impl Encoder {
log::trace!("> {}", &val);
buf.write_all(val.as_bytes()).await?;
if req.header(&http_types::headers::HOST).is_none() {
if req.header(HOST).is_none() {
// Insert Host header
// Insert host
let host = req.url().host_str();

View File

@ -79,7 +79,7 @@
//! println!("starting new connection from {}", stream.peer_addr()?);
//! async_h1::accept(stream.clone(), |_req| async move {
//! let mut res = Response::new(StatusCode::Ok);
//! res.insert_header("Content-Type", "text/plain")?;
//! res.insert_header("Content-Type", "text/plain");
//! res.set_body("Hello");
//! Ok(res)
//! })

View File

@ -4,7 +4,7 @@ use std::str::FromStr;
use async_std::io::{BufReader, Read, Write};
use async_std::prelude::*;
use http_types::headers::{HeaderName, HeaderValue, CONTENT_LENGTH, HOST, TRANSFER_ENCODING};
use http_types::headers::{CONTENT_LENGTH, HOST, TRANSFER_ENCODING};
use http_types::{ensure, ensure_eq, format_err};
use http_types::{Body, Method, Request};
@ -75,16 +75,14 @@ where
);
for header in httparse_req.headers.iter() {
let name = HeaderName::from_str(header.name)?;
let value = HeaderValue::from_str(std::str::from_utf8(header.value)?)?;
req.insert_header(name, value)?;
req.insert_header(header.name, std::str::from_utf8(header.value)?);
}
set_url_and_port_from_host_header(&mut req)?;
handle_100_continue(&req, &mut io).await?;
let content_length = req.header(&CONTENT_LENGTH);
let transfer_encoding = req.header(&TRANSFER_ENCODING);
let content_length = req.header(CONTENT_LENGTH);
let transfer_encoding = req.header(TRANSFER_ENCODING);
http_types::ensure!(
content_length.is_none() || transfer_encoding.is_none(),
@ -93,7 +91,7 @@ where
// Check for Transfer-Encoding
if let Some(encoding) = transfer_encoding {
if !encoding.is_empty() && encoding.last().unwrap().as_str() == "chunked" {
if encoding.last().as_str() == "chunked" {
let trailer_sender = req.send_trailers();
let reader = BufReader::new(ChunkedDecoder::new(reader, trailer_sender));
req.set_body(Body::from_reader(reader, None));
@ -104,7 +102,7 @@ where
// Check for Content-Length.
if let Some(len) = content_length {
let len = len.last().unwrap().as_str().parse::<usize>()?;
let len = len.last().as_str().parse::<usize>()?;
req.set_body(Body::from_reader(reader.take(len as u64), Some(len)));
}
@ -113,11 +111,11 @@ where
fn set_url_and_port_from_host_header(req: &mut Request) -> http_types::Result<()> {
let host = req
.header(&HOST)
.and_then(|header| header.last()) // There must only exactly one Host header, so this is permissive
.ok_or_else(|| format_err!("Mandatory Host header missing"))?; // https://tools.ietf.org/html/rfc7230#section-5.4
.header(HOST)
.map(|header| header.last()) // There must only exactly one Host header, so this is permissive
.ok_or_else(|| format_err!("Mandatory Host header missing"))? // https://tools.ietf.org/html/rfc7230#section-5.4
.to_string();
let host = host.to_string();
if let Some(colon) = host.find(":") {
req.url_mut().set_host(Some(&host[0..colon]))?;
req.url_mut()
@ -134,10 +132,7 @@ async fn handle_100_continue<IO: Write + Unpin>(
req: &Request,
io: &mut IO,
) -> http_types::Result<()> {
let expect_header_value = req
.header(&HeaderName::from_str("expect").unwrap())
.and_then(|v| v.last())
.map(|v| v.as_str());
let expect_header_value = req.header("expect").map(|v| v.as_str());
if let Some("100-continue") = expect_header_value {
io.write_all("HTTP/1.1 100 Continue\r\n".as_bytes()).await?;
@ -255,7 +250,7 @@ mod tests {
.unwrap(),
);
req.insert_header(HOST, host).unwrap();
req.insert_header(HOST, host);
req
}

View File

@ -5,7 +5,10 @@ use std::pin::Pin;
use async_std::io;
use async_std::io::prelude::*;
use async_std::task::{Context, Poll};
use http_types::Response;
use http_types::{
headers::{CONTENT_LENGTH, DATE, TRANSFER_ENCODING},
Response,
};
use crate::chunked::ChunkedEncoder;
use crate::date::fmt_http_date;
@ -138,7 +141,7 @@ impl Encoder {
)?;
}
if self.res.header(&http_types::headers::DATE).is_none() {
if self.res.header(DATE).is_none() {
let date = fmt_http_date(std::time::SystemTime::now());
std::io::Write::write_fmt(&mut self.head, format_args!("date: {}\r\n", date))?;
}
@ -146,8 +149,8 @@ impl Encoder {
let iter = self
.res
.iter()
.filter(|(h, _)| h != &&http_types::headers::CONTENT_LENGTH)
.filter(|(h, _)| h != &&http_types::headers::TRANSFER_ENCODING);
.filter(|(h, _)| h != &&CONTENT_LENGTH)
.filter(|(h, _)| h != &&TRANSFER_ENCODING);
for (header, values) in iter {
for value in values.iter() {
std::io::Write::write_fmt(

View File

@ -45,7 +45,7 @@ async fn test_multiple_header_values_for_same_header_name() {
let res = client::decode(response_fixture).await.unwrap();
pretty_assertions::assert_eq!(res.header(&headers::SET_COOKIE).unwrap().len(), 2);
pretty_assertions::assert_eq!(res.header(&headers::SET_COOKIE).unwrap().iter().count(), 2);
}
#[async_std::test]
@ -60,7 +60,6 @@ async fn test_response_newlines() {
res.header(&headers::CONTENT_LENGTH)
.unwrap()
.last()
.unwrap()
.as_str()
.parse::<usize>()
.unwrap(),

View File

@ -1,6 +1,6 @@
POST / HTTP/1.1
host: localhost:8080
content-length: 5
content-type: text/plain; charset=utf-8
content-type: text/plain;charset=utf-8
hello

View File

@ -1,5 +1,5 @@
HTTP/1.1 200 OK
content-length: 0
date: {DATE}
content-type: text/plain; charset=utf-8
content-type: text/plain;charset=utf-8

View File

@ -1,7 +1,7 @@
HTTP/1.1 200 OK
transfer-encoding: chunked
date: {DATE}
content-type: text/plain
content-type: text/plain;charset=utf-8
7
Mozilla

View File

@ -1,6 +1,6 @@
HTTP/1.1 200 OK
content-length: 41
date: {DATE}
content-type: text/plain; charset=utf-8
content-type: text/plain;charset=utf-8
http://www.w3.org/pub/WWW/TheProject.html