Reputation: 1751
I want to create a Flask error handler that returns a JSON response if the request was from JavaScript but returns a redirect otherwise. I tried using request.is_xhr
, but it is false even for JavaScript requests. How can I check if the request is from JavaScript?
@app.errorhandler(Exception)
def unhandled_exception(error):
if request.is_xhr:
return flask.jsonify(error='yes')
return redirect(url_for('error'))
Upvotes: 4
Views: 5654
Reputation: 31930
Rather than tie my app to a non-standard header I added an Accept:
header to my Javascript instead:
let req = new XMLHttpRequest();
req.open('POST', location);
// signal back-end to return json instead of rendering a full page:
req.setRequestHeader('Accept', 'application/json');
req.send(…);
And in my Python:
# if an ajax-like request, return json instead of html
if request.accept_mimetypes.best == 'application/json':
log.debug('client prefers json, skipping page render.')
return jsonify(status='errror', detail='…')
This should handle other use cases as they come up.
Upvotes: 1
Reputation: 1751
Answer by @davidism makes sense. is_xhr
was only true when a certain header was set by some JavaScript libraries. So, I have set header 'X-Requested-With' to 'XMLHttpRequest
' manually in '$httpProvider'
config in AngularJs
. This ensures that on the back end I will get 'is_xhr
' true for AJAX request.
app.config([
'$httpProvider',
function ($httpProvider) {
$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
var interceptor = [
'$q',
'$rootScope',
function ($q, $rootScope) {
'responseError': function (rejection) {
if(rejection.status != undefined && rejection.status != 'undefined') {
window.location.href = '/error';
}
}
};
return service;
}
];
$httpProvider.interceptors.push(interceptor);
}
]);
Upvotes: 1
Reputation: 2292
If the request is from a javascript/jquery code, is it most certainly from a browser so you can check the flask.request.user_agent
object which is a instance of werkzeug.useragents.UserAgent
to verify that.
Upvotes: -1
Reputation: 127340
There is no standard or reliable way to detect if a request comes from a particular source, such as JavaScript.
is_xhr
was only true when a certain header was set by some JavaScript libraries, such as jQuery. The header is not sent by most JavaScript. is_xhr
has been deprecated for that reason.
You can check the Accept
header to see if the client is asking for application/json
, but that too is unreliable.
if request.is_xhr or request.accept_mimetypes.accept_json:
return jsonify(...)
return redirect(...)
Upvotes: 3