【问题标题】:Identify if Flask request is from JavaScript or not确定 Flask 请求是否来自 JavaScript
【发布时间】:2023-12-08 10:36:01
【问题描述】:

我想创建一个 Flask 错误处理程序,如果请求来自 JavaScript,则返回 JSON 响应,否则返回重定向。我尝试使用request.is_xhr,但即使对于 JavaScript 请求也是错误的。如何检查请求是否来自 JavaScript?

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

    return redirect(url_for('error'))

【问题讨论】:

    标签: python angularjs ajax flask


    【解决方案1】:

    我没有将我的应用绑定到非标准标头,而是在我的 Javascript 中添加了 Accept: 标头:

    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(…);
    

    在我的 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='…')
    

    这应该处理出现的其他用例。

    【讨论】:

    • 那么,我需要在每个 AJAX 请求上设置请求头吗??
    • 看起来您可以使用上面的 angular …headers.common… 行进行尝试。
    • 是否有任何共同的地方可以为所有 AJAX 调用进行配置?因为我的应用程序中有很多 AJAX 调用,而且我很难在任何地方找到和放置。
    • 好多年没用了,抱歉。但我建议为 ajax 调用创建一个函数,然后在任何地方重用它。
    【解决方案2】:

    @davidism 的回答很有道理。 is_xhr 只有在某些 JavaScript 库设置了某个标头时才为真。所以,我在'$httpProvider''$httpProvider' 配置中手动将标题“X-Requested-With”设置为“XMLHttpRequest”。这确保了在后端我会得到 'is_xhr' 对于 AJAX 请求为真。

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

    【讨论】:

      【解决方案3】:

      如果请求来自 javascript/jquery 代码,那么它肯定来自浏览器,因此您可以检查 flask.request.user_agent 对象,它是 werkzeug.useragents.UserAgent 的一个实例来验证这一点。

      【讨论】:

        【解决方案4】:

        没有标准或可靠的方法来检测请求是否来自特定来源,例如 JavaScript。

        is_xhr 仅在某些 JavaScript 库(例如 jQuery)设置某个标头时为真。大多数 JavaScript 不发送标头。出于这个原因,is_xhr 已被弃用。

        您可以检查Accept 标头以查看客户端是否在请求application/json,但这也不可靠。

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

        【讨论】: