I am currently building a simple CRUD app using ExpressJS, and host it on Heroku using free account.
The problem I ran into is:
GET API for getting all items works on localhost, but show status 503 when hosting on Heroku;
POST API for updating one item works on localhost, but same issue as GET API above;
All 503 errors are after 30s of loading, this should be a setting from Heroku.
I do have other API end points that work on both local and Heroku server:
GET API for getting one item using ID
My guessing:
The issue should not be a code issue
There is some issue when the code is deployed and Heroku cannot process this request
I tried to find some articles on the web but this seems hard to diagnose, anyone who has experience please let me know how I can solve this issue. Appreciate your comments.
My Mongoose Schema
const mongoose = require("mongoose");
const ThoughtSchema = mongoose.Schema({
title: {
type: String,
required: true
},
content: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
}
});
module.exports = mongoose.model("Thought", ThoughtSchema);
2 end points that do not work
// Returns all thoughts
router.get("/", async (req, res) => {
try {
const thought = await Thought.find();
res.json(thought);
} catch (err) {
res.json({ message: err });
}
});
// Submit a post
router.post("/", async (req, res) => {
const thought = new Thought({
title: req.body.title,
content: req.body.content
});
try {
const savedThought = await thought.save();
res.json(savedThought);
} catch (err) {
res.json({ message: err });
}
});
The end point that works
// Specific thought
router.get("/:thoughtId", async (req, res) => {
try {
const thought = await Thought.findById(req.params.thoughtId);
res.json(thought);
} catch (err) {
res.json({ message: err });
}
});
My package.json for this express app
{
"name": "my-thoughts-app",
"version": "0.1.0",
"description": "An app to records user's thoughts",
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/PayneTang/my-thoughts-app.git"
},
"author": "Payne Tang",
"license": "ISC",
"bugs": {
"url": "https://github.com/PayneTang/my-thoughts-app/issues"
},
"homepage": "https://github.com/PayneTang/my-thoughts-app#readme",
"dependencies": {
"dotenv": "^8.2.0",
"express": "^4.17.1",
"mongoose": "^5.8.11"
},
"devDependencies": {
"typescript": "^3.7.5"
}
}
EDIT:
My index.js
const express = require("express");
const path = require("path");
const app = express();
const mongoose = require("mongoose");
const thoughtRoute = require("./routes/thought");
require("dotenv").config();
console.log(process.env);
// Mongoose settings
mongoose.connect(
process.env.DB_CONNECTION,
{ useNewUrlParser: true, useUnifiedTopology: true },
() => {
console.log("Connected to DB!");
}
);
app.use(express.json());
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "*");
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept"
);
next();
});
app.use("/api/thought", thoughtRoute);
app.get("/api/test", (req, res) => {
res.send("hi");
});
// Serve client side
app.use(express.static(path.join(__dirname, "client/build")));
app.use(express.static(path.join(__dirname, "client/public")));
// app.get("*", (req, res) => {
// res.sendFile(path.join(__dirname, "client/build/index.html"));
// });
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
console.log("Listening on port " + PORT + "...");
});
The root cause after checking is due to the access restriction from Heroku to Mongo atlas.
After adding 0.0.0.0/0 for IP whitelist, I am able to get data from MongoDB.
Reference: https://docs.atlas.mongodb.com/security-whitelist/#add-whitelist-entries
I had the same problem and I was able to fix it by doing these two steps:
Add node version to package.json file:
"engines": {
"node": "14.17.3"
}
}
I changed access settings in MongoDB, allowing access to the database from anywhere (basically, whitelisting 0.0.0.0/0 IP address)
In my case, the issue was in package.json I installed two new packages yesterday and in my package.json:
"engines": {
"node": "12.16.0"
},
I changed the version to the my current system version:
"engines": {
"node": "14.5.0"
},
this is how my 503 service unavailable error gone.
This can be caused in several ways to the Node app.
1- Make sure that you specify the right port as what heroku does is it runs our app on a dynamic port.
const PORT = process.env.PORT || 3000;
app.listen(PORT, err => {
if(err) throw err;
console.log("%c Server running", "color: green");
});
as described in this comment
https://stackoverflow.com/a/52992592/11887902
2- Make sure that you added the Procfile with
npm start
to start the application.
3- If you are using Nodemon and you install it globally, just make sure that you install it locally too.
Finally, just have a look at the logs of the project to figure what heppen to make your project not in the service.
These cases happened to me and caused this error.
My issue was caused due to case sensitivity that is at times ignored by node,
in my controllers I had a file named sessions.js yet when importing in my routes I had mistakenly put ... = require('../controllers/Sessions'),
Nodemon was running without issues as I was developing but upon deploying on heroku it crashed so I changed to ... = require('../controllers/sessions')
and now it runs ok
Related
I created Next Js project. I deployed it to my CPanel. And I created server.js file on directory.
I called next module as require in server.js. But When I access to my website I catch an error.
internal/modules/cjs/loader.js:638
throw err;
^
Error: Cannot find module 'next';
This error message.
My server.js code
const { createServer } = require("http");
const { parse } = require("url");
const next = require("next");
const dev = process.env.NODE_ENV !== "production";
const port = !dev ? process.env.PORT : 3000;
// Create the Express-Next App
const app = next({ dev });
const handle = app.getRequestHandler();
app
.prepare()
.then(() => {
createServer((req, res) => {
const parsedUrl = parse(req.url, true);
const { pathname, query } = parsedUrl;
handle(req, res, parsedUrl);
console.log("pathname", pathname);
}).listen(port, (err) => {
if (err) throw err;
console.log(`> Ready on http://localhost:${port}`);
});
})
.catch((ex) => {
console.error(ex.stack);
process.exit(1);
});
My package json
{
"name": "projectName",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "node server.js",
"build": "next build",
"start": "NODE_ENV=production node server.js"
},
"dependencies": {
"express": "^4.17.1",
"next": "10.0.6",
"react": "17.0.1",
"react-dom": "17.0.1"
}
}
What should i do?
Thank you.
Best regards
Add this in your package.json dependency section : "#next/env": "^12.0.7"
I've already had problems publishing a next application other than on vercel. To fix the error I had to create a docker in order to publish the application. In case someone doesn't answer with a more viable solution, I recommend looking into using a docker.
I have created my first FullStack JS app. REACT for the front port :3000, NODE for the Back port 3001 and postgresql for database. And is also the first time I use Heroku !
My app called philosophybooks my database postgres is livres with one table books on this table 13 rows, 13 books in my db it's just for exemple :
author, title, date_of_parution, cover cover is just a string I've a folder illustrations_books in my frontend part of my app in this folder I have all images of the cover book
With CLI on windows I have well push all my app with my database all is well on Heroku. In front I've run a build folder and I have copy this one in back part of my app.
When I start heroku local web all work perfectly on http:localhost:5000
but when I launch my app not locally I have a console error
GET https://philosophybooks.herokuapp.com/livres 503 (Service Unavailable)
in front part in package.json I've"proxy": "http://localhost:3001"
little part of index.js
...
app.use(express.static('build'))
...
//Entry point API
app.get('/', (req, res) => {
res.send('My app is well connected and endpoint is OK')
})
//READ ALL
app.get("/livres", (req, res) => {
pool.query('SELECT * FROM books ORDER BY id ASC', (err, results) => {
if (!err)
res.status(200).json(results.rows)
else
console.log(err)
})
})
...
...
const port = process.env.PORT || 3001
app.listen(port, () => {
console.log(`[Express] is running on port ${port}`)
})
Little part of Livres.jsx in front part
...
...
useEffect(() => {
const fetchData = async () => {
setIsError(false)
try {
const result = await axios('/livres') /* 'http://localhost:3001/livres' */
setData(result.data)
} catch (error) {
setIsError(true)
console.log(error)
}
}
fetchData()
}, [])
...
...
config.js
require('dotenv').config()
const { Pool } = require('pg')
/* const pool = new Pool({
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
host: process.env.DB_HOST,
port: process.env.DB_PORT,
database: process.env.DB_DATABASE,
}) */
const isProduction = process.env.NODE_ENV === 'production'
const connectionString = `postgresql://${process.env.DB_USER}:${process.env.DB_PASSWORD}#${process.env.DB_HOST}:${process.env.DB_PORT}/${process.env.DB_DATABASE}`
const pool = new Pool({
connectionString: isProduction ? process.env.DATABASE_URL : connectionString,
ssl: isProduction,
})
module.exports = { pool }
I have also a Procfile file web: node index.js
package.json backend part
{
"name": "philosophybooks",
"version": "1.0.0",
"description": "bibliothéque philosophique",
"main": "index.js",
"engines": {
"node": "12.x",
"npm": "6.x"
},
"scripts": {
"start": "nodemon index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"NODEJS",
"JAVASCRIPT",
"ES6"
],
"author": "LC",
"license": "ISC",
"dependencies": {
"compression": "^1.7.4",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"helmet": "^4.1.1",
"nodemon": "^2.0.4",
"path": "^0.12.7",
"pg": "^8.3.3"
}
}
Render heroku local web
Render in prodhttps://philosophybooks.herokuapp.com/
I have to make a mistake that I don’t see or forget something, can you help me? if you need to see something else tell me. Thank you in advance for your help
EDIT Octobre 18, 2020
My database on HEROKU and via CLI pg:psql
Bonjour Parad0xJ,
PROBLEM:
It wasn't working because you were assigning an ssl certificate that wasn't verified. If you look at the heroku error carefully you will notice this error.
Error: self signed certificate
'DEPTH_ZERO_SELF_SIGNED_CERT'
const pool = new Pool({
connectionString: isProduction ? process.env.DATABASE_URL : connectionString,
ssl: isProduction, <=========== unverified self signed certificate
})
SOLUTION
Get rid of the ssl property in your pool configuration. Heroku already provides you a ssl so all you have to do is determine whether you want to disable or require it. You can read more here
const pool = new Pool({
connectionString: isProduction ? process.env.DATABASE_URL : connectionString,
sslmode: isProduction ? "require" : "disable"
})
Also you need to add the * route to the bottom because when it is at the top no other routes can be access:
app.get('*', (req, res) => { //<=========== Should be at the bottom of all routes
res.sendFile(path.join(__dirname, "frontend/build/index.html"));
});
Here is all the configuration in this git repo :
https://github.com/l0609890/philosophybook/invitations
I'm new to APIs based on nodeJS and I would like to connect to an already existing collection in a MongoDB database.
If I try to access http://localhost:8080/teams I get an error on the browser: Cannot GET /Teams.
Not even the console.log get printed but nodemon (that I'm using to load after each save) shows no errors.
This is an example of the existing records:
use MYDB
db.TeamsCol.find()
{ "_id" : ObjectId("5d702df59ba60607dad06df4"), "teamID" : 1, "teamName" : "PT", "datetime" : "04-09-2019 10:21:16 Wednesday" }
{ "_id" : ObjectId("5d702ed59ba60607dad06df5"), "teamID" : 2, "teamName" : "ES", "datetime" : "01-09-2019 11:20:00 Sunday" }
I built the following struture:
project folder: API
API/server.js
API/models/teamModel.js
API/Routes/teamRouter.js
as described below:
API/server.js file:
// Import express
let express = require('express');
// Import Body parser
let bodyParser = require('body-parser');
// Import Mongoose
let mongoose = require('mongoose');
// Initialise the app
let app = express();
// Setup server port
var port = process.env.PORT || 8080;
// Import routes
let apiRouter = require("./Routes/teamRouter");
// Connecting to the database
const db = mongoose.connect('mongodb://localhost/MYDB', {useNewUrlParser: true});
// setting body parser middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// API routes
app.use('/Teams', apiRouter);
// Running the server
app.listen(port, () => {
console.log(`http://localhost:${port}`)
})
API/models/teamModel.js file:
// Import Mongoose
let mongoose = require('mongoose');
const Schema = mongoose.Schema;
const teamModel = new Schema({
teamID: { type: Number },
teamName: { type: String },
datetime: { type: String },
})
module.exports = mongoose.model('teamsModel', teamModel, 'TeamsCol');
API/Routes/teamRouter.js file:
// Import express
let express = require('express');
// Import Teams controller
var Team = require('../models/teamModel');
const teamRouter = express.Router();
teamRouter.route('/teams')
.get((req, res) => {
Console.log(req)
Team.find({}, (err, teams) => {
res.json(teams)
})
})
// Middleware
teamRouter.use('/:team', (req, res, next)=>{
Team.findById( req.params.team, (err,team)=>{
if(err)
res.status(500).send(err)
else {
req.team = team;
next()
}
})
})
teamRouter.route('/:team')
.get((req, res) => {
res.json(req.team)
}) // end get Teams/:team
// Export API routes
module.exports = teamRouter;
Here are the versions I'm using
mongo --version
MongoDB shell version v3.6.3
node --version
v8.9.4
and also the package.json contents:
{
"name": "teamsapi",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.19.0",
"express": "^4.17.1",
"mongoose": "^5.6.12"
}
}
Any ideas?
Because in your server.js file, you already used:
app.use('/Teams', apiRouter);
So the api /teams doesn't exist, it should be /Teams/teams. And the full url will be http://localhost:8080/Teams/teams.
I'm very new with Express.js, but right now i've created an api of SQL Server DB. It works fine on localhost, but now, i've deployed on Heroku. While my CMD prompt is open, my api works fine, but when it's close, i get an Internal Server Error.
Previously, i've created a test using Mongo as DB, mongoose and deployed to Heroku an the api still working even when the prompt isn't open. Someone knows if i have to create another .js document just like in mongoose or else to keep working my api?
This is my code on the .js document (server.js):
const express = require('express');
const bodyParser = require('body-parser');
const sql = require('mssql');
const app = express();
app.use(bodyParser.json());
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, contentType,Content-Type, Accept, Authorization");
next();
});
const dbConfig = {
user: "daUser",
password: "daPass",
server: "daServer",
database: "DaDB"
}
const executeQuery = function (res, query) {
sql.connect(dbConfig, function (err) {
if (err) {
console.log(err);
res.send(err);
}
else {
// create Request object
var request = new sql.Request();
// query to the database
request.query(query, function (err, result) {
if (err) {
console.log(err);
res.send(err);
}
else {
res.send(result);
}
});
}
});
}
app.get("/api/HolidayBaseApi", function (req, res) {
var query = "SELECT * FROM [HolidaysBase]";
executeQuery(res, query);
})
const PORT = process.env.PORT || 8080
app.listen(PORT, () => {
console.log("App now running on port", PORT);
});
My package.json next:
{
"name": "holidaysbaseapi",
"version": "1.0.0",
"description": "Api of Holidays",
"main": "server.js",
"scripts": {
"start": "node server.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Chuck Villavicencio",
"license": "ISC",
"dependencies": {
"body-parser": "^1.18.3",
"express": "^4.16.4",
"mssql": "^4.3.0"
},
"engines": {
"node": "8.11.3",
"npm": "5.6.0"
}
}
On Heroku i've installed the Heroku CLI; logged in, Clone the repository and deployed my changes.
I'm using Express.js, Node, SQL Server and Heroku
The problem is that your SQL server db is created on you local machine and heroku can't connect to it. You can you the postgresDB provided by heroku or create the sql server db in any provider around the internet and replace the dbConfig with the configs of that db
I'm new to Node and created an app that has some async/await syntax in it like so:
const express = require('express');
const app = express();
const someLibrary = require('someLibrary');
function asyncWrap(fn) {
return (req, res, next) => {
fn(req, res, next).catch(next);
};
};
app.post('/getBlock', asyncWrap(async (req,res,next) => {
let block = await someLibrary.getBlock(req.body.id);
[some more code]
}));
app.listen(process.env.PORT || 8000);
It works fine on my machine but when I deploy to Heroku I get an error because the syntax is not supported:
2017-03-23T10:11:13.953797+00:00 app[web.1]: app.post('/getBlock', asyncWrap(async (req,res,next) => {
2017-03-23T10:11:13.953799+00:00 app[web.1]: SyntaxError: Unexpected token (
What is the easiest way to get Heroku to support this syntax?
Specify the node version you want to use in your package.json: https://devcenter.heroku.com/articles/nodejs-support#specifying-a-node-js-version
So for async/await support you'll want to specify >= 7.6.0
{
"engines": {
"node": ">= 7.6.0"
}
}
From the Heroku documentation here
https://devcenter.heroku.com/articles/getting-started-with-nodejs#declare-app-dependencies
it should be declared in your package.json file which engine(s) should be accessible:
{
"name": "node-js-getting-started",
"version": "0.2.5",
...
"engines": {
"node": "5.9.1"
},
"dependencies": {
"ejs": "2.4.1",
"express": "4.13.3"
},
...
}