从域调用时 Firebase 函数不执行
Firebase function doesn't execute when called from domain
我有一个带有 Firebase 后端的 React 网络应用程序,该后端是使用 NodeJS 创建的。我使用 Firebase 函数。当我从本地主机或 Postman 调用它们时,我的 Firebase 函数就会执行。但是当我从我的域 (moonio.io) 调用函数时,它们不会被执行,唯一发生的事情就是我取回了我的 index.js 文件。因此,我怀疑我的问题是由 firebase.json 文件(api 地址“https://europe-west3-cryptocurrency-tracker-moonio.cloudfunctions.net/api" 被重写为 "/index.html")?
firebase.json
{
"hosting": [
{
"target": "app",
"public": "app/build",
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
],
"functions": {
"source": "functions"
}
}
package.json 对于 Firebase 函数
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"lint": "eslint .",
"serve": "firebase emulators:start --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "12"
},
"main": "index.js",
"dependencies": {
"axios": "^0.21.1",
"express": "^4.17.1",
"firebase": "^8.1.1",
"firebase-admin": "^9.2.0",
"firebase-functions": "^3.13.1",
"google-auth-library": "^6.1.3",
"react-redux": "^7.2.2",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0"
},
"devDependencies": {
"eslint": "^5.12.0",
"eslint-plugin-promise": "^4.0.1",
"firebase-functions-test": "^0.2.0"
},
"private": true
}
package.json 对于我的 React 应用
{
"name": "cryptotracker",
"version": "0.1.0",
"private": true,
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.32",
"@fortawesome/free-solid-svg-icons": "^5.15.1",
"@fortawesome/react-fontawesome": "^0.1.13",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "^4.0.0-alpha.57",
"axios": "^0.20.0",
"chart.js": "^2.9.4",
"chartjs": "^0.3.24",
"colorthief": "^2.3.2",
"cra-template": "1.0.3",
"firebase": "^8.2.3",
"history": "^5.0.0",
"install": "^0.13.0",
"jwt-decode": "^3.1.2",
"lodash": "^4.17.20",
"npm": "^6.14.10",
"prop-types": "^15.7.2",
"react": "^16.13.1",
"react-chartjs-2": "^2.11.1",
"react-dom": "^16.13.1",
"react-google-login": "^5.2.2",
"react-hook-form": "^6.9.1",
"react-loading-skeleton": "^2.1.1",
"react-redux": "^7.2.2",
"react-router-dom": "^5.2.0",
"react-scripts": "3.4.3",
"react-virtualized-select": "^3.1.3",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0",
"retry-axios": "^2.3.0",
"styled-components": "^5.2.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"proxy": "https://europe-west3-cryptocurrency-tracker-moonio.cloudfunctions.net/api"
}
几个小时后,我终于找到了问题所在。
- 需要对 firebase.json 文件添加另一个重写以处理 api。根据单页应用程序的要求,对 api 的所有请求必须转到 Firebase 函数中相应的 api 函数,所有其他请求将转到 index.html。因此,firebase.json 的重写部分需要如下所示:
"rewrites": [
{
"source": "/api/**",
"function": "api"
},
{
"source": "!/api/**",
"destination": "/index.html"
}
]
- package.json 文件中的代理仅用于开发目的。它不会在生产中工作。只要您设置了自定义域,Firebase 就会自动将此域 link 添加到您的函数中。因此,由于我的自定义域是 moonio.io,因此可以通过向 moonio.io/api/
发送请求来执行 Firebase 函数。为了使对这些端点的请求正常工作,重要的是您在 node.js 中的函数设置中的请求 url 中也包含“/api”。我正在使用 express,所以我的 index.js 文件的示例函数如下所示(注意“/api”是 url 的一部分):
const app = require("express")();
const functions = require("firebase-functions");
app.post("/api/signin", signIn);
exports.api = functions.region("us-central1").https.onRequest(app);
- 此外,当从前端向 Firebase 函数发出请求时,有必要在 url 的开头包含“/api”,正如我在以下示例函数中所做的那样:
axios.post("/api/signin", userData)
- Firebase 函数仅适用于 us-central1 中的 Firebase 托管。如果您使用其他位置,请根据我在第 2 部分中的代码示例进行更改。
我有一个带有 Firebase 后端的 React 网络应用程序,该后端是使用 NodeJS 创建的。我使用 Firebase 函数。当我从本地主机或 Postman 调用它们时,我的 Firebase 函数就会执行。但是当我从我的域 (moonio.io) 调用函数时,它们不会被执行,唯一发生的事情就是我取回了我的 index.js 文件。因此,我怀疑我的问题是由 firebase.json 文件(api 地址“https://europe-west3-cryptocurrency-tracker-moonio.cloudfunctions.net/api" 被重写为 "/index.html")?
firebase.json
{
"hosting": [
{
"target": "app",
"public": "app/build",
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
],
"functions": {
"source": "functions"
}
}
package.json 对于 Firebase 函数
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"lint": "eslint .",
"serve": "firebase emulators:start --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "12"
},
"main": "index.js",
"dependencies": {
"axios": "^0.21.1",
"express": "^4.17.1",
"firebase": "^8.1.1",
"firebase-admin": "^9.2.0",
"firebase-functions": "^3.13.1",
"google-auth-library": "^6.1.3",
"react-redux": "^7.2.2",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0"
},
"devDependencies": {
"eslint": "^5.12.0",
"eslint-plugin-promise": "^4.0.1",
"firebase-functions-test": "^0.2.0"
},
"private": true
}
package.json 对于我的 React 应用
{
"name": "cryptotracker",
"version": "0.1.0",
"private": true,
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.32",
"@fortawesome/free-solid-svg-icons": "^5.15.1",
"@fortawesome/react-fontawesome": "^0.1.13",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "^4.0.0-alpha.57",
"axios": "^0.20.0",
"chart.js": "^2.9.4",
"chartjs": "^0.3.24",
"colorthief": "^2.3.2",
"cra-template": "1.0.3",
"firebase": "^8.2.3",
"history": "^5.0.0",
"install": "^0.13.0",
"jwt-decode": "^3.1.2",
"lodash": "^4.17.20",
"npm": "^6.14.10",
"prop-types": "^15.7.2",
"react": "^16.13.1",
"react-chartjs-2": "^2.11.1",
"react-dom": "^16.13.1",
"react-google-login": "^5.2.2",
"react-hook-form": "^6.9.1",
"react-loading-skeleton": "^2.1.1",
"react-redux": "^7.2.2",
"react-router-dom": "^5.2.0",
"react-scripts": "3.4.3",
"react-virtualized-select": "^3.1.3",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0",
"retry-axios": "^2.3.0",
"styled-components": "^5.2.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"proxy": "https://europe-west3-cryptocurrency-tracker-moonio.cloudfunctions.net/api"
}
几个小时后,我终于找到了问题所在。
- 需要对 firebase.json 文件添加另一个重写以处理 api。根据单页应用程序的要求,对 api 的所有请求必须转到 Firebase 函数中相应的 api 函数,所有其他请求将转到 index.html。因此,firebase.json 的重写部分需要如下所示:
"rewrites": [
{
"source": "/api/**",
"function": "api"
},
{
"source": "!/api/**",
"destination": "/index.html"
}
]
- package.json 文件中的代理仅用于开发目的。它不会在生产中工作。只要您设置了自定义域,Firebase 就会自动将此域 link 添加到您的函数中。因此,由于我的自定义域是 moonio.io,因此可以通过向 moonio.io/api/
发送请求来执行 Firebase 函数。为了使对这些端点的请求正常工作,重要的是您在 node.js 中的函数设置中的请求 url 中也包含“/api”。我正在使用 express,所以我的 index.js 文件的示例函数如下所示(注意“/api”是 url 的一部分):
const app = require("express")();
const functions = require("firebase-functions");
app.post("/api/signin", signIn);
exports.api = functions.region("us-central1").https.onRequest(app);
- 此外,当从前端向 Firebase 函数发出请求时,有必要在 url 的开头包含“/api”,正如我在以下示例函数中所做的那样:
axios.post("/api/signin", userData)
- Firebase 函数仅适用于 us-central1 中的 Firebase 托管。如果您使用其他位置,请根据我在第 2 部分中的代码示例进行更改。