Firebase函数发送后无法设置标头

时间:2019-01-31 16:54:18

标签: javascript node.js reactjs firebase google-cloud-functions

我有一个Firebase函数,无法从我的React.js Web应用程序查询,但是通过邮递员没有问题。

当我尝试通过Web应用程序发出请求时,我的Firebase控制台出现以下错误:

  

错误:发送标头后无法设置。

at validateHeader (_http_outgoing.js:491:11)
at ServerResponse.setHeader (_http_outgoing.js:498:3)
at ServerResponse.header (/worker/node_modules/express/lib/response.js:767:10)
at ServerResponse.json (/worker/node_modules/express/lib/response.js:264:10)
at ServerResponse.send (/worker/node_modules/express/lib/response.js:158:21)
at exports.uploadImage.functions.https.onRequest (/srv/index.js:21:13)
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:229:7)

在Web应用程序上,我收到500错误响应,没有返回任何数据。

这是我发出请求的方式:

const data = {
    image: 'image url here',
    options: {
        tags: 'document,doctor',
    }
};
axios.post('*** FUNCTION URL HERE***/uploadImage', data, {
    headers: {
        'Content-Type': 'application/json',
    },
})

但是,如果我通过 Postman 发出请求,那么我会收到200的期望数据响应。

这是我的 functions / index.js 文件的外观:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const cloudinary = require('cloudinary');
const cors = require('cors')({origin: true});

admin.initializeApp();

exports.uploadImage = functions.https.onRequest(async (req, res) => {
    cors(req, res, () => {});
    cloudinary.config({
        cloud_name: 'config here',
        api_key: 'config here',
        api_secret: 'config here',
    });

    try { 
        const data = Object.apply({folder: 'myortho'}, req.body.options);
        const response = await cloudinary.uploader.upload(req.body.image, data);
        return res.send(response);
    }catch(error) {
        return res.send(500, {message: 'Error uploading image', error});
    }
});

我看到了许多与我遇到的错误有关的问题,但是其中许多问题都涉及到人们的路由问题(这对我来说并不重要,因为这是一个Cloud Function,而不是我自己的Node.js后端服务器)。

这也是我无法理解的错误,因为它是通过Postman而不是通过浏览器成功完成的,所以我真的很困惑。

2 个答案:

答案 0 :(得分:0)

使用cors时,应该将代码放入传递给它的回调函数中。您根本没有使用该回调,而发生的是您的代码正在尝试发送两个响应。应该更像这样:

import tkinter

root = tkinter.Tk()
root.grid_rowconfigure(1, weight=1)
root.grid_columnconfigure(2, weight=1)

a = tkinter.Button(root, text="Reticulate")
b = tkinter.Button(root, text="Frobnicate")

a.grid(row=0, column=0)
b.grid(row=0, column=1)

f = tkinter.Frame(root)
f.grid(row=1, column=2, sticky=tkinter.SE)

g = tkinter.Button(f, text="quit")
g.pack()

root.mainloop()

答案 1 :(得分:0)

要回答有关您的请求为何在Postman中而不是在浏览器中按原样工作的问题,

这是因为Postman是开发工具,因此不依赖CORS。另一方面,浏览器更担心安全性,并依赖CORS。

Google Chrome's extension documentation从技术上更详细地解释了这是为什么的(虽然考虑到扩展,Postman也以这种方式表现):

常规网页可以使用XMLHttpRequest对象从远程服务器发送和接收数据,但是它们受同一原始策略的限制。内容脚本代表已将内容脚本注入到的Web起源发起请求,因此,内容脚本也应遵循相同的起源策略。 (自Chrome 73以来,内容脚本一直受CORB的限制,而自Chrome 83以来,内容脚本一直受CORS的限制。)扩展来源不受限制-在扩展的背景页面或前景选项卡中执行的脚本可以与源之外的远程服务器进行对话,只要该扩展程序请求跨域权限。

还有another thread on Stack Overflow对此进行了进一步的讨论。