Cant connect to MongoDB in Firebase Functions - javascript

I am using Firebase Functions as the host for my MERN web app backend.
When I connect to MongoDB locally, it works and can run operations with the database. However, when I deployed to firebase functions, it failed to even connect to the database.
Code:
index.js
const functions = require('firebase-functions');
const server = require('./server.js');
exports.api = functions.runWith({ memory: "2GB", timeoutSeconds: 120 }).https.onRequest(server);
Part of server.js
const express = require("express");
const dotenv = require("dotenv");
const colors = require("colors");
const morgan = require("morgan");
const path = require("path");
const cors = require("cors");
const bodyParser = require("body-parser");
const routes = require("./routes/routes.js");
const mongooseMethods = require("./database.js");
dotenv.config({ path: "./config/config.env" });
mongooseMethods.connectDB(process.env.MONGO_URL);
const PORT = process.env.PORT || 8080;
// set up app
const app = express();
app.listen(PORT, console.log(`Server running in ${process.env.NODE_ENV} mode on port ${PORT}`.yellow.bold));
app.use(cors({ origin: true }));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(morgan("dev"));
app.use("/api", routes); // /api routes
module.exports = app;
routes.js
const express = require("express");
const app = express.Router();
const testingApi = require('../controller/testing.js');
const authApi = require('../controller/auth.js');
// testing
app.get('/testing', testingApi.testing);
// user authentication
app.post('/user/register', authApi.createUser);
module.exports = app;
api/testing/ also works
database.js
const mongoose = require("mongoose");
const mongooseMethods = {
connectDB: async (url) => {
try {
console.log("Connecting to MongoDB")
const connection = await mongoose.connect(url, { useNewUrlParser: true, useUnifiedTopology: true });
console.log(`MongoDB Connected: ${connection.connection.host}`.cyan.bold);
return connection;
} catch (error) {
console.log(`Error: ${error.message}, Exiting`.red.bold);
process.exit(1);
}
}
}
module.exports = mongooseMethods;
auth.js
const User = require('../model/user.model.js');
const bcrypt = require("bcryptjs");
let authenticationApi = {
createUser: async (req, res) => {
try {
console.log("Creating");
let newUser = new User({
...req.body
})
let result = await newUser.save();
return res.status(200).json({ result: result });
} catch (error) {
return res.status(400);
}
}
}
module.exports = authenticationApi;
The error I received when sending request to firebase is
2020-02-27T02:34:46.334044912Z D api: Function execution took 30970 ms, finished with status: 'connection error'
Yet it runs perfectly fine in local. I also don't see the console log "connected to MongoDB". I'm guessing that the problem occurs in database.js that it failed to connect to mongo at the first place yet I don't know how to solve.
I am using the paid plan in Firebase and the outbound networking should be fine.
p.s. this is my first time posting here. thanks for your time and I apologize in advance if i'm breaking any rules.

Listening on a port is not a valid operation in cloud functions:
app.listen(PORT, console.log(`Server running in ${process.env.NODE_ENV} mode on port ${PORT}`.yellow.bold));
Cloud Functions listens for you, using the URL that it was assigned, then delivers the request to your code. When you pass your express app to onRequest(), that's all wired up for you.
I suggest starting with a stripped down, simplified version of an app just to gain experience about how things work, then add in more as you get comfortable.

The reason for this to happen is that the architecture of Firebase Functions is not an actual server, but a serverless lambda-like endpoint. Since it cannot establish a lasting connection to the database, that it has to make a connection every time it received a request, the database sees this as spam and shut down further connection request from Firebase.
Therefore, you simply cannot host a complete express app with intended lasting connection in Firebase Functions.
More on that in this article

Related

Error: Cannot find module './keys_dev' Require stack

