Determine if the 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 to use request.is_xhr

but it is not correct even for JavaScript requests. How can I check if a request is JavaScript?

@app.errorhandler(Exception)
def unhandled_exception(error):
    if request.is_xhr:
        return flask.jsonify(error='yes')

    return redirect(url_for('error'))

      

+3


source to share


4 answers


@Davidism's answer to this makes sense. is_xhr

was only right when a certain header was set by some JavaScript libraries. So, I set the "X-Requested-With" header to " XMLHttpRequest

" manually in '$httpProvider'

config in AngularJs

. This ensures that on the back I get is_xhr

true for the 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);
    }
]);

      

+1


source


There is no standard or reliable way to determine if a request is coming from a specific source like JavaScript.

is_xhr

was only right when a certain header was set by some JavaScript libraries like jQuery. The header is not sent by most JavaScript. is_xhr

for this reason is deprecated.



You can check the header Accept

to see if the client is requesting application/json

, but that is unreliable too.

if request.is_xhr or request.accept_mimetypes.accept_json:
    return jsonify(...)

return redirect(...)

      

+3


source


Instead of binding my app to a custom header, I added a header Accept:

to my Javascript:

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 arise.

+1


source


If the request is javascript / jquery code, it is definitely from the browser, so you can check the object flask.request.user_agent

that is an instance werkzeug.useragents.UserAgent

to see if.

-1


source







All Articles