簡體   English   中英

'Access-Control-Allow-Origin' CORS 嘗試執行時 firebase function

[英]'Access-Control-Allow-Origin' CORS when trying to execute firebase function

我之前將 firebase 函數與 node.js 一起使用,並且一直運行如下類似的函數。 但是,我現在在我的控制台中突然收到此錯誤:

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);


});

有什么辦法可以讓我的客戶端控制台中顯示的錯誤消失 go 並運行我的雲 function 嗎? 任何幫助將不勝感激

我注意到的第一件事是您正在使用可調用的雲函數,但 Express 應用程序在此處使用 cors 中間件: app.use(cors({origin: true}))並且該應用程序中沒有路由。 我認為您在使用可調用函數時不需要顯式導入 express 和 CORS,因此請嘗試刪除它們。 這里引用,“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 在這里應該不再是問題,但請注意它現在是一個快速應用程序,因此 function 中的參數是Request, Response而不是data, context

此外,我看到您正在從本地主機調用 API,因此使用Firebase Functions Emulator可能是個好主意。 要使用指定使用這樣的模擬器: firebase.functions().useFunctionsEmulator('http://localhost:5001')

我有同樣的問題,這個問題實際上與“用戶權限”有關。 文件說

自 2020 年 1 月 15 日起,默認情況下,所有 HTTP 函數都需要對大多數調用者進行身份驗證。 https://cloud.google.com/functions/docs/securing/managing-access-iam#allowing_unauthenticated_http_function_invocation

解決方案

  • 授予所有用戶訪問allUsers

要公開您的 function,您可以使用 --allow-unauthenticated 標志部署它,或使用控制台將 Cloud Functions Invoker 角色授予 allUsers。 然后在function代碼中處理CORS和鑒權。 https://cloud.google.com/functions/docs/writing/http#limitations

  • 授予對您的 Firebase 應用程序 (Firebase Admin SDK) 的訪問權限
    • 您可以在Service Accounts選項卡下的 Firebase 項目 > 設置中找到它。

對於這兩種解決方案,問題是按照文檔我無法獲得函數列表。 因此,請確保您 go 到Cloud Functions以更改/添加權限

在此處輸入圖像描述

點擊你要的function,然后Add插入一個新的Principal 在此處輸入圖像描述

  • 添加您的新Principal
  • Select Cloud functions invoker角色

在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM