Mayur Patel
Mayur Patel

Reputation: 1751

Identify if Flask request is from JavaScript or not

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

Answers (4)

Gringo Suave
Gringo Suave

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

Mayur Patel
Mayur Patel

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

lee-pai-long
lee-pai-long

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

davidism
davidism

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

Related Questions