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

Ergonomic content negotiation #27

Open
aturon opened this issue Nov 8, 2018 · 7 comments
Open

Ergonomic content negotiation #27

aturon opened this issue Nov 8, 2018 · 7 comments
Labels
design Open design question

Comments

@aturon
Copy link
Collaborator

aturon commented Nov 8, 2018

Content negotiation is not (currently!) part of routing in Tide, but we should decide whether we want that to change, and if not, how to make it easy for an endpoint to internally perform content negotiation.

@aturon aturon added the design Open design question label Nov 8, 2018
@humb1t
Copy link

humb1t commented Oct 23, 2020

@aturon did you mean an ability to route based on requested content-type?
I was trying to return JSON or HTML based on it from one endpoint and looks like there is no ability to do that via tide:

      app.at("/courses/:id")
         .get(|request: Request<State>| async move { 
              match request.content_type() {
                  Some(mime::JSON) => Ok(request.state().courses().read(request.param("id").unwrap())),
                 Some(mime::HTML) => ResourceTemplate{}.into(), 
                  _ => Err("Unsupported Content-Type.")
              }
          })

Would be great to have more control over what I can return from one endpoint or for endpoints to be fine grained (not only path-based configuration).

@prabirshrestha
Copy link

nancyfx has an interesting way to do content negotiation. https://github.com/NancyFx/Nancy/wiki/Content-Negotiation

Get["/"] = parameters => {
    return Negotiate
        .WithModel(new RatPack {FirstName = "Nancy "})
        .WithMediaRangeModel("text/html", new RatPack {FirstName = "Nancy fancy pants"})
        .WithView("negotiatedview")
        .WithHeader("X-Custom", "SomeValue");
};

@yoshuawuyts
Copy link
Member

yoshuawuyts commented Oct 26, 2020

We're recently merged a foundation for content negotation into http-types: https://docs.rs/http-types/2.6.0/http_types/content/index.html -- it's not complete yet, but we should be able to use that to drive API experiments.

@yoshuawuyts
Copy link
Member

Note from triage: there are several different things content-negotation might mean, and we probably want to support all of them.

  • content-negotation for responses: serve up the right media type based on the accept headers passed by the client
  • routing based on content-type / accept
  • best-effort deserialization in an endpoint based on the incoming content-type; e.g. always succeed if json or xml passed

We should survey the field, and come up with implementations. We already have all typed headers for these, so we can try implementations.

@shulcsm
Copy link

shulcsm commented Dec 22, 2020

What is the current state of this?
You can't even do

        match request.content_type() {
            Some(mime::JSON) => {

error: to use a constant of type `tide::http_types::Mime` in a pattern, `tide::http_types::Mime` must be annotated with `#[derive(PartialEq, Eq)]`

@yoshuawuyts
Copy link
Member

yoshuawuyts commented Dec 24, 2020

It seems the root issue here is that we're not implementing StructuralEq for Mime. This can only be implemented through a derive, not a manual implementation like we have. This is a relatively easy fix, albeit noisy.

@yoshuawuyts
Copy link
Member

Ah, it appears we actually can't implement StructuralEq for Mime even if we forward the inner types. It seems this is wholly incompatible with custom PartialEq implementations like we have in Mime. And we need those in order to even be able to define constants. This means we're unfortunately limited by what the language is able to express right now.

Tracking issue on the compiler for this: rust-lang/rust#31434

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
design Open design question
Projects
None yet
Development

No branches or pull requests

5 participants