I have set up a Firebase project with Functions and Hosting and built a simple API with express. I am using Firebase's local emulator suite.
I use Postman to make the following request
POST
http://localhost:5000/api/users
{
"name": "Kobe Bryant",
"email": "kobe@gmail.com"
}
and I receive a response of
<!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>
with status code of 404. Also, this is what the logs say
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
I think the issue has to do with the api/api/users
, but I made sure not to have a duplicate /api
because my function's source is already /api
. How can I fix this issue?
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;
I think you might have to include the "/api" prefix here:
app.use('/api/users', require('./routes/users'));