POST 请求使用 Firebase 函数表达 API 时出错

Error when POST request to express API with Firebase functions

我已经使用 Functions 和 Hosting 设置了一个 Firebase 项目,并使用 express 构建了一个简单的 API。我正在使用 Firebase 的本地模拟器套件。

我使用 Postman 发出以下请求

POST
http://localhost:5000/api/users
{
    "name": "Kobe Bryant",
    "email": "kobe@gmail.com"
}

我收到了

的回复
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <title>Error</title>
</head>

<body>
    <pre>Cannot POST /dreamkit-client-web/us-central1/api/api/users</pre>
</body>

</html>

状态代码为 404。另外,这就是日志所说的

00:53:17 I [hosting] Rewriting /api/users to http://localhost:5001/dreamkit-client-web/us-central1/api for local Function api
00:53:17 I function[api] Beginning execution of "api"
00:53:17 I hosting 127.0.0.1 - - [21/Nov/2020:05:53:17 +0000] "POST /api/users HTTP/1.1" 404 185 "-" "PostmanRuntime/7.26.8"
00:53:17 I function[api] Finished "api" in ~1s

我认为问题与 api/api/users 有关,但我确保没有重复的 /api,因为我的函数源已经是 /api。我该如何解决这个问题?

firebase.json

{
  "functions": {
    "predeploy": [
      "npm --prefix \"$RESOURCE_DIR\" run lint"
    ],
    "source": "functions"
  },
  "hosting": {
    "predeploy": [
      "npm --prefix client run build"
    ],
    "public": "client/build",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "/api{,/**}",
        "function": "api"
      },
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  },
  "emulators": {
    "functions": {
      "port": 5001
    },
    "firestore": {
      "port": 8080
    },
    "hosting": {
      "port": 5000
    },
    "ui": {
      "enabled": true
    }
  }
}

index.js

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const express = require('express');

//initialize firebase in order to access its services
admin.initializeApp();

const app = express();

// Init Middleware
app.use(express.json({ extended: false }));

// Define Routes
app.use('/users', require('./routes/users'));

app.get('*', (req, res) => {
  res.send('Hello from the API');
});

exports.api = functions.https.onRequest(app);

users.js

const express = require('express');
const router = express.Router();
const admin = require('firebase-admin');
const { check, validationResult } = require('express-validator');

//initialize the database and the collection
const db = admin.firestore();
const usersRef = db.collection('users');

// @route     POST users
// @desc      Register a user
// @access    Public
router.post(
  '/',
  [
    check('name', 'Please add name').not().isEmpty(),
    check('email', 'Please include a valid email').isEmail(),
  ],
  async (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }

    const { name, email } = req.body;

    try {
      let user = await usersRef.where('email', '==', email).get();

      if (user.exists) {
        return res.status(400).json({ msg: 'User already exists' });
      }

      user = { name, email };

      const payload = await usersRef.add(user);
      const id = payload.id;

      res.json({ id });
    } catch (err) {
      console.error(err);
      res.status(500).send('Server Error');
    }
  }
);

module.exports = router;

我认为您可能需要在此处包含“/api”前缀:

app.use('/api/users', require('./routes/users'));