Is this Express + HTTPS spdy + socket.io server correctly initialized? - javascript

I've been working on a project a while and I'm not sure that my https is correctly mounted since I'm not fully aware of the sentences that are invoked in the code, could someone bring some light into this?
const express = require('express')
const spdy = require('spdy')
const cors = require('cors')
const fs = require('fs')
const app = express()
const serverCertificates = {
key: fs.readFileSync(__dirname + '/cfg/cert/localhost-private.pem'),
cert: fs.readFileSync(__dirname + '/cfg/cert/localhost-cert.pem')
}
const corsOptions = {
cors: {
origin: "https://localhost:3200",
transports: ['websocket'],
upgrade: false
}
}
Up to here is just require, mounting express on app and declaring some server options
After the classic app.use statements comes the trouble, I need to run HTTPS and Socket.io in the same server, and the only role that express is doing is serving statics directories
app.use(express.json())
app.use(cors())
app.use('/', express.static('./public'))
app.get('/favico.ico', (req, res) => res.sendFile(__dirname + '/public/favico.ico'))
let server = spdy.createServer(serverCertificates, app)
let io = app.io = require('socket.io')(server, corsOptions)
io.attach(server)
server.listen(3200, (error) => {
if (error) {
return process.exit(1)
} else {
console.log('Escuchando en *:' + PORT)
}
})
server.on('error', err => console.log(err))
Now I'm not using express routing as an API because the communication with client is done by Express.IO but eventually the project must contain a database that would be handled by express.
The question is "am I doing the right things here? is there a better way of mounting this type of server?"
Thanks in advance

Related

what is use of next() in express js

I m using this script to start my next js app, i cant share whole script, but i need to some help to know:
what is use of compression ?
what is use of helmet ?
what is use of next({dev}) ?
const express = require('express');
const next = require('next');
const helmet = require('helmet');
const compression = require('compression');
const nextApp = next({ dev });
const nextRequestHandler = routes.getRequestHandler(nextApp);
nextApp.prepare()
.then(() => {
const server = express();
server.use(compression());
server.use(helmet.noSniff());
server.use(helmet.hsts({ preload: true }));
server.use(helmet.hidePoweredBy());
const requestFun = (req, res) => {
const parsedUrl = parse(req.url, true);
const { pathname } = parsedUrl;
//res.setHeader('X-XSS-Protection', '1; mode=block');
if (pathname === 'xyz' || pathname.startsWith('xyz') || pathname.startsWith('xyz' || pathname.startsWith('/_next'))) {
const filePath = join(__dirname, '../public', pathname);
nextApp.serveStatic(req, res, filePath);
} else {
nextRequestHandler(req, res, req.url);
}
}
server.listen(port, (err) => {
if (err) {
throw err;
};
console.log(`Server started on port ${port}`);
})
})
.catch((ex) => {
console.error(ex.stack);
process.exit(1);
});
Compress is a middleware to compress the request bodies if possible and traverse/pass it through to the next middleware. And Compress will never compress the responses. For more details, you can read all and get to know some extended features of the package using the official docs "https://www.npmjs.com/package/compression"
Helmet is an express middleware that helps to send HTTP headers in a more secure way and a helmet is The top-level helmet function is a wrapper around 15 smaller middleware. Please go through it once to get to know that package features in detail "https://www.npmjs.com/package/helmet".
Next is a framework to create node servers specifically for backend applications and next() basically is a method/middleware which requires hostname and port and some optional parameters such as environment to create an instance of next and you can store into a variable "const app = next({ dev, hostname, port })". You can get more detail from the official docs "https://nextjs.org/docs/advanced-features/custom-server".

Auto update ssl node.js

is there any way to make the node.js server update automatically with the new certificates generated by let's encrypt every 3 months without restarting the service?
My server has a hosting panel that auto manages the certificates, so I can't use the certbot manually.
Currently I have a cron that runs monthly and restarts the server to take the new changes, but sometimes the certificate changes a few days before and my sites and apis stop working until my server restarts. It doesn't seem to me the most optimal solution.
const fs = require("fs");
const https = require("https");
const express = require("express");
const helmet = require("helmet");
var cors = require("cors");
const API = require("./index.js");
const hostname = "ENV.HOSTAME";
const httpsPort = ENV.PORT;
const httpsOptions = {
cert: fs.readFileSync("CERT-PATH"),
ca: fs.readFileSync("CA-PATH"),
key: fs.readFileSync("CA-KEY"),
};
const app = express();
app.use(helmet());
app.use(cors());
const httpsServer = https.createServer(httpsOptions, app);
// Parse URL-encoded bodies (as sent by HTML forms)
//app.use(express.urlencoded());
// Parse JSON bodies (as sent by API clients)
app.use(express.json());
app.get("/", function (req, res) {
res.redirect("HOSTNAME");
});
app.post("API-ROUTE", async function (req, res) {
const response = await API(req);
if (response != "Error") {
res.status(200).send(response);
} else {
res.status(500).json({ message: "Server Error" });
}
});
httpsServer.listen(httpsPort, hostname);
nodejs uses http service and nginx for reverse proxy. When the certificate is updated, there is no need to restart the whole service. Executing nginx -s reload works for me.

Respond to client after receiving client to server POST request (Node.JS)

