I would like to check if the type that is requested by my client is JSON or HTML, as I want my route to satisfy both human and machine needs.
I have read the Express 3 documentation at:
http://expressjs.com/api.html
And there are two methods req.accepts()
and req.is()
, used like this:
req.accepts('json')
or
req.accepts('html')
Since these are not working as they should, I tried using:
var requestType = req.get('content-type');
or
var requestType = req.get('Content-Type');
requestType
is always undefined
...
Using the suggestion at this thread:
Express.js checking request type with .is() doesn't work
does not work either. what am I doing wrong?
Edit 1: I have checked for correct client HTML negotiation. Here are my two different request headers (taken from the debugger inspector):
HTML :
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
JSON :
Accept: application/json, text/javascript, */*; q=0.01
Solution (thanks to Bret):
Turns out I was specifying the Accept headers wrong, and the */*
was the issue. Here is the code that works!
//server (now works)
var acceptsHTML = req.accepts('html');
var acceptsJSON = req.accepts('json');
if(acceptsHTML) //will be null if the client does not accept html
{}
I am using JSTREE, a jQuery plugin that uses jQuery Ajax calls underneath). The parameters passed to the Ajax call are in the "ajax" field, and I have replaced the "accepts" parameter with a complete "headers" object. Now it works, and should solve the problem when you are using plain jQuery if it should ever occur.
//client
.jstree({
// List of active plugins
"plugins" : [
"themes","json_data","ui","crrm","cookies","dnd","search","types","hotkeys","contextmenu"
],
"json_data" : {
"ajax" : {
// the URL to fetch the data
"url" : function(n) {
var url = n.attr ? IDMapper.convertIdToPath(n.attr("id")) : "<%= locals.request.protocol + "://" + locals.request.get('host') + locals.request.url %>";
return url;
},
headers : {
Accept : "application/json; charset=utf-8",
"Content-Type": "application/json; charset=utf-8"
}
}
}
})
var requestType = req.get('Content-Type');
definitely works if a content-type was actually specified in the request (I just re-verified this a minute ago). If no content-type is defined, it will be undefined. Keep in mind that typically only POST and PUT requests will specify a content type. Other requests (like GET) will often specify a list of accepted types, but that's obviously not the same thing.
EDIT:
Okay, I understand your question better now. You're talking about the Accept: header, not content-type.
Here's what's happening: notice the */*;q=0.8
at the end of listed accept types? That essentially says "I'll accept anything." Therefore, req.accepts('json')
is always going to return "json"
because technically it's an accepted content type.
I think what you want is to see if application/json
is explicitly listed, and if so, respond in json, otherwise respond in html. This can be done a couple of ways:
// a normal loop could also be used in place of array.some()
if(req.accepted.some(function(type) {return type.value === 'application/json';}){
//respond json
} else {
//respond in html
}
or using a simple regular expression:
if(/application\/json;/.test(req.get('accept'))) {
//respond json
} else {
//respond in html
}
It's a bit later, but I found this a better solution for me:
req.accepts('html, json') === 'json'
Hope it helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With