I have cloned a GitHub repo for reference. But i don't know what this .keys_dev refers to. Everything seems fine to me. But it is returning me error. Everything is in its place as expected. I hope anyone can help me. It requires stack that is unknown to me. It is requiring api that is already defined. I need to understand can anyone help?
const express = require("express");
const bodyPaser = require('body-parser');
const mongoose = require('mongoose');
const passport = require('passport');
const path = require('path');
const cors = require('cors');
const users = require('./routes/api/users');
const level = require('./routes/api/levels');
const employee = require('./routes/api/employees');
const exception = require('./routes/api/exception');
const payslip = require('./routes/api/payslip');
const dashboard = require('./routes/api/dashboard');
const individualcost = require('./routes/api/individualcost');
const oneoffpayment = require('./routes/api/oneoffpayment');
const record = require('./routes/api/record');
const app = express();
//Body parser middleware
app.use(bodyPaser.urlencoded({ extended: false }));
app.use(bodyPaser.json());
app.use(cors())
//Db
const db = require("./config/keys").mongoURI;
//MongoDB connection
mongoose
.connect(
db,
{ useNewUrlParser: true }
)
.then(() => console.log("MongoDB connected"))
.catch(err => console.log(err));
//Passport Middleware
app.use(passport.initialize());
//Passport config
require('./config/passport')(passport);
//Use routes
app.use('/api/users', users);
app.use('/api/level', level);
app.use('/api/employee', employee);
app.use('/api/exception', exception);
app.use('/api/payslip', payslip);
app.use('/api/dashboard', dashboard);
app.use('/api/individualcost', individualcost);
app.use('/api/oneoffpayment', oneoffpayment);
app.use('/api/record', record);
// Server static assets if in production
if (process.env.NODE_ENV === 'production') {
// Set static folder
app.use(express.static('client/build'));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
}
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`App is running on port ${PORT}`));
const db = require("./config/keys").mongoURI;
This require is fetching application configurations from the local filesystem, in this case the db URI. Perhaps the author of the repo forgot to mention that detail? It's very likely that if you want to use a MongoDB you'll have to setup your own local or cloud database and create a file under config/keys that contains a mongoURI. This should look similar to this:
// this is the contents of ./config/keys
export default {
mongoURI: "mongodb+srv://project:your-mongo-uri-here",
};
If you're looking to start a mongo cluster on the cloud, I've been using cloud.mongodb for a small pet project, works like a charm and it has a free plan tier.
You can also run mongo locally and just point the mongoURI to your local mongo instance.

Error 404 when I make a request to the API in http://localhost:5000

I am carrying out a project in MERN Stack and when making the request to the Api it returns a 404 error.
I do not know what it can be since the server works correctly, the strange thing is that sometimes when lifting it if it works without touching anything but other times it does not and I do not know how to solve it.
Another curious fact is that when raising the servers of other projects that were working correctly, I get the same error.
Error on Google Chrome DevTools:
image of error in Google Chrome
Server:
const express = require('express')
const cors = require('cors')
const mongoose = require('mongoose')
require('dotenv').config()
const app = express()
const port = process.env.PORT || 5000
app.use(cors())
app.use(express.json())
mongoose
.connect('mongodb://127.0.0.1:27017/justwatch',{useNewUrlParser:true})
.catch(e=>console.log('Connection error:',e.message))
const connection = mongoose.connection
connection.once('open',()=>{
console.log('MongoDB MOVIES database connection successfully');
})
const movieRouter = require('./routes/movie')
const seriesRouter = require('./routes/serie')
app.use('/movies',movieRouter)
app.use('/series',seriesRouter)
app.listen(port,()=>{console.log(`Server is running on port: ${port}`)})
Router:
const router = require('express').Router()
let Movie = require('../models/movie.model')
router.route('/movies').get((req,res)=>{
let limite = parseInt(req.params.number)
Movie.find().limit(12)
.then(movies=>res.json(movies))
.catch(err=>res.status(400).json('Error: '+err))
})
router.route('/').get((req,res)=>{
Movie.find().limit(12)
.then(movies=>res.json(movies))
.catch(err=>res.status(400).json('Error: '+err))
})
module.exports = router
React requests:
const getMovies = async() => {
await axios.get('localhost:5000/movies/')
.then(res=>{ console.log(res.data); setMovies(res.data) })
.catch(err=>console.log(err)) console.log(movies) }

MongooseServerSelectionError: connect ECONNREFUSED 127.0.0.1:27017

I used mongoose to connect my database to my app.
I got this unexpected error.
My app.js look like this
const express = require('express');
const mongoose = require('mongoose');
const authRoutes = require('./routes/authRoutes');
const cookieParser = require('cookie-parser');
const { requireAuth, checkUser } = require('./middleware/authMiddleware');
const run = require('./admin/connection');
const app = express();
// middleware
app.use(express.static('public'));
app.use(express.json());
app.use(cookieParser());
const {default : AdminBro} = require('admin-bro');
const buildAdminRouter = require('./admin/admin.router');
const options = require('./admin/admin.options');
const port = 3000;
const url = 'mongodb://localhost:27017/dbName';
let mongooseDb;
const databaseConnect = async () => {
mongooseDb = await mongoose.connect(url, { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex:true })
.then((result) => app.listen(3000))
.catch((err) => console.log(err));
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
console.log("we are connected to database");
});
const admin = new AdminBro(options)
const router = buildAdminRouter(admin);
app.use(admin.options.rootPath, router);
};
databaseConnect();
I already installed mongodb database.
I already find similar question in stackoverflow but that answers didn't resolve my issue. Any help will be appreciated. Thanks
If It's MAC OS, run following command and try again:
brew services restart mongodb-community
the commands that follow will be the following:
Stopping mongodb-community... (might take a while)
==> Successfully stopped mongodb-community (label: homebrew.mxcl.mongodb-community)
==> Successfully started mongodb-community (label: homebrew.mxcl.mongodb-community)
I faced a similar problem.Give a try to this one:
Open your C drive.
Make a folder named 'data'.
Make another folder inside this data folder name 'db'.
You can see in the documentation that By default MongoDB try to search these directories, We have to create these manually
This error occurs when you run your node app without a server.
Fix is to run your mongodb server first then your app.

