Enabling SSL certificate on Mongo using Mongoose and Express - node.js

I can't figure out how to add an SSL certificate to my server.js so I can access my API on the server through https.
var express = require('express'),
cors = require('cors'),
app = express(),
port = process.env.PORT || 3000,
mongoose = require('mongoose'),
Task = require('./api/models/todoListModel'), //created model loading here
bodyParser = require('body-parser'),
helmet = require('helmet');
// Test SSL connection
var MongoClient = require('mongodb').MongoClient;
// mongoose instance connection url connection
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost/Tododb'); // was tododb
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
// adding Helmet to enhance your API's security
app.use(helmet());
// enabling CORS for all requests
app.use(cors());
app.get('/', (req, res) => res.send('Hello World!'))
var routes = require('./api/routes/todoListRoutes'); //importing route
routes(app); //register the route
app.listen(port);
console.log('Supporter RESTful API server started on: ' + port);
I have tried mongoose.connect('mongodb://localhost/Tododb&ssl=true'); but I don't really know what to do after that? I understand I have to add a reference to the key and certificate files that I have generated but I can't figure how I add those to the connection string.
I have been attempting to follow some of this https://docs.mongodb.com/manual/reference/connection-string/
What's the next step?

The next step is to provide ConnectionOptions to the mongoose.connect call. The mongoose documentation (at https://mongoosejs.com/docs/connections.html#options) specifies that it will pass on ssl specific options to the underlying MongoClient. The options for the MongoClient can be found at: http://mongodb.github.io/node-mongodb-native/2.2/api/MongoClient.html#connect
The ones you are interrested in are likely sslCert, sslKey, and maybe sslPass (along with some more of the ssl* settings). Note that the ones I listed here might require you to load in a file in code yourself. You might be able to use something like:
var fs = require('fs');
var options = {
...
sslCert: fs.readFileSync(path.join(__dirname, <relative path to the cert>))
};
mongoose.connect('mongodb://localhost/Tododb', options);

Related

Why ECONNRESET error is coming in POSTMAN while making a NODEJS request

I have written a simple request response code in NODEJS but there is no response in return of the request is there .
The code for my app.js(Server file) is
const express = require('express');
const cors = require('cors')
const paymentroute = require('./routes/paymentRoutes');
const app = express();
app.use(cors);
app.use("/api",paymentroute);
app.listen(3100,()=>{
console.log(`listening to port 3100`);
})
The code for my req and res is
const express = require('express');
const router = express.Router();
// const { checkout } = require('../controllers/paymentController');
router.post("/checkout",(req,res) => {
console.log("this function is called ")
return res.json({success:"true"})
});
module.exports = router;
Even the console.log inside the res function is not working.
Just change app.use(cors); to app.use(cors());
const express = require('express');
const cors = require('cors');
const paymentroute = require('./routes/paymentRoutes');
const app = express();
app.use(cors());
app.use('/api', paymentroute);
app.listen(3100, () => {
console.log(`listening to port 3100`);
});
I think it is a connection-related issue often related to a networking issue caused by a Virtual Private Network (VPN) that in some cases is required by some API services or, in other cases, prevents you to reach an API service.
The issue seems to be a combo of having the no-cache header enabled and a request URL length over 64 characters. If the issue persists after doing this solution then try to upgrade to the latest version of Postman.

Express Server Not Handling Simultaneous API Calls Asynchroniously (Waiting for old call to resolve)

I am creating my first web application using the MEVN stack (MongoDb, Express, VueJS, Node). As far as I can tell from research, functions in my node server.js file are all async by default, but every time I make a request (POST/GET whatever) to the API, it halts the backend until that function has resolved. I need users who use the website to be able to send GET requests to the site while another user is uploading info to the DB for instance with a POST request in another function. Currently it just halts all calls until the first one resolves. I am testing by going to /test on my server with a 5 second wait, while simultaneously making a call to /api in Postman. The Postman request just hangs until the /test function resolves. I'm sure this is a novice issue, but why is this not functioning asynchronously? I have pasted the head from my server.js below
// Importing required modules
const bodyParser = require('body-parser');
const cors = require('cors');
const express = require('express');
const morgan = require('morgan');
const multer = require('multer');
const hashlips = require('./src/main.js')
const fs = require('fs-extra');
// parse env variables
require('dotenv').config();
require("./helpers/db/mongodb.js")();
// Configuring port
const port = process.env.PORT || 9000;
//configure express
const app = express();
// Configure middlewares
app.use(cors());
app.use(express.json({ limit: '10mb' }));
app.use(morgan('dev'));
app.use(bodyParser.json({ limit: '10mb' }));
app.use(express.urlencoded({extended: true}, { limit: '10mb' }));
app.set('view engine', 'html');
// Static folder
app.use(express.static(__dirname + '/views/'));
// Defining route middleware
app.use('/api', require('./routes/api'));
//routes
app.get('/test', (req, res) => {
await new Promise(r => setTimeout(r, 5000));
res.send("<h3>Express Server")
})
Here' is my api.js
const express = require('express');
const {
//init CRUD
createData,
readData,
updateData,
deleteData,
deleteAllData,
//init register login
registerNewUser,
loginUser,
getUserDetails,
//init collection saving
createCollection,
readCollectionData,
deleteAllCollections,
deleteCollection,
updateCollection,
} = require('../controllers/user_controller');
const auth = require('../config/auth')
const router = express.Router();
router
.put("/collection", createCollection)
.put("/collectionu", updateCollection)
.post("/", createData)
.post("/register", registerNewUser)
.post("/login", loginUser)
.get("/collection", readCollectionData)
.get("/me", auth, getUserDetails)
.get('/', readData)
.put('/:id', updateData)
.delete('/deletecollections', deleteAllCollections)
.delete('/deleteall', deleteAllData)
.delete('/deletecollection/:id', auth, deleteCollection)
.delete('/:id', deleteData);
module.exports = router;
Any help would be greatly appreciated! Idk if it's helpful but here's my --trace-sync-io stack trace:
(node:62551) WARNING: Detected use of sync API
at pbkdf2Sync (node:internal/crypto/pbkdf2:80:37)
at HI (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/cmap/auth/scram.js:245:31)
at continueScramConversation (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/cmap/auth/scram.js:138:28)
at /home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/cmap/auth/scram.js:90:9
at onMessage (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/cmap/connection.js:222:9)
at /home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/cmap/connection.js:63:60
at emit (node:events:394:28)
at processIncomingData (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/cmap/message_stream.js:132:20)
at _write (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/cmap/message_stream.js:33:9)
at writeOrBuffer (node:internal/streams/writable:389:12)
Connected to MongoDB
(node:62551) WARNING: Detected use of sync API
at randomFillSync (node:internal/crypto/random:137:19)
at randomBytes (node:internal/crypto/random:99:5)
at uuidV4 (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/utils.js:439:27)
at ServerSession (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/sessions.js:541:62)
at acquire (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/sessions.js:619:16)
at get serverSession (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/sessions.js:94:46)
at applySession (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/sessions.js:670:35)
at command (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/cmap/connection.js:278:53)
at /home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/sdam/server.js:210:18
at /home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongodb/lib/cmap/connection_pool.js:271:13
(node:62551) WARNING: Detected use of sync API
at randomFillSync (node:internal/crypto/random:137:19)
at randomBytes (node:internal/crypto/random:99:5)
at ObjectId.generate (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/bson/lib/objectid.js:145:54)
at ObjectId (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/bson/lib/objectid.js:47:34)
at NativeCollection.<computed> (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js:84:18)
at create (/home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongoose/lib/model.js:1803:22)
at /home/zach/Documents/WebProjects/mevn/ezmode/server/node_modules/mongoose/lib/model.js:1764:7
at processTicksAndRejections (node:internal/process/task_queues:78:11)

Combine node.js rest api's and angular on same server

We first developed REST api's using node.js and have that running on a VPS. We now have developed an Angular web app to display data that comes in via a mobile app that calls some of the REST api's and then updates the data by calls back to other REST API's. Running the Angular app on the localhost was able to successfully call the REST api's.
We want to combine both applications on the same server. After searching around it seemed that we could add commands to the REST api server.js to pass urls that didn't meet the REST api path to Angular. Code snippet is below:
// API verison
var apiVersion = '/v1'
var fs ;
var https ;
// Dependencies
var express = require('express');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
// MongoDB
...
// Express
var app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
// Routes
app.use(apiVersion, require('./routes/api'));
// Start server
fs = require('fs')
https = require('https')
https.createServer({
key: fs.readFileSync('...'),
cert: fs.readFileSync('...')
}, app)
.listen(443, function () {
console.log('HTTPS Server running on default port 443')
});
// Pass request to angular?
app.use(function(req, res) {
var path = require('path');
res.sendfile(path.resolve('/home/.../index.html')); // but not getting anything
});
The REST api's still work but when directing a browser to 'mydomain.net' I just get a blank page. I don't see any errors on the node/error logs.
Any ideas?
You can do something like this. Use static content to send from the dist folder and rest will work fine. I have added two reference in case you might need them to refer.
var apiVersion = '/v1'
const fs = require('fs')
const https = require('https');
const path = require('path')
// Dependencies
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
// MongoDB
...
// Express
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
// Pass request to angular?
app.use('path', express.static(path.resolve('your path should be correct')));
// Routes
app.use(apiVersion, require('./routes/api'));
// Start server
https.createServer({
key: fs.readFileSync('...'),
cert: fs.readFileSync('...')
}, app)
.listen(443, function () {
console.log('HTTPS Server running on default port 443')
});
Check here1 or here2 for more details, there are simple steps to follow.

CORS in node blocks POSTMAN to get data?

I'm using POSTMAN dev tool to test this API :
http://localhost:3000/users
and I have this express.js script :
const express = require("express");
const cors = require("cors");
const mongoose = require("mongoose");
const mongoConfig = require("./config/mongodb.config");
var bodyParser = require("body-parser");
// Routers
const userRouter = require("./core/user/user.route");
const app = express();
const port = process.env.PORT || 3000;
const URI = mongoConfig.mongoURI;
const connectionOptions = mongoConfig.connectionOption;
// Connect Mongo Atlas database
mongoose
.connect(URI, connectionOptions)
.then(() => {
console.log("Connection is established successfully ...");
})
.catch((err) => {
console.error(err);
});
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.json());
app.use(cors);
app.use("/users", userRouter);
app.listen(port, () => {
console.log("The server is running on port", `${port}`);
});
The problem is when I remove CORS :
// app.use(cors);
POSTMAN can get data but when I add CORS it blocks and returns this stack trace :
Could not get any response
There was an error connecting to http://localhost:3000/users.
Why this might have happened:
The server couldn't send a response:
Ensure that the backend is working properly
Self-signed SSL certificates are being blocked:
Fix this by turning off 'SSL certificate verification' in Settings > General
Proxy configured incorrectly
Ensure that proxy is configured correctly in Settings > Proxy
Request timeout:
Change request timeout in Settings > General
As far as I know, POSTMAN is dev tool and CORS is related only with a browser but I did not understand the reason behind it.
After debugging my server.js I found the bug was inside my server and it's not related to POSTMAN.
The problem is using cors before user using my routers will block the server ( unlimited looping ).
So when I changed this code :
app.use(cors);
app.use(express.json());
app.use("/users", userRouter);
To
app.use("/users", userRouter);
app.use(cors);
app.use(express.json());
The issue is solved but I did not understand why and what happens exactly inside the server.

