From efb5a9b48a47b903fed73b236a8979737153b805 Mon Sep 17 00:00:00 2001 From: Nihal T M Date: Mon, 15 Jul 2024 14:37:36 +0530 Subject: [PATCH 1/5] add http2 server guide --- _stable/server/hello-world-http2.md | 151 ++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 _stable/server/hello-world-http2.md diff --git a/_stable/server/hello-world-http2.md b/_stable/server/hello-world-http2.md new file mode 100644 index 0000000..2c44802 --- /dev/null +++ b/_stable/server/hello-world-http2.md @@ -0,0 +1,151 @@ +--- +title: Getting Started with a HTTP2 Server +layout: guide +--- + +Let's start by making a "Hello, World!" server but this time with http2. + +First we need to declare out dependencies, let's add the following to out `Cargo.toml`: + +```toml +[dependencies] +hyper = { version = "1", features = ["full"] } +tokio = { version = "1", features = ["full"] } +http-body-util = "0.1" +hyper-util = { version = "0.1", features = ["full"] } +``` + +Next, we need to add these imports in out `main.rs` file: + +```rust +# extern crate tokio; +# extern crate hyper; +# extern crate http_body_util; +# extern crate hyper_util; +use hyper::body::Bytes; +use hyper::server::conn::http2; +use hyper::service::service_fn; +use hyper::{Request, Response}; +use hyper_util::rt::TokioIo; +use tokio::net::TcpListener; +``` + +## Creating a http2 Service + +A [`Service`][service] lets us define how our server will respond to +incoming requests. It represents an async function that takes a +[`Request`][request] and returns a `Future`. When the processing of this future is complete, it will resolve to a [`Response`][response] or an error. + +Hyper provides a utility for creating a `Service` from a function that should +serve most usecases: [`service_fn`][service_fn]. We will use this to create +a service from our `hello` function below when we're ready to start our +server. + +```rust +# extern crate hyper; +# extern crate http_body_util; +# use std::convert::Infallible; +# use http_body_util::Full; +# use hyper::body::Bytes; +# use hyper::{Request, Response}; +async fn hello(_: Request) -> Result, hyper::Error> { + Ok(Response::new(Full::new(Bytes::from("Hello, World!")))) +} +``` + +Using this function as a service, we tell our server to respond to all requests +with a default `200 OK` status. The response `Body` will contain our friendly +greeting as a single chunk of bytes, and the `Content-Length` header will be +set automatically. + +## Creating an Executor that uses the tokio runtime + +The http2 server requires an executor to run. We can use the build this declaring a struct that implements the hyper `Executor` trait. + +```rust +impl hyper::rt::Executor for TokioExecutor +where + F: std::future::Future + Send + 'static, + F::Output: Send + 'static, + { + fn execute(&self, fut: F) { + tokio::task::spawn(fut); + } +} +``` + +## Starting the Server + +Lastly, we need to hook up our `hello` service into a running hyper server. + +```rust +# use std::convert::Infallible; +# use std::net::SocketAddr; +# +# use http_body_util::Full; +# use hyper::body::Bytes; +# use hyper::server::conn::http2; +# use hyper::service::service_fn; +# use hyper::{Request, Response}; +# use hyper_util::rt::TokioIo; +# use tokio::net::TcpListener; +# +# async fn hello(_: Request) -> Result>, Infallible> { +# Ok(Response::new(Full::new(Bytes::from("Hello, World!")))) +# } +# +# #[derive(Clone)] +# /// An Executor that uses the tokio runtime. +# pub struct TokioExecutor; +# +# impl hyper::rt::Executor for TokioExecutor +# where +# F: std::future::Future + Send + 'static, +# F::Output: Send + 'static, +# { +# fn execute(&self, fut: F) { +# tokio::task::spawn(fut); +# } +# } +#[tokio::main] +async fn main() -> Result<(), Box> { + let addr = SocketAddr::from(([127,0,0,1], 3000)); + + // We create a TcpListener and bind it to 127.0.0.1:3000 + let listener = TcpListener::bind(addr).await?; + + // We start a loop to continuously accept incoming connections + loop { + let (stream, _) = listener.accept().await?; + + // Use an adapter to access something implementing `tokio::io` traits as if they implement + // `hyper::rt` IO traits. + let io = TokioIo::new(stream); + + // Spawn a tokio task to serve multiple connections concurrently + tokio::task::spawn(async move{ + // Finally, we bind the incoming connection to our http2 `hello` service + if let Err(err) = http2::Builder::new(TokioExecutor) + // `service_fn` converts our function in a `Service` + .serve_connection(io, service_fn(hello)) + .await + { + eprintln!("Error serving connection: {}", err); + } + }); + } +} +``` + +To see all the snippets put together, check out the [full example][example]! + +Also, if `service_fn` doesn't meet your requirements and you'd like to implement +`Service` yourself, see this [example][impl service]. + +[service]: {{ site.hyper_docs_url }}/hyper/service/trait.Service.html +[service_fn]: {{ site.hyper_docs_url }}/hyper/service/fn.service_fn.html +[request]: {{ site.hyper_docs_url }}/hyper/struct.Request.html +[response]: {{ site.hyper_docs_url }}/hyper/struct.Response.html +[parts]: {{ site.http_docs_url }}/http/response/struct.Parts.html +[example]: {{ site.examples_url }}/hello-http2.rs +[impl service]: {{ site.examples_url }}/service_struct_impl-http2.rs \ No newline at end of file From c11f34e065fc73afbb97dd68971d20e6cc165ad6 Mon Sep 17 00:00:00 2001 From: Nihal T M Date: Mon, 15 Jul 2024 15:13:13 +0530 Subject: [PATCH 2/5] fix impl service link --- _stable/server/hello-world-http2.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_stable/server/hello-world-http2.md b/_stable/server/hello-world-http2.md index 2c44802..e28035a 100644 --- a/_stable/server/hello-world-http2.md +++ b/_stable/server/hello-world-http2.md @@ -148,4 +148,4 @@ Also, if `service_fn` doesn't meet your requirements and you'd like to implement [response]: {{ site.hyper_docs_url }}/hyper/struct.Response.html [parts]: {{ site.http_docs_url }}/http/response/struct.Parts.html [example]: {{ site.examples_url }}/hello-http2.rs -[impl service]: {{ site.examples_url }}/service_struct_impl-http2.rs \ No newline at end of file +[impl service]: {{ site.examples_url }}/service_struct_impl.rs \ No newline at end of file From b6f37fe502588e78454b59002f707b5d0d1d0ba4 Mon Sep 17 00:00:00 2001 From: Nihal T M Date: Mon, 15 Jul 2024 17:46:54 +0530 Subject: [PATCH 3/5] fixes after proofreading --- _stable/server/hello-world-http2.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/_stable/server/hello-world-http2.md b/_stable/server/hello-world-http2.md index e28035a..e52700d 100644 --- a/_stable/server/hello-world-http2.md +++ b/_stable/server/hello-world-http2.md @@ -5,7 +5,7 @@ layout: guide Let's start by making a "Hello, World!" server but this time with http2. -First we need to declare out dependencies, let's add the following to out `Cargo.toml`: +First we need to declare our dependencies, let's add the following to our `Cargo.toml`: ```toml [dependencies] @@ -15,7 +15,7 @@ http-body-util = "0.1" hyper-util = { version = "0.1", features = ["full"] } ``` -Next, we need to add these imports in out `main.rs` file: +Next, we need to add these imports in our `main.rs` file: ```rust # extern crate tokio; @@ -58,9 +58,9 @@ with a default `200 OK` status. The response `Body` will contain our friendly greeting as a single chunk of bytes, and the `Content-Length` header will be set automatically. -## Creating an Executor that uses the tokio runtime +## Creating an Executor -The http2 server requires an executor to run. We can use the build this declaring a struct that implements the hyper `Executor` trait. +The http2 server requires an executor to run. ```rust impl hyper::rt::Executor for TokioExecutor @@ -74,9 +74,9 @@ where } ``` -## Starting the Server +## Starting the Server -Lastly, we need to hook up our `hello` service into a running hyper server. +We now have to add our `hello` service into a running hyper server. ```rust # use std::convert::Infallible; @@ -124,7 +124,7 @@ async fn main() -> Result<(), Box> { // Spawn a tokio task to serve multiple connections concurrently tokio::task::spawn(async move{ - // Finally, we bind the incoming connection to our http2 `hello` service + // Finally, we bind the incoming connection to our http2 `hello` service along with our executor if let Err(err) = http2::Builder::new(TokioExecutor) // `service_fn` converts our function in a `Service` .serve_connection(io, service_fn(hello)) From 29024e1f292efeb79a450606a67d75a22f46a06f Mon Sep 17 00:00:00 2001 From: Nihal T M Date: Tue, 16 Jul 2024 12:04:32 +0530 Subject: [PATCH 4/5] deleted http2 example md and added example to hello-world.md --- _stable/server/hello-world-http2.md | 151 ---------------------------- _stable/server/hello-world.md | 19 ++++ 2 files changed, 19 insertions(+), 151 deletions(-) delete mode 100644 _stable/server/hello-world-http2.md diff --git a/_stable/server/hello-world-http2.md b/_stable/server/hello-world-http2.md deleted file mode 100644 index e52700d..0000000 --- a/_stable/server/hello-world-http2.md +++ /dev/null @@ -1,151 +0,0 @@ ---- -title: Getting Started with a HTTP2 Server -layout: guide ---- - -Let's start by making a "Hello, World!" server but this time with http2. - -First we need to declare our dependencies, let's add the following to our `Cargo.toml`: - -```toml -[dependencies] -hyper = { version = "1", features = ["full"] } -tokio = { version = "1", features = ["full"] } -http-body-util = "0.1" -hyper-util = { version = "0.1", features = ["full"] } -``` - -Next, we need to add these imports in our `main.rs` file: - -```rust -# extern crate tokio; -# extern crate hyper; -# extern crate http_body_util; -# extern crate hyper_util; -use hyper::body::Bytes; -use hyper::server::conn::http2; -use hyper::service::service_fn; -use hyper::{Request, Response}; -use hyper_util::rt::TokioIo; -use tokio::net::TcpListener; -``` - -## Creating a http2 Service - -A [`Service`][service] lets us define how our server will respond to -incoming requests. It represents an async function that takes a -[`Request`][request] and returns a `Future`. When the processing of this future is complete, it will resolve to a [`Response`][response] or an error. - -Hyper provides a utility for creating a `Service` from a function that should -serve most usecases: [`service_fn`][service_fn]. We will use this to create -a service from our `hello` function below when we're ready to start our -server. - -```rust -# extern crate hyper; -# extern crate http_body_util; -# use std::convert::Infallible; -# use http_body_util::Full; -# use hyper::body::Bytes; -# use hyper::{Request, Response}; -async fn hello(_: Request) -> Result, hyper::Error> { - Ok(Response::new(Full::new(Bytes::from("Hello, World!")))) -} -``` - -Using this function as a service, we tell our server to respond to all requests -with a default `200 OK` status. The response `Body` will contain our friendly -greeting as a single chunk of bytes, and the `Content-Length` header will be -set automatically. - -## Creating an Executor - -The http2 server requires an executor to run. - -```rust -impl hyper::rt::Executor for TokioExecutor -where - F: std::future::Future + Send + 'static, - F::Output: Send + 'static, - { - fn execute(&self, fut: F) { - tokio::task::spawn(fut); - } -} -``` - -## Starting the Server - -We now have to add our `hello` service into a running hyper server. - -```rust -# use std::convert::Infallible; -# use std::net::SocketAddr; -# -# use http_body_util::Full; -# use hyper::body::Bytes; -# use hyper::server::conn::http2; -# use hyper::service::service_fn; -# use hyper::{Request, Response}; -# use hyper_util::rt::TokioIo; -# use tokio::net::TcpListener; -# -# async fn hello(_: Request) -> Result>, Infallible> { -# Ok(Response::new(Full::new(Bytes::from("Hello, World!")))) -# } -# -# #[derive(Clone)] -# /// An Executor that uses the tokio runtime. -# pub struct TokioExecutor; -# -# impl hyper::rt::Executor for TokioExecutor -# where -# F: std::future::Future + Send + 'static, -# F::Output: Send + 'static, -# { -# fn execute(&self, fut: F) { -# tokio::task::spawn(fut); -# } -# } -#[tokio::main] -async fn main() -> Result<(), Box> { - let addr = SocketAddr::from(([127,0,0,1], 3000)); - - // We create a TcpListener and bind it to 127.0.0.1:3000 - let listener = TcpListener::bind(addr).await?; - - // We start a loop to continuously accept incoming connections - loop { - let (stream, _) = listener.accept().await?; - - // Use an adapter to access something implementing `tokio::io` traits as if they implement - // `hyper::rt` IO traits. - let io = TokioIo::new(stream); - - // Spawn a tokio task to serve multiple connections concurrently - tokio::task::spawn(async move{ - // Finally, we bind the incoming connection to our http2 `hello` service along with our executor - if let Err(err) = http2::Builder::new(TokioExecutor) - // `service_fn` converts our function in a `Service` - .serve_connection(io, service_fn(hello)) - .await - { - eprintln!("Error serving connection: {}", err); - } - }); - } -} -``` - -To see all the snippets put together, check out the [full example][example]! - -Also, if `service_fn` doesn't meet your requirements and you'd like to implement -`Service` yourself, see this [example][impl service]. - -[service]: {{ site.hyper_docs_url }}/hyper/service/trait.Service.html -[service_fn]: {{ site.hyper_docs_url }}/hyper/service/fn.service_fn.html -[request]: {{ site.hyper_docs_url }}/hyper/struct.Request.html -[response]: {{ site.hyper_docs_url }}/hyper/struct.Response.html -[parts]: {{ site.http_docs_url }}/http/response/struct.Parts.html -[example]: {{ site.examples_url }}/hello-http2.rs -[impl service]: {{ site.examples_url }}/service_struct_impl.rs \ No newline at end of file diff --git a/_stable/server/hello-world.md b/_stable/server/hello-world.md index e36bcf6..f832cf3 100644 --- a/_stable/server/hello-world.md +++ b/_stable/server/hello-world.md @@ -126,6 +126,24 @@ async fn main() -> Result<(), Box> { To see all the snippets put together, check out the [full example][example]! +This example uses the `http1` module to create a server that speaks HTTP/1. +In case you want to use HTTP/2, you can use the `http2` module with a few changes to the +http1 server. The http2 builder requires an executor to run. Executor should implement the `hyper::rt::Executor` trait. + +```rust +impl hyper::rt::Executor for TokioExecutor +where + F: std::future::Future + Send + 'static, + F::Output: Send + 'static, + { + fn execute(&self, fut: F) { + tokio::task::spawn(fut); + } +} +``` + +The see the full example with HTTP/2, check out the [full example][example_http2]! + Also, if `service_fn` doesn't meet your requirements and you'd like to implement `Service` yourself, see this [example][impl service]. @@ -135,4 +153,5 @@ Also, if `service_fn` doesn't meet your requirements and you'd like to implement [response]: {{ site.hyper_docs_url }}/hyper/struct.Response.html [parts]: {{ site.http_docs_url }}/http/response/struct.Parts.html [example]: {{ site.examples_url }}/hello.rs +[example_http2]: {{ site.examples_url }}/hello-http2.rs [impl service]: {{ site.examples_url }}/service_struct_impl.rs From b28e497caab7e18df8363e7174b3308fe489a847 Mon Sep 17 00:00:00 2001 From: Nihal T M Date: Sat, 21 Sep 2024 13:31:20 +0530 Subject: [PATCH 5/5] Implemented suggestions --- _stable/server/hello-world.md | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/_stable/server/hello-world.md b/_stable/server/hello-world.md index f832cf3..372a019 100644 --- a/_stable/server/hello-world.md +++ b/_stable/server/hello-world.md @@ -5,7 +5,7 @@ layout: guide Let's start by making a "Hello, World!" server, and expand from there. -First we need to declare our dependencies, let's add the following to our `Cargo.toml`: +First, we need to declare our dependencies, let's add the following to our `Cargo.toml`: ```toml [dependencies] @@ -43,7 +43,7 @@ incoming requests. It represents an async function that takes a future is complete, it will resolve to a [`Response`][response] or an error. Hyper provides a utility for creating a `Service` from a function that should -serve most usecases: [`service_fn`][service_fn]. We will use this to create +serve most use cases: [`service_fn`][service_fn]. We will use this to create a service from our `hello` function below when we're ready to start our server. @@ -67,7 +67,7 @@ set automatically. ## Starting the Server -Lastly, we need to hook up our `hello` service into a running hyper server. +Lastly, we need to hook up our `hello` service into a running Hyper server. We'll dive in to the specifics of some of these things in another guide. @@ -126,26 +126,17 @@ async fn main() -> Result<(), Box> { To see all the snippets put together, check out the [full example][example]! +Also, if `service_fn` doesn't meet your requirements and you'd like to implement +`Service` yourself, see this [example][impl service]. + +## HTTP/2 + This example uses the `http1` module to create a server that speaks HTTP/1. In case you want to use HTTP/2, you can use the `http2` module with a few changes to the http1 server. The http2 builder requires an executor to run. Executor should implement the `hyper::rt::Executor` trait. -```rust -impl hyper::rt::Executor for TokioExecutor -where - F: std::future::Future + Send + 'static, - F::Output: Send + 'static, - { - fn execute(&self, fut: F) { - tokio::task::spawn(fut); - } -} -``` - -The see the full example with HTTP/2, check out the [full example][example_http2]! - -Also, if `service_fn` doesn't meet your requirements and you'd like to implement -`Service` yourself, see this [example][impl service]. +To implement the Executor, check out the runtime [example][runtime]. +To see the full example with HTTP/2, check out the [full example][example_http2]! [service]: {{ site.hyper_docs_url }}/hyper/service/trait.Service.html [service_fn]: {{ site.hyper_docs_url }}/hyper/service/fn.service_fn.html @@ -154,4 +145,5 @@ Also, if `service_fn` doesn't meet your requirements and you'd like to implement [parts]: {{ site.http_docs_url }}/http/response/struct.Parts.html [example]: {{ site.examples_url }}/hello.rs [example_http2]: {{ site.examples_url }}/hello-http2.rs +[runtime]: ../init/runtime.md [impl service]: {{ site.examples_url }}/service_struct_impl.rs