jshttp / type-is

Infer the content-type of a request.
MIT License
228 stars 33 forks source link

Support for media type version request #14

Open bazwilliams opened 9 years ago

bazwilliams commented 9 years ago

We use vendor specific media types for all our resources and use versions to differentiate between breaking changes to that resource.

For example:

application/vnd.linn.space-configuration+json; version=1

is our current media type for application/vnd.linn.space-configuration+json and type-is correctly returns the type when +json is used. However, the versioning is lost and we have no way to differentiate between a version 2 of this resource when it becomes available.

dougwilson commented 9 years ago

Hi! We are actually actively working on this problem :) This module depends on the negotiator module to do the work, and we have a PR https://github.com/jshttp/negotiator/pull/40 that is trying to get the parameters exposed when you get a negotiation result. Let me know if this seems to fit what you're looking for or not :)

bazwilliams commented 9 years ago

That looks just the thing. We could ideally provide the following as type params:

[{
    mediaType: 'application/vnd.linn.space-configuration+json',
    version: 1
}, {
    mediaType: 'application/vnd.linn.sapce-configuration+json',
    version: 2
}, {
    mediaType: 'json'
}]
dougwilson commented 9 years ago

We could ideally provide the folliowing as type params

As in, input to this library? If that is that you're suggesting, we already do offer that:

typeis(req, ['application/vnd.linn.space-configuration+json; version=1', 'application/vnd.linn.sapce-configuration+json; version=2', 'json'])
dougwilson commented 9 years ago

Hi @bazwilliams , sorry this went stale, but it looks like I was waiting for clarification to my question. Can you clarify?

bazwilliams commented 9 years ago

Yes, using type-is to match the entire string including version does work, but doesn't provide much additional benefit over comparing the header directly.

dougwilson commented 9 years ago

Ok, but you still haven't cleared up to me what you want me to do. Can you elaborate more on what you mean in https://github.com/jshttp/type-is/issues/14#issuecomment-111172617 ?

bazwilliams commented 9 years ago

Sorry I wasn't clear.

If you run the following code:

var is=require('type-is');

var req = {
        headers: {
            'content-type': 'application/vnd.linn.test+json; version=1',
            'transfer-encoding': 'chunked'
        }
    };

//Should be false
console.log(is(req,['application/json']));

//Should be application/vnd.linn.test+json
console.log(is(req,['+json']));

//Should be application/vnd.linn.test+json
console.log(is(req,['application/vnd.linn.test+json']));

//Should be application/vnd.linn.test+json, but also want access to the version which matched!
console.log(is(req,['application/vnd.linn.test+json; version=1', 'application/vnd.linn.test+json; version=2']));

The first 3 examples give output that I would expect. But the last fails to match.

Further, it would be useful to be able to find out which version was requested, but particularly important in the last example where our code can receive both version 1 and 2 requests. But unless we parse the header manually, cannot tell what the version of the content-type is.

dougwilson commented 9 years ago

Gotcha, makes sense now. So yes, this library doesn't let you match on the parameters. The only way you can do it currently is to include the content-type library to get the library:

var contentType = require('content-type')
var typeis = require('type-is')

// ... later on

if (typeis(req, 'application/vnd.linn.test+json')) {
  console.log('accepts application/vnd.linn.test+json with version ' + contentType.parse(req).parameters.version)
}

PRs to add things like this are always welcome, though, if the above is not an acceptable solution for you.

bazwilliams commented 9 years ago

Cheers for the workaround, I'd definitely prefer the library to do this so will fork tomorrow for a future PR.