nodejs: complaining about an used model

I was following this tutorial https://www.codementor.io/olatundegaruba/nodejs-restful-apis-in-10-minutes-q0sgsfhbd for building my first api.
Everything worked fine, and then I decided to change it to store locations and favorites, created a FavoritesModel.js and a LocationsModel.js.
My server.js now has
var express = require('express'),
app = express(),
port = process.env.PORT || 3000,
mongoose = require('mongoose'),
Location = require('./api/models/LocationsModel'),
Favorite = require('./api/models/FavoritesModel'),
bodyParser = require('body-parser');
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost/db');
require("./api/models/LocationsModel");
require("./api/models/FavoritesModel");
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
var routes = require('./api/routes/geolocationAPIRoutes');
routes(app);
app.listen(port);
console.log('geolocation RESTful API server started on: ' + port);
app.use(function(req, res) {
res.status(404).send({url: req.originalUrl + ' not found'})
});
However, when i run npm run start, i get MissingSchemaError: Schema hasn't been registered for model "Tasks".
What am I doing wrong? There's no reference for Tasks anywhere anymore. Do I need to rebuild the API or something? I already did a npm rebuild.
Location = require('./api/models/LocationsModel'), // remove this
Favorite = require('./api/models/FavoritesModel'), // remove this
bodyParser = require('body-parser');
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost/db');
var Location = require("./api/models/LocationsModel");// change this
var Favorite = require("./api/models/FavoritesModel");// change this
You requires those models twice.
Remove those requires before connect. And sentence variables after connection.

Resources