我已经查看了许多SO答案,但似乎找不到这个问题。我感觉我可能只是错过了一些显而易见的东西。
我有一个基本的Flask API,并实现了flask_cors扩展和自定义的Flask修饰器 [@crossdomain from Armin Ronacher]1 (http://flask.pocoo.org/snippets/56/) ,两者都显示相同的问题。
这是我的示例应用程序:
application = Flask(__name__,
static_url_path='',
static_folder='static')
CORS(application)
application.config['CORS_HEADERS'] = 'Content-Type'
@application.route('/api/v1.0/example')
@cross_origin(origins=['http://example.com'])
# @crossdomain(origin='http://example.com')
def api_example():
print(request.headers)
response = jsonify({'key': 'value'})
print(response.headers)
return response
(已插入EDIT 3):
当我从浏览器中的JS向该端点发出GET请求时(来自127.0.0.1),它总是返回200,而我希望看到的是:
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:5000' is therefore not allowed access. The response had HTTP status code 403.
CURL:
ACCT:ENVIRON user$ curl -i http://127.0.0.1:5000/api/v1.0/example
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 20
Access-Control-Allow-Origin: http://example.com
Server: Werkzeug/0.11.4 Python/2.7.11
Date: [datetime]
{
"key": "value"
}
日志:
Content-Length:
User-Agent: curl/7.54.0
Host: 127.0.0.1:5000
Accept: */*
Content-Type:
Content-Type: application/json
Content-Length: 20
127.0.0.1 - - [datetime] "GET /api/v1.0/example HTTP/1.1" 200 -
我甚至没有看到响应中的所有正确标头,并且似乎不关心请求的来源。有什么想法吗?谢谢!
编辑:
另外,查看文档示例这里(https://flask-cors.readthedocs.io/en/v1.7.4/#a-more-complicated-example),它显示:
@app.route("/")
def helloWorld():
'''
Since the path '/' does not match the regular expression r'/api/*',
this route does not have CORS headers set.
'''
return '''This view is not exposed over CORS.'''
...这很有趣,因为我已经暴露了根路径(和其他路径),没有任何CORS装饰,而且它们从任何来源都可以正常工作。所以似乎这个设置存在根本性的问题。
在这方面,教程(此处)(https://blog.miguelgrinberg.com/post/designing-a-restful-api-with-python-and-flask)似乎表明Flask API应该自然地暴露而不受保护(我认为这只是因为CORS扩展还没有被应用),但我的应用程序基本上就像CORS扩展甚至不存在一样运行(除了日志中的一些注释,您可以看到)。
编辑2:
我的评论不太清楚,因此我在AWS API Gateway上创建了三个具有不同CORS设置的示例端点。它们是简单返回“success”的GET方法端点:
1)未启用CORS(默认):
响应:
XMLHttpRequest无法加载 https://t9is0yupn4.execute-api.us-east-1.amazonaws.com/prod/cors-default。 Preflight请求的响应未通过访问控制检查:所请求的资源上没有'Access-Control-Allow-Origin'头。因此,源'http://127.0.0.1:5000'不允许访问。响应的HTTP状态代码为403。
2)启用CORS-来源受限:
Access-Control-Allow-Headers:'Content-Type'
Access-Control-Allow-Origin:'http://example.com'
- 端点:https://t9is0yupn4.execute-api.us-east-1.amazonaws.com/prod/cors-enabled-example
响应:
XMLHttpRequest无法加载https://t9is0yupn4.execute-api.us-east-1.amazonaws.com/prod/cors-enabled-example。 预检请求的响应未能通过访问控制检查:'Access-Control-Allow-Origin'标头的值为http://example.com,而不是提供的来源'http://127.0.0.1:5000'。因此,不允许访问该来源。3)启用CORS - 来源通配符:
- Access-Control-Allow-Headers:'Content-Type'
- Access-Control-Allow-Origin:'*'
- 端点:https://t9is0yupn4.execute-api.us-east-1.amazonaws.com/prod/cors-enabled-wildcard
"success"
我对基础设施不是很有经验,但我期望启用Flask CORS扩展程序后,我的api端点会根据我在
origins=
设置中设置的内容而模仿这种行为。在这个Flask设置中,我漏掉了什么?
解决方案编辑:
好吧,鉴于我的某些地方显然不正常,我精简了我的应用程序,并为每个CORS来源限制的变化重新实现了一些非常基本的API。我一直在使用AWS弹性Beanstalk来托管测试环境,所以我重新上传了那些示例并运行了一个JS ajax请求。它现在可以工作。
我在裸露的端点上遇到了
Access-Control-Allow-Origin
错误。似乎当我为部署配置应用程序时取消注释CORS(application, resources=r'/api/*')
时,这显然允许所有起源访问裸露的端点!我不确定为什么我的具有特定限制(
origins=[]
)的路由也允许一切,但那一定是一些小错误或笔误之类的东西,因为现在它正在工作。特别感谢sideshowbarker提供的帮助!
origins=
setting”这句话的意思。 - sideshowbarker