Receive HTTPS POST request in NODEJS - node.js

I want to handle the POST request data in NODEJS using HTTPS. Something like below,
var express = require('express')
var bodyParser = require('body-parser')
var https = require('https');
// Create a new instance of express
var app = express()
// Tell express to use the body-parser middleware and to not parse extended bodies
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }))
//private key and certificate for secure connection (https)
var options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem'),
requestCert: false,
rejectUnauthorized: false,
};
var httpsApp = https.createServer(options,app);
// Route that receives a POST request to /sms
httpsApp._events.request.post('/xyz', function (req, res) {
-----
some code
-----
})
httpsApp.listen(5004, function(){
console.log("listening on port 5004");
logger.info("listening on port 5004");
});
But turns out, this only works for HTTP request. This will not give any error but it wont receive the data to be received in '/xyz'.
Thanks.

Maybe you can use something like an Reverse-Proxy to fix this more nicely?

Maybe you need to check your certificates.
I have checked this code through my certificates and they are working with https.
I m putting code here:
var express = require('express')
var bodyParser = require('body-parser')
var https = require('https');
var fs = require('fs')
// Create a new instance of express
var app = express()
// Tell express to use the body-parser middleware and to not parse extended bodies
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }))
//private key and certificate for secure connection (https)
var options = {
key: fs.readFileSync('./certificates/server.key'),
cert: fs.readFileSync('./certificates/server.crt'),
requestCert: false,
rejectUnauthorized: false,
};
var httpsApp = https.createServer(options,app);
// Route that receives a POST request to /sms
httpsApp._events.request.get('/xyz', function (req, res) {
console.log("Works")
res.send("working")
})
httpsApp.listen(5004, function(){
console.log("listening on port 5004");
});

Related

How do you send a http request to a raspberry pi node server api

I have a Raspberry Pi running a Node server using Express to set up different endpoints for an API. The server's IP Address is 192.168.x.y with some port..
I'm trying to send a request from my computer to the Raspberry Pi using the request npm package, and I keep getting Invalid protocol error.
Is it possible to use an actual IP Address to send a request to in my code? I also tried using axios but I was getting errors with that too.
My Raspberry Pi Server:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var fs = require("fs");
const axios = require('axios');
const request = require('request');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.get('/', function(req, res) {
res.json({ message: 'API is Online!' });
});
app.listen(process.env.IP || 3000, process.env.IP, function () {
console.log("server started");
});
My Client:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
const request = require('request');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
//my raspberry pi IP address and port
request('192.168.x.y:3000', { json: true }, (err, res, body) => {
if (err) { return console.log(err); }
console.log(body);
});

nodejs, expressjs ) sessionID is regenerated on every request even secure is set to false

I know there are already some questions with same problems. But none of them solved my issue.
I use reactJS as my frontend code and expressJS as my server code.
My problem is, each time express gets request, it regenerates a different sessionID.
As the solution I found here, Express change session every request, that secure must be set to false if you want to prevent sessionID from resetting for every request.
The code below is my session setting in app.js
app.use(
session({
resave:false,
saveUninitialized:false,
secret:process.env.redis_secret_key,
cookie:{
maxAge:3600,
httpOnly:true,
/**
* for production code:
* secure:true
*/
secure:false
},
store:new RedisClient({createdClientRedis})
})
);
As you see, secure is set to false, but!
the code which I used to set cookie and redis.get shows me different sessionID.
code of cookie.js
const express = require('express');
module.exports={
setCookie:function(res,req,id){
res.cookie('user',req.sessionID);
},
removeCookie:function(res){
res.clearCookie('user',{path:'/'});
}
}
result:
redis code:
getRedis:function(req){
console.log("get redis "+req.sessionID);
return new Promise((resolve,reject)=>{
//some redis.get code
})
},
result:
Of course, getRedis function generates different sessionID for every request too.. and I cannot get value from redis database.
And the react code which I use to send a fetch request to server already has credentials setting.
export function chatRoomFetch(type,requestBody){
return fetch(`//localhost:8000/chat/${type}`,{
method:'POST',
credentials:'include',
headers:{
'Accept':'application/json',
'Content-Type':'application/json'
},
body:JSON.stringify(requestBody)
}).then((response)=>{
return response.json();
});
};
What am I doing wrong?
This is my entire express.js app.js code
//main javascript file for nodejs. server
const express = require('express');
const session = require('express-session');
const app = express();
const port = 8000;
const cors =require('cors');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const chatRouter = require('./router/chatRouter.js');
const authRouter = require('./router/authRouter.js');
const redis = require ('./redis/redis');
const { RedisClient } = require('redis');
const redisStore= require('connect-redis')(session);
require('dotenv').config();
//cors setting
app.use(cors({
origin:'http://localhost:8081',
credentials:true
}));
app.use(express.urlencoded({extended: true}));
app.use(express.json());
app.use(cookieParser());
//redis
const createdClientRedis = redis.createRedisClient();
app.use(
session({
resave:false,
name:'user',
saveUninitialized:false,
secret:process.env.redis_secret_key,
cookie:{
maxAge:3600,
httpOnly:true,
/**
* for production code:
* secure:true
*/
secure:false
},
store:new RedisClient({createdClientRedis})
})
);
//Routers
app.use('/chat',chatRouter);
app.use('/auth',authRouter);
app.listen(port, () => {
console.log(`Example app listening on port ${port}!`)
});

Nodejs bodyparser returning undefined for body variables

I'm trying to extract POST data using a NodeJS script (with Express). The body is received, but I cannot seem to extract the variable from it when posting to the page with Postman. The variable is undefined, although I have used the same code I found in different questions. I have correctly installed Nodejs, express and body-parser.
To clarify, I'm posting form-data with Postman with key 'username' and value 'test'.
Anyone knows what I'm doing wrong?
var https = require('https');
var fs = require('fs');
var app = require('express')();
const bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
var httpsOptions = {
key: fs.readFileSync('/home/privkey.pem'),
cert: fs.readFileSync('/home/cert.pem'),
};
var server = https.createServer(httpsOptions, app);
server.listen(3000);
app.get('/', function(req, res) { //On get
res.send(req.method);
});
app.post('/', function(req, res) { //On post
res.send( req.body.username );
});
I guess it has to do with the encoding:
JSON:
you have to set a header with Content-Type: application/json and
add the encoding in express before the route :
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
Otherwise you can just use the option x-www-form-urlencoded and set the inputs

Cannot GET when using forever with node and express

We are using NodeJS and Express in combination with forever. That worked fine, but now we had to update our NodeJS version and it all stops working.
We use angular with ui-routing for frontend routing so we have an static folder.
I can go to our homepage (/) and from there I can navigate to the whole site. But when I refresh an page or I go directly to an page (eg. /products) I get an
Cannot GET /products
error.
Node gives an 404 error.
When I run the script directly without forever everything works fine. As you can see we have 2 static folders configured in express. Before the update everything works fine.
We also use Apache to redirect custom domainnames to specific pages without changing the address in the browser, but that works fine (only shows the GET error instead of the page).
Anybody any idea how to solve this?
our app.js
var path = require('path');
var fs = require('fs');
// Return values from different config files will be added to this object so you can call config.[category].[property].
config = {};
// Save the app root directory to a global variable so it can be used in config files and other parts of the app. global.root is reserved, but global.path.root can be used without problems.
global.path = {root: path.resolve(__dirname)};
// Set environment and initialize environment-specific config variables
config.env = require(path.join(__dirname, 'config', 'env.config'));
// Set up database connection to use throughout the application
config.db = require(path.join(__dirname, 'config', 'db.config'));
// HTTP for development environment, HTTPS for production environment
var http = require('http');
var https = require('https');
// Set up debugging/logging for the development environment
var debug = require('debug')('http');
// Start the app using the Express settings/routines in express.config.
var app = require(path.join(__dirname, 'config', 'express.config'));
// Start GraphQL process
// require(path.join(__dirname, 'config', 'graphql.config'))(app);
var router = require(path.join(__dirname, 'config', 'routes.config'));
router(app);
// Running in production mode: HTTPS only
if(config.env.name === 'production') {
var credentials = {
privateKey: fs.readFileSync('privkey'),
certificate: fs.readFileSync('fullchain')
};
var server = https.createServer(credentials, app);
server.listen(4443);
server.on('error', onError);
server.on('listening', onListen);
var server2 = http.createServer(app);
server2.listen(8080);
// Running in development mode: HTTP only
} else {
var server = http.createServer(app);
server.listen(config.env.port);
server.on('error', onError);
server.on('listening', onListen);
}
//some listeners here
Our express.config.js
var path = require('path');
console.log('Initializing API...');
var express = require('express');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var compression = require('compression');
var morgan = require('morgan');
var session = require('express-session');
var MongoStore = require('connect-mongo')(session);
var config = require(path.join(__dirname, 'db.config'));
// The GraphQL server implementation for Express by the Apollo team.
var graphqlExpress = require('graphql-server-express').graphqlExpress;
var graphiqlExpress = require('graphql-server-express').graphiqlExpress;
var OpticsAgent = require("optics-agent");
var passport = require('passport');
var app = express();
// Handle application/json requests
app.use(bodyParser.json({ limit: '50mb' }));
// Handle application/x-www-form-urlencoded requests (usually POST, PUT, etc.)
app.use(bodyParser.urlencoded({ extended: false, limit: '50mb' }));
app.use(cookieParser());
app.use(session({
store: new MongoStore({
url: 'mongodb://' + config.url + ':' + config.port + '/' + config.name
}),
secret: 'secret',
key: 'skey.sid',
resave: false,
saveUninitialized: false,
cookie : {
maxAge: 604800000 // 7 days in miliseconds
}
}));
app.use(passport.initialize());
app.use(passport.session());
require(path.join(__dirname, 'auth.config'))(passport); //Load passport config
app.use(function(req, res, next) {
req.resources = req.resources || {};
// res.locals.app = config.app;
res.locals.currentUser = req.user;
res.locals._t = function (value) { return value; };
res.locals._s = function (obj) { return JSON.stringify(obj); };
next();
})
// Use gzip compression (following the Express.js best practices for performance)
app.use(compression());
// Serve frontend and static files like stylesheets and images from the Express server
app.use(express.static(path.join(__dirname, '..', '..', 'app')));
app.use(express.static(path.join(__dirname, '..', '..', 'public')));
// Morgan logger (previously named express-logger)
app.use(morgan("dev"));
// Generate the GraphQL schema
var schema = require(path.join(__dirname, 'graphql.config'))().then(function(schema) {
/* Use Apollo Optics middleware for query optimization/tracing. */
OpticsAgent.instrumentSchema(schema);
app.use('/apiv2', OpticsAgent.middleware());
console.log('GraphQL schema generated.');
/* Return params object for Apollo GraphQL Server using a request handler function. */
app.use('/apiv2', graphqlExpress(function(req) {
return {
schema: schema,
debug: true,
context: {
opticsContext: OpticsAgent.context(req)
}
};
}));
app.use('/graphiql', graphiqlExpress({endpointURL: '/apiv2'}));
console.log('GraphQL started.');
/* Handle all other HTTP requests AFTER graphql server API endpoint and other routes are defined. */
app.use('*', express.static('app'));
});
// Always keep the errorHandler at the bottom of the middleware function stack!
// Returns a user-friendly error message when the server fails to fulfill the request
app.use(function(err, req, res, next) {
var status = 500, response = {message: 'An internal server error has occurred while trying to load this page. '};
console.error(err.stack);
res.status(status).json(response);
next(err);
});
module.exports = app;
Not really an solution to this problem, but we changed forever to PM2 (https://github.com/Unitech/pm2) and that program is doing his job fine!

HTTPS POST using cURL CLI to a NodeJS server

I wrote an HTTPS NodeJS server (with a self signed certificate) where I want to receive and process POST requests from cURL CLI.
My server:
var https = require('https');
var fs = require('fs');
var config = require('./conf.json');
var g3updater_kernel = require('./g3updater_kernel');
var express = require('express');
var app = express();
var privateKey = fs.readFileSync(config.security_repository+'/CA/rootCA.key', 'utf8');
var certificate = fs.readFileSync(config.security_repository+'/CA/rootCA.pem', 'utf8');
var httpsOptions = {
key: privateKey,
cert: certificate
}
app.post('/', function(req, res){
console.log(req.query);
});
https.createServer(httpsOptions, app).listen(443);
cURL command I use:
curl -d M=1 https://localhost/ -k
The problem is that I receive an empty query. console.log(req.query) displays:
{}
am I missing something in the query?
In order to parse the queries in your post request you're going to want to use body-parser.
In Express 4, there was conscious decision made to move bodyParser and CookieParser to separate modules.
In order to access your queries, you're code should look something like:
var https = require('https');
var fs = require('fs');
var config = require('./conf.json');
var g3updater_kernel = require('./g3updater_kernel');
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
var privateKey = fs.readFileSync(config.security_repository+'/CA/rootCA.key', 'utf8');
var certificate = fs.readFileSync(config.security_repository+'/CA/rootCA.pem', 'utf8');
var httpsOptions = {
key: privateKey,
cert: certificate
}
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
app.post('/', function(req, res){
console.log(req.body);
});
https.createServer(httpsOptions, app).listen(443);
Note that they will be held in req.body instead of req.query.
Happy Coding!

Resources