1

我有一个使用 Flask 和 Flask-Restful 创建的 RESTful API。使用开发服务器一切正常。所有路线都在蓝图中,尽管我们在这里处理的特定路线不是 Flask-Restful 路线。这只是一条普通的 Flask 路线。

我也在使用 Flask-CORS。

部署时,一切都是 dockerized,我使用 CherryPy 作为 WSGI 主机。因此,CherryPy 应用程序将 Flask 应用程序托管在容器中。我在另一个容器中使用 Traefik 作为反向代理。

如果我通过粘贴 URL 在 Chrome 中发出以下请求,则 GET 请求有效:

https://api.my-app.new/api/admin/user?_end=10&_order=DESC&_sort=id&_start=0

但是,如果我尝试从 React 应用程序发出相同的 GET 请求,则会发出一个 OPTIONS 预检请求,但它会以 404 失败。我已经尽我所能在 PyCharm 中跟踪它,问题似乎出在Flask 的 app.py 中的以下代码:

def preprocess_request(self):
    bp = _request_ctx_stack.top.request.blueprint

基本上没有找到蓝图。

在这个 curl 调用中可以看到实际发送的内容:

curl 'https://api.my-app.new/api/admin/user?_end=10&_order=DESC&_sort=id&_start=0' \
     -X OPTIONS -H 'access-control-request-method: GET' -H 'origin: https://admin.my-app.new' \
     -H 'accept-encoding: gzip, deflate, br' -H 'accept-language: en-US,en;q=0.9' \
     -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36' \
     -H 'accept: */*' -H 'referer: https://admin.my-app.new/' -H 'authority: api.my-app.new' \
     -H 'access-control-request-headers: authorization,content-type' --compressed

如果我打印出 Flask-app 收到的标头(在 @app.before_request 中),我会得到以下信息:

[2018-01-25 04:31:48,438] INFO - X-Forwarded-Server: cb5d56692c6d
Referer: https://admin.my-app.new/
Accept-Language: en-US,en;q=0.9
Origin: https://admin.my-app.new
X-Real-Ip: 172.19.0.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
Access-Control-Request-Headers: authorization,content-type
X-Forwarded-Proto: https
Host: api.my-app.new
Accept: */*
Access-Control-Request-Method: GET
X-Forwarded-Host: api.my-app.new
X-Forwarded-For: 172.19.0.1
X-Forwarded-Port: 443
Accept-Encoding: gzip, deflate, br

[2018-01-25 04:31:48,440] INFO - Error 404:/api/admin/user?_end=10&_order=DESC&_sort=id&_start=0: 404 Not Found: The requested URL was not found on the server.  If you entered the URL manually please check your spelling and try again. ("/app/app/routes.py:87")

现在,如果我在没有 traefik 反向代理的情况下运行应用程序时发出相同的请求,它就可以工作。curl请求中唯一不同的是我使用的是http,而不是https。

以下是 Flask 在这种情况下收到的标头:

[2018-01-24 21:43:43,199] INFO - Referer: https://admin.my-app.new/
Origin: https://admin.my-app.new
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
Authority: api.my-app.new
Access-Control-Request-Headers: authorization,content-type
Host: api.my-app.new:8000
Accept: */*
Access-Control-Request-Method: GET
Accept-Language: en-US,en;q=0.9
Accept-Encoding: gzip, deflate, br

[24/Jan/2018 21:43:43] "OPTIONS /api/admin/user?_end=10&_order=DESC&_sort=id&_start=0 HTTP/1.1" 200 -

我认为标题有问题或使 Flask 感到困惑。我看到 2014 年的另一篇文章提到需要 SERVER_NAME,但这没有帮助。

最后,我最初使用 NGinx 作为备用代理,并且一切正常。难以使用 NGinx 的一件事是重定向和 OPTION 请求。在疯狂地追逐各种博客文章之后,我确实让它工作了,但是当我回顾它时,我注意到了一件奇怪的事情:我最终在 nginx.conf 中编写脚本以自动为所有 OPTIONS 请求返回 200!

知道为什么 OPTION 请求失败了吗?

4

1 回答 1

1

正如 webKnjaZ 所说:“这是一个错误。”

在深入研究之后,我发现 Flask 获取 GET 请求的 URL 与 OPTIONS 请求的 URL 不同的问题,如果 CherryPy 被删除,问题就消失了。这让我想到了这个 CherryPy 问题,它准确地描述了我的情况。

https://github.com/cherrypy/cherrypy/issues/1662

作者注意到从 CherryPy 11 迁移到 12(我在 13.x 上)时出现了该错误,因此我尝试降级到 11.0.0 并修复了它。

于 2018-01-26T13:12:20.773 回答