Firebase托管应用引擎网址的Access-Control-Allow-Origin

时间:2017-02-07 16:00:19

标签: firebase firebase-hosting

我在Firebase托管上托管单页应用,我需要允许跨域请求到应用引擎。应用程序托管在project-id.firebaseapp.com上,app-引擎服务托管在project-id.appspot.com上。我红了deployment documentation并且没有示例如何为URL添加Access-Control-Allow-Origin标头。

这是我的firebase.json的样子:

{
  "database": {
    "rules": "database.rules.json"
  },
  "hosting": {
    "public": "public",
    "redirects": [
      {
        "source": "/server/:rest*",
        "destination": "https://app-id.appspot.com/:rest*",
        "type": 301
      }
    ],
    "rewrites": [
      {
        "source": "/views/**",
        "destination": "/views/**"
      },
      {
        "source": "**",
        "destination": "/index.html"
      }
    ],
    "headers": [ {
      "source" : "https://app-id.appspot.com/registration/generate",
      "headers" : [ {
        "key" : "Access-Control-Allow-Origin",
        "value" : "*"
      } ]
    } ]
  }
}

我尝试使用gsutils设置CORS,但它也没有帮助:

这是我的cors.json

[
    {
        "maxAgeSeconds": 3600, 
        "method": ["GET", "POST"], 
        "origin": ["https://project-id.appspot.com/"]
    }
]

提前致谢

解决方案:

如果您只想在静态文件上允许CORS,那么在app.yaml中设置Access-Control-Allow-Origin标头就足够了。对于动态请求,此标头不允许在app.yaml中,因此您必须以编程方式添加它。

如果您的请求很简单,则以下代码有效:

@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) 
    resp.addHeader("Access-Control-Allow-Origin", "*");
    resp.addHeader("Content-Type", "text/csv");
    resp.getWriter().append("Response");

}

但是,如果您的请求已预先通过,则您必须覆盖doOptions方法并添加相应的标头:

@Override
protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    resp.addHeader("Access-Control-Allow-Origin", "*");
    resp.addHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
    resp.addHeader("Access-Control-Allow-Headers", "Content-Type");
}

@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    resp.addHeader("Access-Control-Allow-Origin", "*");
    resp.addHeader("Content-Type", "text/csv");
    resp.getWriter().append("Response");
}

Here是一个有用的图表,阐明了服务器上的CORS实现:

1 个答案:

答案 0 :(得分:7)

您的firebase.json无法控制appspot.com文件,也无法用于修改您的应用引擎服务中的标头。在此,您已尝试在Access-Control-Allow-Origin上设置https://app-id.appspot.com/registration/generate。这不起作用,因为那不是Firebase Hosting托管的页面。

相反,将标题添加到Firebase页面的方式是将它放在firebase.json中,如下所示:

"headers": [ {
  "source" : "index.html",
  "headers" : [ {
    "key" : "Access-Control-Allow-Origin",
    "value" : "*"
  } ]
} ]

但这不会对CORS问题有所帮助,因为它需要到位on the returned resource

看起来您可以根据this doc将其放入handlers下的app.yaml中。

handlers:
- url: /.*
  http_headers:
    Access-Control-Allow-Origin: http://mygame.appspot.com

此外,您可以以编程方式添加此内容。正如enable-cors.org上所解释的,这里有一些脚本实现:

对于Google App Engine中基于Python的应用程序,可以使用self.response.headers.add_header()方法,例如:

class CORSEnabledHandler(webapp.RequestHandler):
  def get(self):
    self.response.headers.add_header("Access-Control-Allow-Origin", "*")
    self.response.headers['Content-Type'] = 'text/csv'
    self.response.out.write(self.dump_csv())

对于基于Java的应用程序,请使用resp.addHeader()

public void doGet(HttpServletRequest req, HttpServletResponse resp) {
  resp.addHeader("Access-Control-Allow-Origin", "*");
  resp.addHeader("Content-Type", "text/csv");
  resp.getWriter().append(csvString);
}

对于基于Go的应用程序,请使用w.Header().Add()

func doGet(w http.ResponseWriter, r *http.Request) {
  w.Header().Add("Access-Control-Allow-Origin", "*")
  w.Header().Add("Content-Type", "text/csv")
  fmt.Fprintf(w, csvData)
}
相关问题