Swa*_*nil 8 django google-app-engine nginx cors
我一直在尝试在Google应用引擎上启用CORS标头,但我在互联网上找到的方法都不适合我.
我的应用程序是在Python/Django上,我希望我的前端应用程序(单独托管)能够在Google App Engine上对我的后端平台进行API调用.
2017年1月发行说明说明了这一点
我们正在改变可扩展服务代理(ESP)的行为以默认拒绝跨源资源共享(CORS)请求
这里可以看到
并且启用它们提供的CORS的解决方案是将以下片段添加到服务的OpenAPI配置中.
"host": "echo-api.endpoints.YOUR_PROJECT_ID.cloud.goog",
"x-google-endpoints": [
{
"name": "echo-api.endpoints.YOUR_PROJECT_ID.cloud.goog",
"allowCors": "true"
}
],
...
Run Code Online (Sandbox Code Playgroud)
所以我按照这个例子在我的代码库中创建了两个文件
openapi.yml:
swagger: "2.0"
info:
description: "Google Cloud Endpoints APIs"
title: "APIs"
version: "1.0.0"
host: "echo-api.endpoints.<PROJECT-ID>.cloud.goog"
x-google-endpoints:
- name: "echo-api.endpoints.<PROJECT-ID>.cloud.goog"
allowCors: "true"
paths:
"/api/v1/sign-up":
post:
description: "Sends an email for verfication"
operationId: "signup"
produces:
- "application/json"
responses:
200:
description: "OK"
parameters:
- description: "Email address of the user"
in: body
name: email
required: true
schema:
type: string
- description: "password1"
in: body
name: password1
required: true
schema:
type: string
- description: "password2"
in: body
name: password2
required: true
schema:
type: string
Run Code Online (Sandbox Code Playgroud)
OpenAPI的-appengine.yml:
swagger: "2.0"
info:
description: "Google Cloud Endpoints API fo localinsights backend server"
title: "Localinsights APIs"
version: "1.0.0"
host: "<PROJECT-ID>.appspot.com"
Run Code Online (Sandbox Code Playgroud)
然后我运行了这个命令:
gcloud service-management deploy openapi.yml
Run Code Online (Sandbox Code Playgroud)
然后我编辑了我的app.yml文件使它看起来像这样(添加了endpoints_api_service.在添加之前,应用程序部署没有任何错误):
runtime: python
env: flex
entrypoint: gunicorn -b :$PORT myapp.wsgi
beta_settings:
cloud_sql_instances: <cloud instance>
runtime_config:
python_version: 3
automatic_scaling:
min_num_instances: 1
max_num_instances: 1
resources:
cpu: 1
memory_gb: 0.90
disk_size_gb: 10
env_variables:
DJANGO_SETTINGS_MODULE: myapp.settings.staging
DATABASE_URL: <dj-database-url>
endpoints_api_service:
name: "<PROJECT-ID>.appspot.com"
config_id: "<CONFIG-ID>"
Run Code Online (Sandbox Code Playgroud)
然后我刚刚部署了应用程序
gcloud app deploy
Run Code Online (Sandbox Code Playgroud)
现在,该应用程序已成功部署,但它表现得很奇怪.应该返回200响应的所有请求仍然会抛出CORS错误,但返回400状态的请求确实有效.
例如 - 注册API需要这些字段 - email,password1,password2,其中password1应与password2相同.现在,当我发送正确的参数时,我得到HTTP 502说
请求的资源上不存在"Access-Control-Allow-Origin"标头.因此,不允许原始{origin-url}访问.响应具有HTTP状态代码502
但是当我发送密码1与密码2不同时,我得到HTTP 400响应,我确信它来自我的代码,因为如果密码1和密码2不匹配,则响应是代码中写的字典.同样在这种情况下,标题具有Access-Control-Allow-Origin*,但在前一种情况下,这不是真的
我还检查了我的nginx错误日志
*27462上游过早关闭连接,同时读取响应头
我在这做错了什么?这是在GAE中启用CORS的正确方法吗?
经过几天的摸索,我终于找到了真正的问题所在。我的数据库服务器拒绝与 web 应用程序服务器的任何连接。
由于在 HTTP 200 响应的情况下,Web 应用程序应该进行数据库调用,因此 Web 应用程序尝试连接到数据库服务器。该连接花费的时间太长,一旦超出 NGINX 的超时时间,NGINX 就会向 Web 浏览器发送状态代码为 502 的响应。
由于“access-control-allow-origin”标头是从 web 应用程序设置的,NGINX 并未在其响应中设置该标头。因此,浏览器将其解释为 CORS 拒绝。
一旦我将数据库服务器的 Web 应用程序实例的 IP 地址列入白名单,一切就开始顺利运行
概括:
更新:
只是想更新我的答案以指定您不必将实例的 IP 添加到 SQL 实例的白名单 IP 中的方式
像这样配置数据库:
DATABASES = {
'HOST': <your-cloudsql-connection-string>, # This is the tricky part
'ENGINE': <db-backend>,
'NAME': <db-name>,
'USER': <user>,
'PASSWORD': <password>
}
Run Code Online (Sandbox Code Playgroud)
记下数据库中的 HOST 密钥。GAE 有一种方法,您不必将实例的 IP 列入白名单,但要使其正常工作,主机应该是cloudsql-connection-string而不是 SQL 实例的 IP。
如果您不确定您的 cloudsql-connection-string 是什么,请转到 Google 云平台仪表板并选择存储部分下的 SQL 选项卡。您应该看到一个表,其中有一列实例连接名称。此列下的值是您的 cloudsql-connection-string。
| 归档时间: |
|
| 查看次数: |
937 次 |
| 最近记录: |