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

Routing and rendering based on media type/content type negotiation #177

Closed
daenney opened this issue Apr 7, 2017 · 4 comments
Closed

Routing and rendering based on media type/content type negotiation #177

daenney opened this issue Apr 7, 2017 · 4 comments

Comments

@daenney
Copy link

daenney commented Apr 7, 2017

I'm looking for some advice on how to potentially do routing and rendering based on media type. As some might have seen a number of API's use content type negotiation with things like content-type: application/vnd.github.v3+json for example, to define that you want the v3 representation of the resource in JSON format without encoding that in the URL.

In trying to figure out how to do that it in Chi I got a little stuck. It seems that I would need two things which Chi already does (a combination of the versions and render examples) but modified in such a way that it's not centred around version information being encoded in the URL.

So it seems to me I would need two things:

  • A middleware similar to the one from the versions example to extract the API version out of the content-type header and dispatch based on those (like the articleRouter() does)
  • A patch(?) to the render package so that aside from the few predefined content type headers it recognises it's also able to scan something like application/vnd.github.v3+json and understand that it then should treat it as if it were a ContentTypeJSON but simply set a slightly different header from application/json in the response.

That second part, how to use and amend render, is where I'm mostly stuck at figuring out how to elegantly do. Does anyone have any pointers for me on how I could proceed with this? Is there also something obvious you feel I've missed?


P.S I'm not looking to get into a debate about REST API versioning. This is an experiment to see how I could achieve API versioning through content type negotiation with Chi.

@pkieltyka
Copy link
Member

Hey @daenney this is completely doable with chi today :)

The approach I'd suggest based on your description is to create a middleware and put it at the very top of your routing tree, where that middleware parses the request "Accept" header and sets on the context the kind of content response type, and the API version number, then you'll need some helper function or various possibilities to use the right render.Renderer to handle payloads for your respective version.

@pkieltyka
Copy link
Member

pkieltyka commented Apr 7, 2017

Give it a shot, perhaps in a small example forking from _examples/rest and let me know where you come to. If you give me a gist or some working example I may be able to help. The only part that needs some consideration is the pattern to select the appropriate renderer, but given that it's an interface, you could compose Renderers like you do middlewares -- as in, for each kind of payload type, which would read the r.Context(), check the version and then call its versioned payload Renderer method. I initially left it as an exercise for the reader :) there are lots of possibilities.

@daenney
Copy link
Author

daenney commented Apr 13, 2017

Sorry for my lack of response on this! I've gotten the middleware part to work, that was fairly easy. I'm mostly stuck with the Renderer, I'm not quite clear how you mean to compose that like the way you could compose middleware? Do you have a (pseudocode) example of what that could look like?

@pkieltyka
Copy link
Member

btw, the chi/render package has been moved to its own project repo at https://github.com/go-chi/render

Made a reference here go-chi/render#1

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

No branches or pull requests

2 participants