尝试执行 firebase 功能时出现“Access-Control-Allow-Origin”CORS

问题描述

我之前在 node js 中使用过 firebase 函数,并且一直运行类似的函数,如下所示。但是,我现在在控制台中突然收到此错误

Access to fetch at 'https://us-central1-myapp.cloudfunctions.net/test2' from origin 'http://localhost:8383' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs,set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

POST https://us-central1-myapp.cloudfunctions.net/test2 net::ERR_Failed

这是我的代码,我不知道我做错了什么:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const nodemailer = require('nodemailer');
const {Storage} = require('@google-cloud/storage');
var PizZip = require('pizzip');
var Docxtemplater = require('docxtemplater');
admin.initializeApp();
const BUCKET = 'gs://myapp.appspot.com';
const cors = require('cors');
const https = require('https');
const express = require('express');
const app = express();
app.use(cors({origin: true}));

    const storage = new Storage({
    projectId: 'myapp' });
    
    
    // The error object contains additional information when logged with JSON.stringify (it contains a properties object containing all suberrors).
function replaceErrors(key,value) {
    if (value instanceof Error) {
        return Object.getownPropertyNames(value).reduce(function(error,key) {
            error[key] = value[key];
            return error;
        },{});
    }
    return value;
}

function errorHandler(error) {
    console.log(JSON.stringify({error: error},replaceErrors));

    if (error.properties && error.properties.errors instanceof Array) {
        const errorMessages = error.properties.errors.map(function (error) {
            return error.properties.explanation;
        }).join("\n");
        console.log('errorMessages',errorMessages);
        // errorMessages is a humanly readable message looking like this :
        // 'The tag beginning with "foobar" is unopened'
    }
    throw error;
}

function readStreamToBuffer(stream) {
    return new Promise((resolve,reject) => {
        const chunkArray = [];
        
        stream
        .on('data',(chunk) => chunkArray.push(chunk))
        .on('error',(err) => {
            chunkArray = [];
            reject(err);
        })
        .on('end',() => {
            const buffer = Buffer.concat(chunkArray);
            chunkArray = [];
            resolve(buffer);
        });
    });
}


exports.test2 = functions.https.onCall(async(data,context) => {
 const file_name = 'tag-example.docx';
 const storageRef = storage.bucket(BUCKET).file(file_name);
  const buffer = await readStreamToBuffer(storageRef.createReadStream());
  const zip = new PizZip(buffer);

  let doc;
  try {
      doc = new Docxtemplater(zip);
  } catch(error) {
      // Catch compilation errors (errors caused by the compilation of the template : misplaced tags)
      errorHandler(error);
  }

  doc.setData({
      first_name: 'Fred',last_name: 'Flinstone',phone: '0652455478',description: 'Web app'
  });
          
  try {
      doc.render();
  } catch (error) {
      errorHandler(error);
  }

  const contentBuffer = doc.getZip()
      .generate({type: 'nodebuffer'});
  
  console.log(doc);
  const targetStorageRef = storage.bucket(BUCKET).file("compiled.docx");
  await targetStorageRef.put(contentBuffer);


});

有没有办法让我的客户端控制台中显示错误消失并且我的云功能运行?任何帮助将不胜感激

解决方法

我注意到的第一件事是您正在使用可调用的云函数,但 express 应用程序在此处使用 cors 中间件:app.use(cors({origin: true})) 并且该应用程序中没有路由。我认为在使用可调用函数时不需要显式导入 express 和 CORS,因此请尝试删除它们。引自 here,“CORS 应由 onCall 处理程序自动处理”。

如果你想像这样使用 Express 和 CORS 中间件,你应该尝试如下所示的 onRequest 函数:

const express = require('express');
const cors = require('cors');

const app = express();

// Automatically allow cross-origin requests
app.use(cors({ origin: true }));

// build multiple CRUD interfaces:
app.get('/test2',(req,res) => {
  //Handle your test2 methods here
  return res.send('your response')
});


// Expose Express API as a single Cloud Function:
exports.api = functions.https.onRequest(app);

现在在这种情况下,您编写的 CORS 中间件将运行。您函数的 URL 可能类似于 - https://us-central1-myapp.cloudfunctions.net/api 然后要使用 /test2 路由,它变为 https://us-central1-myapp.cloudfunctions.net/api/test2。 CORS 在这里应该不再是问题,但请注意它现在是一个快速应用程序,因此函数中的参数是 Request,Response 而不是 data,context

此外,我看到您正在从本地主机调用 API,因此使用 Firebase Functions Emulator 可能是一个好主意。要使用指定来使用模拟器,如下所示:firebase.functions().useFunctionsEmulator('http://localhost:5001')