Giter VIP home page Giter VIP logo

Comments (5)

seanmonstar avatar seanmonstar commented on August 15, 2024 1

Thanks for the detailed write up! We've also been interested in something like WSGI/Rack/Servlet. Hopefully with the community's help, we can make something stellar.


In regards to T having no bounds: This is actually a benefit!

First of all, by not having bounds on the body generic, this allows the crate to be used in both asynchronous frameworks and in synchronous. Requiring a trait bounds would likely hamper one of those sides. Likely, framework ecosystems will show up that do require a bounds. You could imagine a framework that behaves somewhat like hyper today, where T: Stream is required.

Secondly, this allows for application writers to have these bounds at the borders, but to then map them into anything they want internally. So, if an framework receives Request<T> where T: Stream<Item=Vec<u8>, Error=io::Error>, a user could map the request into something like a Request<Comment> internally. Something like this:

fn framework_entrypoint<T>(req: Request<T>) -> BoxFuture<Response<T>, io::Error>
where T: Stream<Item=Vec<u8>, Error=io::Error> {
    if req.method() == POST && req.uri().path() == "/article/comment" {
        let (head, body) = req.into_parts();
        body.concat2().map(move |vec| {
            let comment = serde_json::from_slice(&vec)?;
            let req = Request::from_parts(head, comment);
            post_comment_for_article(req)
        })
    }
    // ...
}

#[derive(Deserialize)]
struct Comment {
    author: String,
    body: String,
}

fn post_comment_for_article(req: Request<Comment>) -> Something {
    // ...
}

Additionally, any sort of middleware that only adjusts headers can be made to work for any framework, since it can just put zero bounds on the body (since it won't look at the body anyways).

fn apply_cors<T>(res: &mut Response<T>, options: &CorsOptions) {
    res.headers_mut().insert(name, value);
}

from http.

carllerche avatar carllerche commented on August 15, 2024

It looks like the discussion here came to a close.

from http.

jimmycuadra avatar jimmycuadra commented on August 15, 2024

We're discussing this issue right now in the Ruma project. We use an Endpoint trait for each API endpoint which converts between http request and response types and our own concrete request and response types defined for each API endpoint. We have a crate (ruma-client-api) that implements these conversions, and a separate crate (ruma-client) that actually provides an HTTP client using Hyper. Notably, Ruma is only bound to Hyper at the level of ruma-client.

Our goal is to keep ruma-api and ruma-client-api agnostic to HTTP client implementations. Without the ability to constrain what type "body" is, and in the absence of any convention in the Rust HTTP ecosystem, there's no way to:

  1. Implement our Endpoint trait, because we need some knowledge of what the body is
  2. Keep it interoperable with potential other HTTP clients.

To make item 1 possible, we'd need to add a restriction that the body is a Stream whose items can be deref coerced into [u8]. That would make it work with Hyper's Body and Chunk types. But we have no way of knowing whether or not such an interface would be compatible with other HTTP clients. Perhaps a convention will emerge in the ecosystem, but the unconstrained generic type in http means that there's no real way to future proof this.

from http.

carllerche avatar carllerche commented on August 15, 2024

The HTTP crate specifically does not want to constrain request / response bodies to anything that resembles bytes. This would prevent storing a typed representation of the body.

from http.

jimmycuadra avatar jimmycuadra commented on August 15, 2024

Yep, I understand the reason it's designed the way it is. But the issue brought up here is a cost of this design. The crate offers types for everything except req/res bodies, and as a result req/res bodies cannot be interoperable between higher level crates that both use http.

Perhaps a way of meeting in the middle would be to add traits to represent the most common scenarios: an async stream of bytes, and a sync collection of bytes. That way downstream crates could opt in to constraining the body types to one of these traits and be interoperable. Use cases that don't want this don't need to do anything different than they're doing now.

from http.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.