Cloud Functions for Firebase 在 CORS 预检请求上触发功能

Posted

技术标签:

【中文标题】Cloud Functions for Firebase 在 CORS 预检请求上触发功能【英文标题】:Cloud Functions for Firebase triggering function on CORS preflight request 【发布时间】:2018-03-04 08:09:19 【问题描述】:

我有一个云功能,可以验证客户端上表单提交的输入。我正在使用 Cloud Functions for Firebase https triggers 和 cors express middleware。

Firebase 函数

const functions = require('firebase-functions');
const express = require('express');
const cors = require('cors')(origin: true);
const validateImageForm = require('./library/validate-image-form');

exports.apiValidateImageForm = functions.https.onRequest((req, res) => 

  cors(req, res, () => 

    validateImageForm(req.body.formInputs, req.body.imageStatus).then((data) => 
      res.status(200).send(data);
    );

  );

);

客户端调用函数

const validateImageFormFetchOptions = 
   headers: 
     'Accept': 'application/json',
     'Content-Type': 'application/json'
   ,
   method: 'POST',
   body: JSON.stringify(
     formInputs: formInputs
   )


fetch('https://project-url.cloudfunctions.net/apiValidateImageForm', validateImageFormFetchOptions)
 .then(response => response.json())
 .then(serverErrors => console.log(serverErrors));

问题

当我使用提取请求从客户端调用此函数时,我在函数日志中看到两个 apiValidateImageForm 触发器。第一个是状态 204,我假设这来自检查来源的 cors 预检请求。最后的请求是状态 200。我只想要一个函数触发器,当我获取 apiValidateImageForm 函数时。我担心随着时间的推移,输出状态 204 的预检请求会将不必要的函数调用添加到我的项目配额中。

问题

是否可以防止 firebase 在预检请求中触发函数调用?如果没有,那么有没有办法阻止预检请求并成功地将数据传递给函数。

【问题讨论】:

只要您在请求中添加Content-Type': 'application/json' 标头,浏览器就会在尝试来自您的代码的请求之前自动执行 CORS preflight OPTIONS 请求。因此,唯一避免的方法是不将其编码为 application/json 发送,而是将 JSON 作为请求正文中的参数值发送,内容类型为 application/x-www-form-urlencoded;也就是说,就像json=[your JSON data here] 这样的名称+值对。请参阅***.com/a/43881141/441757 答案的如何避免 CORS 预检部分 【参考方案1】:

要修复重复的请求 200 和 204,然后更改客户端获取请求的方式。 @sideshowbarker 是对的。浏览器会自动执行 CORS 预检 OPTIONS 请求,因此这在 Cloud Functions for Firebase 中不是问题。 This answer 很有帮助。

为了修复预检,我将代码更改为以下内容:

客户端调用函数

完全从 fetch 选项中删除了标头,而不是将内容类型设置为 application/json。默认情况下,获取请求的内容类型是 application/x-www-form-urlencoded;字符集=UTF-8。

const validateImageFormFetchOptions = 
  method: 'POST',
  body: JSON.stringify(
   formInputs: formInputs
  )


fetch('https://project-url.cloudfunctions.net/apiValidateImageForm', validateImageFormFetchOptions)
  .then(response => response.json())
  .then(serverErrors => console.log(serverErrors));

Firebase 函数

显式解析请求正文,因为它现在作为文本字符串接收。

const functions = require('firebase-functions');
const express = require('express');
const cors = require('cors')(origin: true);
const validateImageForm = require('./library/validate-image-form');

exports.apiValidateImageForm = functions.https.onRequest((req, res) => 
  cors(req, res, () => 
    const body = JSON.parse(req.body);
    validateImageForm(body.formInputs, body.imageStatus).then((data) => 
      res.status(200).send(data);
    );
  );
);

【讨论】:

以上是关于Cloud Functions for Firebase 在 CORS 预检请求上触发功能的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Firebase Cloud Functions 测试中模拟 FCM admin.messaging().sendToDevice() 的实现

如何使用 Google Python Client for Cloud Functions 获取 Google Cloud Functions 列表?

Cloud Functions for Firebase 超时

Cloud Functions for Firebase onWrite 超时

在 Cloud Functions for Firebase 中访问 db 数据

Cloud Functions for Firebase 组织