Problem
I have deployed a Node.js/Express.js/Mongoose API to Heroku, however when I hit the endpoints I get a 503 status code and the Heroku prompt telling me there is an application error.
Attempts at a solution
I read on a different Stackoverflow post that you needed to add the MONGODB_URI as a config var in the settings of your Heroku app, so I added the connection string and changed the MongoDB connection to:
// Connect to DB
mongoose.connect(process.env.MONGODB_URI || uri, {useNewUrlParser: true, useUnifiedTopology: true}, () =>
console.log('Connected to DB!')
);
However that didn't seem to help. I also tried appending &ssl=true to the connection string, which didn't work. Then I tried changing the Mongoose version to 5.7.0 and changing the MongoDB connection string to Node version 2.12.12 or later (From Atlas Cloud). None of it worked.
File structure of app
Here is the very simple structure of my API
In index.js I setup the express app, set the routes, connect to the port and connect to the database using Mongoose:
const express = require('express');
const cors = require('cors');
const mongoose = require('mongoose');
const uri = "mongodb+srv://username:[email protected]/quizappdb?retryWrites=true&w=majority";
const app = express();
// Middleware
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(cors());
// Import routes
const questionRoutes = require('./routes/questions.js');
app.use('/question', questionRoutes);
// Set to port 5000 and listen on port
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server started on port ${port}`));
// Connect to DB
mongoose.connect(process.env.MONGODB_URI || uri, {useNewUrlParser: true, useUnifiedTopology: true}, () =>
console.log('Connected to DB!')
);
(redacted username and password in uri)
And in routes/questions.js I define the API functions using the express router:
const express = require('express');
const router = express.Router();
const Question = require('../models/question');
// Get all questions
router.get('/', async (req, res) => {
try {
const questions = await Question.find();
res.json(questions);
} catch(err) {
res.json({message: err})
}
});
// Get questions by category
router.get('/:category', async (req, res) => {
const category = req.params.category;
console.log(category);
Question.find({category: category})
.exec()
.then(doc => {
console.log("From database", doc);
if (doc) {
res.status(200).json(doc);
} else {
res.status(404).json({message: 'No valid entry'})
}
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
})
})
// Add question
router.post('/', async (req, res) => {
const question = new Question({
category: req.body.category,
description: req.body.description,
option1: req.body.option1,
option2: req.body.option2,
option3: req.body.option3,
option4: req.body.option4,
answer: req.body.answer,
});
try {
const savedQuestion = await question.save()
res.json(savedQuestion);
} catch(err){
res.json({message: err})
}
});
// Delete question by id
router.delete('/:questionId', async (req, res) => {
try {
const removedQuestion = await Question.remove({_id: req.params.questionId})
res.json(removedQuestion);
} catch(err) {
res.json({message: err})
}
})
module.exports = router;
For Heroku to know which version of Node I am using I define it in the "engines" part of the package.json:
"engines": {
"node": "14.x"
}
And in the Procfile I have:
web: node index.js
When I go to the app at /question it hangs for 30 seconds, puts up the Heroku prompt of application error and in the logs I see:
2021-01-21T16:56:32.313123+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=GET path="/question" host=quiz-app-dk.herokuapp.com request_id=cda581cb-25c0-4980-a669-e65008a59ecd fwd="212.10.104.241" dyno=web.1 connect=1ms service=30001ms status=503 bytes=0 protocol=https
So a 503 status code.
When I specify a category and go to /question/Sport I get the same result:
2021-01-21T16:57:10.687786+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=GET path="/question/Sport" host=quiz-app-dk.herokuapp.com request_id=2620dc48-7581-406c-aa66-2085ee6decb3 fwd="212.10.104.241" dyno=web.1 connect=1ms service=30000ms status=503 bytes=0 protocol=https
Connection to DB
It is also worth noting that the connection to the DB seems to happen, as I see this in the Heroku logs:
2021-01-21T14:07:55.273864+00:00 app[web.1]: Connected to DB!
However, when I do either of those things locally, everything works fine. I suspect something with the routes is amiss, but I can't figure out what. Any help is greatly appreciated. Thank you.
UPDATE
I wrapped the database connection in a try catch and got the following:
2021-01-21T17:07:08.861455+00:00 app[web.1]: Unable to connect to the server. Please start the server. Error: MongoNetworkError: failed to connect to server [devcluster-shard-00-00.hesav.mongodb.net:27017] on first connect [MongoNetworkError: connection 5 to devcluster-shard-00-00.hesav.mongodb.net:27017 closed
2021-01-21T17:07:08.861463+00:00 app[web.1]: at TLSSocket.
question from:
https://stackoverflow.com/questions/65829611/why-is-my-node-api-working-locally-but-not-on-heroku