I have been attempting to respond to a client-side request with Node.JS. I have discovered Node JS - call function on server from client javascript, which seems to explain what I want, except that I can't seem to translate it to my program.
Here is the request via POST in index.html:
$.post("/", {data: 'hi'}, function(result){
$("body").html(result);
});
what I was hoping it would do would be write the result of the call, from my server.js (Node):
const express = require('express');
const path = require('path');
const http = require('http');
const fs = require('fs');
function handler(data, app){
if(req.method == "POST"){
app.setHeader('Content-Type', 'text/html');
app.writeHead(200);
app.end(data);
}
}
const BUILDPATH = path.join(__dirname);
const { PORT = 3000 } = process.env;
const app = express();
app.set('port', PORT);
app.use(express.static(BUILDPATH));
app.get('/*', (req, res) => res.sendFile('static/index.html', { root: BUILDPATH }));
const httpServer = http.createServer(app);
httpServer.listen(PORT);
console.info(`🚀 Client Running on: http://localhost:${PORT}`);
try this code:
const express = require('express');
const path = require('path');
const http = require('http');
const fs = require('fs');
function handler(data, app){
if(req.method == "POST"){
app.setHeader('Content-Type', 'text/html');
app.writeHead(200);
app.end(data);
}
}
const BUILDPATH = path.join(__dirname);
const { PORT = 3000 } = process.env;
const app = express();
app.set('port', PORT);
app.use(express.static(BUILDPATH));
app.get('/', (req, res) => {
res
// best practice is to always return an status code
.status(200)
// just return an json object
.json({"msg": "ok, it all works just fine"})
});
const httpServer = http.createServer(app);
httpServer.listen(PORT);
console.info(`🚀 Client Running on: http://localhost:${PORT}`);
The issue is, is that the only route your Node server listens to is the one you define with /*. As you can see, that route returns your index.html file to the client. You did not specify a route that listens for a request that comes from the client.
To solve the issue, you will have to define a route that listens on a specific route for the request you are trying to make from your client.
I see you are using ExpressJS. here is the documentation on writing routes.

Implementing socket.io in mongoDB and Angular it is throwing errors Cannot GET /socket.io/

I am developing an angular application which I need to use notifications for example.
I have a user which can add friends and then I can sent a friend request as in facebook and then the other user will be notificate in realtime for example You have one new notification, this user wants to be friends.
If anyone has better idea than socket.io I am free to listen and to learn
The problem it is that I get everytime Cannot GET /socket.io/
Request URL: http://localhost:4200/socket.io/?EIO=3&transport=polling&t=NVvJf99
Request Method: GET
Status Code: 404 Not Found
Remote Address: 127.0.0.1:4200
I can show the list who sent me friend but I need everytime to reload page to see new requests.
I am using socket.io in both frameworks.
Angular I have installed with npm and the same in the mongoDB.
My server.js that is what I use for the requests and responses in frontend.
Server.js
const express = require('express');
const mongoose = require('mongoose');
const http = require('http');
const cors = require('cors');
const routes = require('./src/app/routes/routes');
const path = require('path');
const socketIO = require('socket.io');
const app = express();
const server = http.Server(app);
mongoose.connect('mongodb+srv://vip:admin#test-name-sn4qu.mongodb.net/test?retryWrites=true&w=majority'
, {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false
});
app.use(cors());
const io = socketIO(server);
app.set(io);
app.use(express.json({limit: '50mb'}));
app.use(express.urlencoded({limit: '50mb', extended: true}));
app.use('/images', express.static(path.resolve(process.cwd(), '../images')));
app.use(routes);
mongoose.set('useNewUrlParser', true);
mongoose.set('useFindAndModify', false);
mongoose.set('useCreateIndex', true);
app.get("/", (req, res) => {
res.json({ message: "Welcome to application." });
});
const PORT = process.env.PORT || 5000;
server.listen(PORT);
And then in the friendController I use something like this.
function createNewRequest(req, res, next) {
const io = req.app.get('io');
friendService.createNewRequest(req.body)
.then(res.status(200).json({ message: 'Friend added successfully' }),
io.emit('newTaskAdded'))
.catch(err => next(err));
}
And then in the frontend I do have something like this.
And I am having an error which says
Cannot find namespace 'SocketIOClient'. private socket:SocketIOClient.Socket;
import * as io from "socket.io-client";
constructor() {
this.socket = io();
}
ngOnInit(): void {
this.LoadRequestingFriends();
this.socket.on('newTaskAdded', () => {
this.LoadRequestingFriends();
})
}

Continuously changing Express Route Paths for protection

I want to create a hidden internal webserver with ever-changing routes.
The aim is to prevent/deter people from scraping the site or using the API without permission.
There's probably a better way (or this could be totally useless)
I've written some code that works but either convince me why I'm wasting my time or why it would work.
const express = require('express');
const uuid = require('uuid/v4');
const app = express();
// These are the hidden routes
const routes = {
hiddenPage: undefined,
};
setInterval(() => {
// Change the path of the hidden page
// every 5 seconds
routes.hiddenPage = `/${uuid()}`;
}, 1000 * 5);
app.get('*', (req, res) => {
// There would be other middleware for
// security reasons
if (req.path === routes.hiddenPage) {
res.send('Welcome to the hidden page');
return;
}
res.send(`Page at <a href=${routes.hiddenPage}>${routes.hiddenPage}</a>`);
});
// Listen on 3000
app.listen(3000);
You can use CORS middleware to allow only specific clients to access your server.
https://expressjs.com/en/resources/middleware/cors.html
Example:
var express = require('express')
var cors = require('cors')
var app = express()
var corsOptions = {
origin: 'http://example.com',
}
app.get('/products/:id', cors(corsOptions), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for only example.com.'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})

Categories