Is there a way to have a GET request with setInterval on the backend without the help of the client side/frontend?

I have this GET request that fetches data from a third party api. I want to check if there is new data every 5-10 minutes or so. Right now i have this setup on my backend.
exports.get_alerts = async (req, res) => {
const alertsUrl = `https://www.g2smart.com/g2smart/api/alert?cpo=${req.params.cpo}&status=Opened&limit=10&page=1`;
const axios = require("axios");
const auth = await refreshToken;
const currTime = moment().subtract(1, "days").format("X");
const newAlertsData = [];
const availableUsers = await axios.get(
"http://localhost:5000/api/schedule/available"
) ....
and on the front end i have this code to send a get request to my alerts api endpoint.
getAlerts = async () => {
axios
.get("/api/alerts/total_fr_hpc")
.then((response) => console.log(response.data))
.catch((err) => console.log(err));
};
timer = (time) => {
const date = new Date(time);
return `${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`;
};
componentDidMount() {
this.alertsInterval = setInterval(this.getAlerts, 900000);
}
componentWillUnmount() {
clearInterval(this.alertsInterval);
My question is can i have all this done on the backend only? I read a bit about websockets but that seems to be only for a continuous 2way connection between the backend and frontend.
I'd like to have something like that towards my third party apis on the node/express server, either fetching data at a set interval or a continuous connection checking for new data without having to make GET requests from my frontend. I want to be able to get new Data and store it into MongoDB even when there is nobody logged in to the client side.
I want that the data the users get is always up to date without having at least one person logged in to trigger the GET requests.
This is how my node/express server is currently setup
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const passport = require("passport");
const cors = require("cors");
const path = require("path");
const indexRouter = require("./routes/index");
const apiRouter = require("./routes/api"); //Import routes for "api" area of site
const app = express();
// CORS Middleware
app.use(cors());
app.options("*", cors());
// Bodyparser middleware
app.use(
bodyParser.urlencoded({
extended: false,
})
);
app.use(bodyParser.json());
// DB Config
const db = require("./config/keys").mongoURI;
// Connect to MongoDB
mongoose
.connect(db, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
})
.then(() => console.log("MongoDB successfully connected"))
.catch((err) => console.log(err));
// Passport middleware
app.use(passport.initialize());
// Passport config
require("./config/passport")(passport);
// Routes
// Add api routes to middleware chain.
app.use("/", indexRouter);
app.use("/api", apiRouter);
// Serve static assets (build folder) if in production
if (process.env.NODE_ENV === "production") {
// Set static folder
app.use(express.static("client/build"));
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "client", "build", "index.html"));
});
}
const port = process.env.PORT || 5000;
app.listen(port, "0.0.0.0", () =>
console.log(`Server up and running on port ${port} !`)
);
I am not familiar with the axios as I always use the native fetch API. Maybe the isomorphic fetch can help.

Express does not properly follow server.js specifications

I am very new to learning and using the MERN stack. Currently, I am having a problem where when I try to run "nodemon server", the port opens on instead of despite specifying in server.js that I want it to start on 5000. I am having trouble sending POST requests to using Insomnia with the current server.js code below (I get a 404 error) and think that this might be causing the POST command to fail. Moreover, it also doesn't run console.log('Server is running on port: ${port}'); into the terminal I am running the server from. Any feedback is appreciated.
server.js
const express = require("express");
const cors = require("cors");
const mongoose = require("mongoose");
require("dotenv").config();
const app = express();
const port = process.env.PORT || 5000;
app.use(cors());
app.use(express.json());
const uri = process.env.ATLAS_URI;
mongoose.connect(uri, { useNewUrlParser: true, useCreateIndex: true });
const connection = mongoose.connection;
connection.once("open", () => {
console.log("MongoDB database connection established successfully");
});
const courseRouter = require("./routes/course");
const termRouter = require("./routes/term");
const userRouter = require("./routes/user");
app.use("/course", courseRouter);
app.use("/term", termRouter);
app.use("/user", userRouter);
app.listen(port, () => {
console.log(`Server is running on port: ${port}`);
});

Categories

Resources