Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(util): add ResponseExt trait #150

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

joshka
Copy link

@joshka joshka commented Mar 25, 2025

This adds a ResponseExt trait to the http_body_util crate. This
trait provides two methods, box_body and box_body_unsync, which
allow you to box the body of an http::Response to make writing code
that returns responses with different body types easier.

use bytes::Bytes;
use http::{Response, StatusCode};
use http_body_util::{Empty, Full, ResponseExt};

let response = match uri.path() {
    "/greeting" => greeting().box_body(),
    "/empty" => empty().box_body(),
    _ => not_found().box_body(),
}

fn greeting() -> Response<String> {
    Response::new("Hello, World!".to_string())
}

fn empty() -> Response<Empty<Bytes>> {
    Response::new(Empty::new())
}

fn not_found() -> Response<Full<Bytes>> {
    Response::builder()
        .status(StatusCode::NOT_FOUND)
        .body("Not Found".into())
        .unwrap()
}

This adds a `ResponseExt` trait to the `http_body_util` crate. This
trait provides two methods, `box_body` and `box_body_unsync`, which
allow you to box the body of an `http::Response` to make writing code
that returns responses with different body types easier.

```rust
use bytes::Bytes;
use http::{Response, StatusCode};
use http_body_util::{Empty, Full, ResponseExt};

let response = match uri.path() {
    "/greeting" => greeting().box_body(),
    "/empty" => empty().box_body(),
    _ => not_found().box_body(),
}

fn greeting() -> Response<String> {
    Response::new("Hello, World!".to_string())
}

fn empty() -> Response<Empty<Bytes>> {
    Response::new(Empty::new())
}

fn not_found() -> Response<Full<Bytes>> {
    Response::builder()
        .status(StatusCode::NOT_FOUND)
        .body("Not Found".into())
        .unwrap()
}
```
joshka added a commit to joshka/techempower-benchmarks that referenced this pull request Mar 25, 2025
- move the server header to the router and add it to all responses.
- move the response boxing to the router simplifying the return types of
  each handler.

hyperium/http-body#150 will simplify the router
code even futher to the following:

```rust
let mut response = match request.uri().path() {
     "/ping" => ping()?.box_body(),
     "/json" => json::get()?.box_body(),
     "/db" => single_query::get().await?.box_body(),
     "/queries" => multiple_queries::get(request.uri().query()).await?.box_body(),
     "/fortunes" => fortunes::get().await?.box_body(),
     "/plaintext" => plaintext::get()?.box_body(),
     _ => not_found_error()?.box_body(),
};
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant