diff --git a/examples/server.rs b/examples/server.rs index 8fb9f0c..f4b9049 100644 --- a/examples/server.rs +++ b/examples/server.rs @@ -2,12 +2,13 @@ use async_std::net::{TcpListener, TcpStream}; use async_std::prelude::*; use async_std::task; use http_types::{Response, StatusCode}; +use url::Url; #[async_std::main] async fn main() -> http_types::Result<()> { // Open up a TCP connection and create a URL. let listener = TcpListener::bind(("127.0.0.1", 8080)).await?; - let addr = format!("http://{}", listener.local_addr()?); + let addr = Url::parse(&format!("http://{}", listener.local_addr()?))?; println!("listening on {}", addr); // For each incoming TCP connection, spawn a task and call `accept`. @@ -25,7 +26,7 @@ async fn main() -> http_types::Result<()> { } // Take a TCP stream, and convert it into sequential HTTP request / response pairs. -async fn accept(addr: String, stream: TcpStream) -> http_types::Result<()> { +async fn accept(addr: Url, stream: TcpStream) -> http_types::Result<()> { println!("starting new connection from {}", stream.peer_addr()?); async_h1::accept(&addr, stream.clone(), |_req| async move { let mut res = Response::new(StatusCode::Ok); diff --git a/src/lib.rs b/src/lib.rs index 5868726..adb5ce6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -60,7 +60,7 @@ //! async fn main() -> http_types::Result<()> { //! // Open up a TCP connection and create a URL. //! let listener = TcpListener::bind(("127.0.0.1", 8080)).await?; -//! let addr = format!("http://{}", listener.local_addr()?); +//! let addr: url::Url = format!("http://{}", listener.local_addr()?).parse()?; //! println!("listening on {}", addr); //! //! // For each incoming TCP connection, spawn a task and call `accept`. @@ -68,8 +68,8 @@ //! while let Some(stream) = incoming.next().await { //! let stream = stream?; //! let addr = addr.clone(); -//! task::spawn(async { -//! if let Err(err) = accept(addr, stream).await { +//! task::spawn(async move { +//! if let Err(err) = accept(&addr, stream).await { //! eprintln!("{}", err); //! } //! }); @@ -78,7 +78,7 @@ //! } //! //! // Take a TCP stream, and convert it into sequential HTTP request / response pairs. -//! async fn accept(addr: String, stream: TcpStream) -> http_types::Result<()> { +//! async fn accept(addr: &url::Url, stream: TcpStream) -> http_types::Result<()> { //! println!("starting new connection from {}", stream.peer_addr()?); //! async_h1::accept(&addr, stream.clone(), |_req| async move { //! let mut res = Response::new(StatusCode::Ok); diff --git a/src/server/decode.rs b/src/server/decode.rs index 3a1373c..499aca4 100644 --- a/src/server/decode.rs +++ b/src/server/decode.rs @@ -8,6 +8,7 @@ use async_std::prelude::*; use http_types::headers::{HeaderName, HeaderValue, CONTENT_LENGTH, TRANSFER_ENCODING}; use http_types::{ensure, ensure_eq, format_err}; use http_types::{Body, Method, Request}; +use url::Url; use crate::chunked::ChunkedDecoder; use crate::{MAX_HEADERS, MAX_HEAD_LENGTH}; @@ -18,7 +19,7 @@ const LF: u8 = b'\n'; const HTTP_1_1_VERSION: u8 = 1; /// Decode an HTTP request on the server. -pub(crate) async fn decode(addr: &str, reader: R) -> http_types::Result> +pub(crate) async fn decode(addr: &Url, reader: R) -> http_types::Result> where R: Read + Unpin + Send + Sync + 'static, { @@ -59,7 +60,7 @@ where let uri = httparse_req.path; let uri = uri.ok_or_else(|| format_err!("No uri found"))?; - let uri = url::Url::parse(&format!("{}{}", addr, uri))?; + let uri = addr.join(uri)?; let version = httparse_req.version; let version = version.ok_or_else(|| format_err!("No version found"))?; diff --git a/src/server/mod.rs b/src/server/mod.rs index 05fb675..19cbb2f 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -3,9 +3,9 @@ use std::time::Duration; use async_std::future::{timeout, Future, TimeoutError}; -use async_std::io::{self}; -use async_std::io::{Read, Write}; +use async_std::io::{self, Read, Write}; use http_types::{Request, Response}; +use url::Url; mod decode; mod encode; @@ -31,7 +31,7 @@ impl Default for ServerOptions { /// Accept a new incoming HTTP/1.1 connection. /// /// Supports `KeepAlive` requests by default. -pub async fn accept(addr: &str, io: RW, endpoint: F) -> http_types::Result<()> +pub async fn accept(addr: &Url, io: RW, endpoint: F) -> http_types::Result<()> where RW: Read + Write + Clone + Send + Sync + Unpin + 'static, F: Fn(Request) -> Fut, @@ -44,7 +44,7 @@ where /// /// Supports `KeepAlive` requests by default. pub async fn accept_with_opts( - addr: &str, + addr: &Url, mut io: RW, endpoint: F, opts: ServerOptions, diff --git a/tests/server-chunked-encode-large.rs b/tests/server-chunked-encode-large.rs index 9ca34c1..209f23e 100644 --- a/tests/server-chunked-encode-large.rs +++ b/tests/server-chunked-encode-large.rs @@ -145,12 +145,16 @@ const RESPONSE: &'static str = concat![ #[async_std::test] async fn server_chunked_large() { let case = TestCase::new(REQUEST, "").await; - async_h1::accept("http://example.com", case.clone(), |_| async { - let mut res = Response::new(StatusCode::Ok); - let body = Cursor::new(TEXT.to_owned()); - res.set_body(Body::from_reader(body, None)); - Ok(res) - }) + async_h1::accept( + &"http://example.com".parse().unwrap(), + case.clone(), + |_| async { + let mut res = Response::new(StatusCode::Ok); + let body = Cursor::new(TEXT.to_owned()); + res.set_body(Body::from_reader(body, None)); + Ok(res) + }, + ) .await .unwrap(); case.assert_writer_with(RESPONSE, common::munge_date).await; diff --git a/tests/server-chunked-encode-small.rs b/tests/server-chunked-encode-small.rs index 91ebf41..a0d439c 100644 --- a/tests/server-chunked-encode-small.rs +++ b/tests/server-chunked-encode-small.rs @@ -41,12 +41,16 @@ const RESPONSE: &'static str = concat![ #[async_std::test] async fn server_chunked_large() { let case = TestCase::new(REQUEST, "").await; - async_h1::accept("http://example.com", case.clone(), |_| async { - let mut res = Response::new(StatusCode::Ok); - let body = Cursor::new(TEXT.to_owned()); - res.set_body(Body::from_reader(body, None)); - Ok(res) - }) + async_h1::accept( + &"http://example.com".parse().unwrap(), + case.clone(), + |_| async { + let mut res = Response::new(StatusCode::Ok); + let body = Cursor::new(TEXT.to_owned()); + res.set_body(Body::from_reader(body, None)); + Ok(res) + }, + ) .await .unwrap(); case.assert_writer_with(RESPONSE, common::munge_date).await; diff --git a/tests/server.rs b/tests/server.rs index 6ac0c82..96bc737 100644 --- a/tests/server.rs +++ b/tests/server.rs @@ -12,9 +12,9 @@ async fn test_basic_request() { "fixtures/response-add-date.txt", ) .await; - let addr = "http://example.com"; + let addr = "http://example.com".parse().unwrap(); - async_h1::accept(addr, case.clone(), |_req| async { + async_h1::accept(&addr, case.clone(), |_req| async { let mut res = Response::new(StatusCode::Ok); res.set_body(""); Ok(res) @@ -32,9 +32,9 @@ async fn test_chunked_basic() { "fixtures/response-chunked-basic.txt", ) .await; - let addr = "http://example.com"; + let addr = "http://example.com".parse().unwrap(); - async_h1::accept(addr, case.clone(), |_req| async { + async_h1::accept(&addr, case.clone(), |_req| async { let mut res = Response::new(StatusCode::Ok); res.set_body(Body::from_reader( Cursor::new(b"Mozilla") @@ -59,8 +59,8 @@ async fn test_chunked_echo() { ) .await; - let addr = "http://example.com"; - async_h1::accept(addr, case.clone(), |req| async { + let addr = "http://example.com".parse().unwrap(); + async_h1::accept(&addr, case.clone(), |req| async { let ct = req.content_type(); let body: Body = req.into(); @@ -86,9 +86,9 @@ async fn test_unexpected_eof() { "fixtures/response-unexpected-eof.txt", ) .await; - let addr = "http://example.com"; + let addr = "http://example.com".parse().unwrap(); - async_h1::accept(addr, case.clone(), |req| async { + async_h1::accept(&addr, case.clone(), |req| async { let mut res = Response::new(StatusCode::Ok); let ct = req.content_type(); let body: Body = req.into(); @@ -112,9 +112,9 @@ async fn test_invalid_trailer() { "fixtures/response-invalid-trailer.txt", ) .await; - let addr = "http://example.com"; + let addr = "http://example.com".parse().unwrap(); - async_h1::accept(addr, case.clone(), |req| async { + async_h1::accept(&addr, case.clone(), |req| async { let mut res = Response::new(StatusCode::Ok); let ct = req.content_type(); let body: Body = req.into();