Skip to content

Instantly share code, notes, and snippets.

@Thorsson
Forked from leereamsnyder/wantsJSON.js
Created September 13, 2016 14:30
Show Gist options
  • Save Thorsson/894dd98e1831136dfae7feeadc08d38d to your computer and use it in GitHub Desktop.
Save Thorsson/894dd98e1831136dfae7feeadc08d38d to your computer and use it in GitHub Desktop.
Detect if a request in Express is for HTML or JSON
/*
Usage:
var jsoncheck = require('./wantsJSON') // path to file with this middleware function
app.use(jsoncheck)
app.get('/', function(req,res,next){
if (req.wantsJSON) {
// serve JSON
}
if (req.wantsHTML) {
// serve HTML
}
})
But feel free to just scan the code and the bits you need
The Middleware below is super simple, but Google was letting me down
Here's what I was after: sometimes, clients, including browsers, would be requesting HTML,
and other times JSON, and I needed a simple way to detect between them.
This was surprisingly tough!
Some folks recommended using req.xhr http://expressjs.com/api.html#req.xhr
However, req.xhr only checks if the request’s “X-Requested-With” header field is “XMLHttpRequest”
In that situation, there's a solid chance the client wants JSON, but that's not a guarantee!
Maybe you'd think, "I could look for 'html' in the Accepts header!"
Solid theory!
Well, here's Internet Explorere's Accept header when requesting a web page:
> image/jpeg, application/x-ms-application, image/gif,
> application/xaml+xml, image/pjpeg, application/x-ms-xbap,
> application/x-shockwave-flash, application/msword, * /*
Note that "text/html" isn't there.
Yes, a web browser doesn't specify that it might be keen on HTML ( ._.)
Other things I found recommended using req.accepts('json')
However, if the client indicates they accept * / *, that says "hey JSON is OK!",
so req.accepts('json') will return "json" instead of undefined
You'll see this with most browsers: they have * / * in the Accepts header when requesting a web page.
The trick is to use req.accepts(), but specify both 'html' and 'json' IN THAT ORDER.
req.accepts('html','json') says, more or less:
Given the Accepts headers on this request (which take order into account),
AND given a choice between matching 'html' or 'json',
AND I prefer 'html', (based on the order of arguments)
which would be the best match?
That covers you:
browsers that accept text/html return "html"
IE that accepts * return "html"
If a request explicitly puts application/json before text/html or *, it'll get "json"
And that's probably what you want
*/
module.exports = function(res,res,next){
req.wantsJSON = req.accepts('html','json') === 'json';
req.wantsHTML = req.accepts('html','json') === 'HTML';
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment