diff --git a/Cargo.toml b/Cargo.toml index eab7710..f43d975 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ log = "0.4" bytes = "1.0" futures-util = { version = "0.3", default-features = false } memchr = "2.4" -http = "0.2" +http = "1.0" httparse = "1.3" mime = "0.3" encoding_rs = "0.8" @@ -42,7 +42,9 @@ tokio-util = { version = "0.7", features = ["io"], optional = true } [dev-dependencies] serde = { version = "1.0", features = ["derive"] } tokio = { version = "1.0", features = ["full"] } -hyper = { version = "0.14", features = ["server", "http1", "stream", "tcp"] } +hyper = { version = "1.0", features = ["server", "http1"] } +http-body-util = "0.1" +hyper-util = { version = "0.1.1", features = ["full"] } [build-dependencies] version_check = "0.9" diff --git a/examples/hyper_server_example.rs b/examples/hyper_server_example.rs index 0fb1baa..ddfb380 100644 --- a/examples/hyper_server_example.rs +++ b/examples/hyper_server_example.rs @@ -1,13 +1,14 @@ use std::{convert::Infallible, net::SocketAddr}; -use hyper::server::Server; -use hyper::service::{make_service_fn, service_fn}; -use hyper::{header::CONTENT_TYPE, Body, Request, Response, StatusCode}; +use bytes::Bytes; +use futures_util::StreamExt; +use http_body_util::{BodyStream, Full}; +use hyper::{body::Incoming, header::CONTENT_TYPE, Request, Response, StatusCode}; // Import the multer types. use multer::Multipart; // A handler for incoming requests. -async fn handle(req: Request) -> Result, Infallible> { +async fn handle(req: Request) -> Result>, Infallible> { // Extract the `multipart/form-data` boundary from the headers. let boundary = req .headers() @@ -19,7 +20,7 @@ async fn handle(req: Request) -> Result, Infallible> { if boundary.is_none() { return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) - .body(Body::from("BAD REQUEST")) + .body(Full::from("BAD REQUEST")) .unwrap()); } @@ -27,17 +28,21 @@ async fn handle(req: Request) -> Result, Infallible> { if let Err(err) = process_multipart(req.into_body(), boundary.unwrap()).await { return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(Body::from(format!("INTERNAL SERVER ERROR: {}", err))) + .body(Full::from(format!("INTERNAL SERVER ERROR: {}", err))) .unwrap()); } - Ok(Response::new(Body::from("Success"))) + Ok(Response::new(Full::from("Success"))) } // Process the request body as multipart/form-data. -async fn process_multipart(body: Body, boundary: String) -> multer::Result<()> { +async fn process_multipart(body: Incoming, boundary: String) -> multer::Result<()> { + // Convert the body into a stream of data frames. + let body_stream = BodyStream::new(body) + .filter_map(|result| async move { result.map(|frame| frame.into_data().ok()).transpose() }); + // Create a Multipart instance from the request body. - let mut multipart = Multipart::new(body, boundary); + let mut multipart = Multipart::new(body_stream, boundary); // Iterate over the fields, `next_field` method will return the next field if // available. @@ -72,13 +77,21 @@ async fn process_multipart(body: Body, boundary: String) -> multer::Result<()> { #[tokio::main] async fn main() { let addr = SocketAddr::from(([127, 0, 0, 1], 3000)); - - let make_svc = make_service_fn(|_conn| async { Ok::<_, Infallible>(service_fn(handle)) }); - - let server = Server::bind(&addr).serve(make_svc); - + let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); println!("Server running at: {}", addr); - if let Err(e) = server.await { - eprintln!("server error: {}", e); + + let service = hyper::service::service_fn(handle); + + loop { + let (socket, _remote_addr) = listener.accept().await.unwrap(); + let socket = hyper_util::rt::TokioIo::new(socket); + tokio::spawn(async move { + if let Err(e) = hyper::server::conn::http1::Builder::new() + .serve_connection(socket, service) + .await + { + eprintln!("server error: {}", e); + } + }); } }