Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/469.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为Firebase启用云中CORS功能_Javascript_Firebase_Google Cloud Platform_Cors_Google Cloud Functions - Fatal编程技术网

Javascript 为Firebase启用云中CORS功能

Javascript 为Firebase启用云中CORS功能,javascript,firebase,google-cloud-platform,cors,google-cloud-functions,Javascript,Firebase,Google Cloud Platform,Cors,Google Cloud Functions,我目前正在学习如何为Firebase使用新的云函数,我遇到的问题是无法访问通过AJAX请求编写的函数。我得到了“No‘Access Control Allow Origin’”错误。下面是我编写的函数示例: exports.test = functions.https.onRequest((request, response) => { response.status(500).send({test: 'Testing functions'}); }) 该函数位于以下url中: F

我目前正在学习如何为Firebase使用新的云函数,我遇到的问题是无法访问通过AJAX请求编写的函数。我得到了“No‘Access Control Allow Origin’”错误。下面是我编写的函数示例:

exports.test = functions.https.onRequest((request, response) => {
  response.status(500).send({test: 'Testing functions'});
})
该函数位于以下url中:

Firebase docs建议在函数中添加CORS中间件,我已经尝试过了,但它对我不起作用:

我就是这样做的:

var cors = require('cors');    

exports.test = functions.https.onRequest((request, response) => {
   cors(request, response, () => {
     response.status(500).send({test: 'Testing functions'});
   })
})
我做错了什么?我将非常感谢您的帮助

更新:

奥巴马的回答起了作用。添加({origin:true})修复了这个问题,我还必须将
response.status(500)
更改为
response.status(200)
,这是我一开始完全没有注意到的。

Firebase团队提供了两个演示CORS使用的示例:

第二个示例使用与您当前使用的cors不同的工作方式

考虑这样导入,如示例所示:

const cors = require('cors')({origin: true});
函数的一般形式如下:

exports.fn = functions.https.onRequest((req, res) => {
    cors(req, res, () => {
        // your function body here - use the provided req and res from cors
    })
});
// Init the firebase SDK first    
const functions = firebase.functions();
const addMessage = functions.httpsCallable(`newRequest`);
import * as cors from 'cors';
const corsHandler = cors({origin: true});

export const pingFunctionWithCorsAllowed = functions.https.onRequest((request, response) => {
  corsHandler(request, response, () => {
    response.send(`Ping from Firebase (with CORS handling)! ${new Date().toISOString()}`);
  });
});

我刚刚发表了一篇关于这方面的小文章:

一般来说,您应该使用Express,这需要稍加修改以满足GCF/Firebase函数中的要求


希望有帮助

另外一条信息,只是为了那些在一段时间后在谷歌上搜索的人: 如果您使用的是firebase托管,您还可以设置重写,以便(firebase_hosting_host)/api/myfunction等url重定向到(firebase_cloudfunctions_host)/doStuff函数。这样,因为重定向是透明的,并且是服务器端的,所以您不必处理COR

您可以通过firebase.json中的“重写”部分进行设置:

"rewrites": [
        { "source": "/api/myFunction", "function": "doStuff" }
]

对于@Andreys对他自己问题的回答,我还有一点补充

似乎您不必在
cors(req,res,cb)
函数中调用回调函数,因此您只需调用函数顶部的cors模块,而无需将所有代码嵌入回调函数中。如果您想在以后实现cors,这会更快

exports.exampleFunction = functions.https.onRequest((request, response) => {
    cors(request, response, () => {});
    return response.send("Hello from Firebase!");
});
别忘了初始化cors,如开场白中所述:

const cors=require('cors')({origin:true})


更新:任何需要时间的响应函数都可能在该实现中出现CORS错误,因为它没有相应的异步/等待。不要使用返回静态数据的快速原型化端点之外的端点。

对于试图在Typescript中执行此操作的任何人,以下是代码:

import * as cors from 'cors';
const corsHandler = cors({origin: true});

export const exampleFunction= functions.https.onRequest(async (request, response) => {
       corsHandler(request, response, () => {});
       //Your code here
});

没有CORS解决方案适合我。。。直到现在

不确定是否有其他人遇到了我遇到的相同问题,但我设置了CORS,就像我发现的示例中的5种不同方式一样,但似乎没有任何效果。我用Plunker设置了一个最小的例子,看看它是否真的是一个bug,但是这个例子运行得很好。我决定检查firebase函数日志(在firebase控制台中找到),看看这是否能告诉我什么我的节点服务器代码中有几个错误,与CORS无关,当我调试时,发布了我的CORS错误消息。我不知道为什么与CORS无关的代码错误会返回CORS错误响应,但它让我在错误的兔子洞里呆了好几个小时


tl;灾难恢复-如果没有CORS解决方案工作,请检查firebase功能日志,并调试任何错误。您可以在云功能中设置CORS,如下所示

response.set('Access-Control-Allow-Origin','*')


无需导入
cors

,因为我在将
app
传递到
onRequest
时遇到了同样的问题。我意识到问题是firebase函数的请求url上有一个尾随斜杠。Express正在查找
'/'
,但我在函数
[project id].cloudfunctions.net/[function name]
上没有尾随斜杠。CORS错误为假阴性。当我添加尾随斜杠时,我得到了预期的响应

如果您不使用Express或只是想使用CORS。下面的代码将有助于解决此问题

const cors = require('cors')({ origin: true, });   
exports.yourfunction = functions.https.onRequest((request, response) => {  
   return cors(request, response, () => {  
        // *Your code*
    });
});

只有这种方式对我有效,因为我在请求中有授权:

exports.hello = functions.https.onRequest((request, response) => {
response.set('Access-Control-Allow-Origin', '*');
response.set('Access-Control-Allow-Credentials', 'true'); // vital
if (request.method === 'OPTIONS') {
    // Send response to OPTIONS requests
    response.set('Access-Control-Allow-Methods', 'GET');
    response.set('Access-Control-Allow-Headers', 'Content-Type');
    response.set('Access-Control-Max-Age', '3600');
    response.status(204).send('');
} else {
    const params = request.body;
    const html = 'some html';
    response.send(html)
} )};
这可能会有帮助。 我使用express(自定义URL)创建了firebase HTTP云函数

请确保已添加“重写”部分

"rewrites": [
      {
        "source": "/api/v1/**",
        "function": "functionName"
      }
]

如果有像我这样的人:如果你想从云函数本身所在的同一个项目调用云函数,你可以初始化firebase sdk并使用onCall方法。它将为您处理一切:

exports.newRequest = functions.https.onCall((data, context) => {
    console.log(`This is the received data: ${data}.`);
    return data;
})
按如下方式调用此函数:

exports.fn = functions.https.onRequest((req, res) => {
    cors(req, res, () => {
        // your function body here - use the provided req and res from cors
    })
});
// Init the firebase SDK first    
const functions = firebase.functions();
const addMessage = functions.httpsCallable(`newRequest`);
import * as cors from 'cors';
const corsHandler = cors({origin: true});

export const pingFunctionWithCorsAllowed = functions.https.onRequest((request, response) => {
  corsHandler(request, response, () => {
    response.send(`Ping from Firebase (with CORS handling)! ${new Date().toISOString()}`);
  });
});
Firebase文档:

如果无法初始化SDK,以下是其他建议的要点:

  • 如果在默认位置使用firebase主机和主机,请选择“重写”:
  • 或者像krishnazden建议的那样使用COR:

如果您在本地测试firebase应用程序,则需要将函数指向
localhost
而不是云。默认情况下,
firebase-serve
firebase-emulators:start
在web应用程序上使用时,将函数指向服务器而不是本地主机

在firebase初始化脚本之后的html标头中添加以下脚本:

 <script>
      firebase.functions().useFunctionsEmulator('http://localhost:5001')
 </script> 

firebase.functions().useFunctionsEmulator('http://localhost:5001')
确保在将代码部署到服务器时删除此代码段


如果您不/不能使用cors插件,那么在handler函数中首先调用
setCorsHeaders()
函数也可以

回复时也使用respondSuccess/Error函数

const ALLOWED_ORIGINS = ["http://localhost:9090", "https://sub.example.com", "https://example.com"]


// Set CORS headers for preflight requests
function setCorsHeaders (req, res) {
  var originUrl = "http://localhost:9090"


  if(ALLOWED_ORIGINS.includes(req.headers.origin)){
    originUrl = req.headers.origin
  }

  res.set('Access-Control-Allow-Origin', originUrl);
  res.set('Access-Control-Allow-Credentials', 'true');

  if (req.method === 'OPTIONS') {
    // Send response to OPTIONS requests
    res.set('Access-Control-Allow-Methods', 'GET,POST','PUT','DELETE');
    res.set('Access-Control-Allow-Headers', 'Bearer, Content-Type');
    res.set('Access-Control-Max-Age', '3600');
    res.status(204).send('');
  }
}

function respondError (message, error, code, res) {
  var response = {
    message: message,
    error: error
  }
  res.status(code).end(JSON.stringify(response));
}


function respondSuccess (result, res) {
  var response = {
    message: "OK",
    result: result
  }
  res.status(200).end(JSON.stringify(response));
}

在我的例子中,错误是由云函数调用程序限制访问引起的。请将诱惑者添加到云函数调用器。请接电话。请参阅以了解更多信息,通过
更改
true
“*”
为我完成了这项任务,因此它看起来是这样的:

const cors = require('cors')({ origin: "*" })
我尝试这种方法是因为
const corsHandler = (request, response, handler) => {
    cors({ origin: true })(request, response, async () => {
        try {
            await handler();
        }
        catch (e) {
            functions.logger.error('Error: ' + e);
            response.statusCode = 500;
            response.send({
                'status': 'ERROR' //Optional: customize your error message here
            });
        }
    });
};
exports.helloWorld = functions.https.onRequest((request, response) => {
    corsHandler(request, response, () => {
        functions.logger.info("Hello logs!");
        response.send({
            "data": "Hello from Firebase!"
        });
    });
});
import * as express from "express";
import * as cors from "cors";


const api = express();
api.use(cors({ origin: true }));
api.get("/url", function);
//Express
const express = require('express');
const app = express();

const cors = require('cors');
app.use(cors({
  origin: 'https://pericope.app'
}));
const applyMiddleware = handler => (req, res) => {
  return cors(req, res, () => {
    return handler(req, res)
  })
}
exports.handler = functions.https.onRequest(applyMiddleware(handler))
https://xxxx-default-rtdb.firebaseio.com/myendpoint
https://xxxx-default-rtdb.firebaseio.com/myendpoint.json
app.get('/create-customer', (req, res) => {
  return cors()(req, res, () => {
    ... your code ...
firebase.functions().httpsCallable('makeSureThisStringIsCorrect');
import * as cors from 'cors';
const corsHandler = cors({origin: true});

export const pingFunctionWithCorsAllowed = functions.https.onRequest((request, response) => {
  corsHandler(request, response, () => {
    response.send(`Ping from Firebase (with CORS handling)! ${new Date().toISOString()}`);
  });
});