node js proxy service issue updating port - javascript

I am trying to set the target show in my proxy options to have the same port that is coming from my bonjour service. Also if the port change I would like to run the proxy function to setting the target. any help please. The code works however the issue is that the proxy only sets once. If the value from servicePort change the proxy does not update it continues to run with the old target
const express = require("express");
const { createServer } = require("http");
const { Server } = require("socket.io");
const { WebMidi } = require("webmidi");
const { createProxyMiddleware } = require("http-proxy-middleware");
var cors = require("cors");
var bonjour = require("bonjour")();
const app = express();
const httpServer = createServer(app);
let servicePort = bonjour.find({ type: "gametime" }, function (service) {
console.log("Found an HTTP server:", service);
return service.port
});
// proxy middleware options
const options = {
target: `http://localhost:63695${servicePort}`, // target host
changeOrigin: true, // needed for virtual hosted sites
ws: true, // proxy websockets
};
// create the proxy (without context)
const proxyService = createProxyMiddleware(options);
// set cors
app.use(cors());
// route: forward all request to proxy service
app.use("/", proxyService);
httpServer.listen(9080);

Related

Unable to setup Express server on HTTPS

Trying to set up my Express server on HTTPS but unable to access my api. Here is my code:
// server.js
const express = require('express');
const { readFileSync } = require('fs');
const https = require('https');
const app = express();
const key = readFileSync(
'/etc/letsencrypt/live/mydomain.com/privkey.pem',
'utf8'
);
const cert = readFileSync(
'/etc/letsencrypt/live/mydomain.com/fullchain.pem',
'utf8'
);
const ca = readFileSync(
'/etc/letsencrypt/live/mydomain.com/chain.pem',
'utf8'
);
const credentials = { key, cert, ca };
const port = 443
const server = https.createServer(credentials, app);
server.listen(port, () => console.log(`Server is running on port ${port}`));
The error I am receiving is a 502 Bad gateway on all calls to the server.
Everything worked perfectly before when I was running on HTTP like this:
const server = app.listen(8000, () => {});
Beside the URL on my site I can see the padlock icon and it says my site is secure so I believe my certifcate is valid.
Have seen a lot of similar questions posted on here and followed what I've seen in responses. I've even asked chatGPT to check my code and it doesn't see any errors. I've also tried reading my SSL keys as .env variables so I don't think the issue is an incorrect file path.
Can anybody please help me find the solution?
EDIT
Here is an example of a get request I am making to my backend using axios:
const fetchMembers = async () => {
await axios
.get(`/api/total-users`)
};
This invokes a function totalUsers with express.Router from a users file in my routes folder on the backend:
// routes/users.js
const express = require('express');
const router = express.Router();
router.get('/total-users', totalUsers);
const totalUsers = async (req, res) => {
try {
const total = await User.find().estimatedDocumentCount();
res.json(total);
} catch (err) {
console.log(err);
}
};
I am using a middleware app.use with a prefix /api and importing the users file to make a connection to my endpoints:
// server.js
const userRoutes = require('./routes/users')
app.use('/api', userRoutes)
While editing this question I tried modifying the middleware prefix to `:443/api' however this still hasn't helped.
Where is User defined inside of routes/users.js? You need to import your DB models before accessing them like this:
const total = await User.find().estimatedDocumentCount();
Otherwise, generally when running fetch('/api...), React will try to access localhost:3000/api instead of localhost:443/api.
React needs to know where to proxy requests to the backend. One way is using the http-proxy-middleware library and by defining a setupProxy.js file.
client/src/setupProxy.js
/**
* Proxy most calls to the server
* #type {Array}
*/
/* eslint-disable #typescript-eslint/no-var-requires */
const { createProxyMiddleware } = require('http-proxy-middleware');
const proxy_urls = ['/api/*';
const target = 'https://localhost:443';
module.exports = function (app) {
proxy_urls.forEach((url) => {
app.use(url, createProxyMiddleware({ target }));
});
};

Socket.io - How to check message size before receiving it, And reject if it's bigger than 1MB?

I'm new to Socket.io
I'm programming an online browser game in Node.JS with a chat application
And I want to limit the message size to 1MB and reject if it's bigger than that
This is my code:
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server, { cors: { origin: "*" } });
const PORT = process.env.PORT || 3001;
const cors = require("cors");
// ... some code ...
io.on('connection', (socket) => {
// ... some code ...
socket.on("chat-message", message => {
// I did something like this:
if (message.length > 1000000) return;
});
});
But the server keeps receiving the message even if it's 100MB
I want to reject it before receiving the whole message
where you create your socket server use the "maxHttpBufferSize" property to set the maximum message size, you can do it like this:
const express = require('express');
const http = require('http');
const { Server } = require("socket.io");
const app = express();
const server = http.createServer(app);
// here, we have set the maximum size of the message to 10
// which you can see using the ".length" property on the string
const socketServer = new Server(server, {
maxHttpBufferSize: 1e1
});
const port = 9000;
server.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
but there is one down to it. messages bigger than the size limit are not recieved by the server.
hope this helps you

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.

Server side or Clint side API call?

If you're working with React.js, what is the best way to make an API call? For example, if I'm trying to get some book data from google books API should I do this on the client side with React.js or on the server side. Why would it be better to do it on one side vs the other? Thanks.
You can do something like this.
const express = require('express');
const app = express();
const path = require('path');
const fs = require('fs');
const proxy = require('http-proxy-middleware');
app.use(
'/api',
proxy({
target: 'http://api.books.com',
changeOrigin: true,
ws: true,
pathRewrite: { '^/api': '' },
})
);
const index = fs.readFileSync(path.resolve('./build', 'index.html'), { encoding: 'utf-8' });
app.get('*', (req, res) => {
res.contentType('text/html').send(index);
});
const server = app.listen(3000, function() {
const host = server.address().address;
const port = server.address().port;
console.log('The server is running at http://%s:%s/', host, port);
});
And call like this (throw proxy), to not have problems with CORS or to replace server after.
fetch('/api/get-books')

Enabling HTTPS on an express server

I'm trying to configure my express server to use HTTPS but I am running into some issues. I followed the documentation to setup my HTTPS server but I am still encountering some errors.
Here's my app.js
var express = require('express');
var app = express();
var server = require('https').createServer(options, app);
var io = require('socket.io')(server);
var port = process.env.PORT || 3000;
var fs = require('fs');
var options = {
key: fs.readFileSync('/test/key.pem'),
cert: fs.readFileSync('/test/cert.pem')
};
server.listen(port, function () {
console.log('Server listening at port %d', port);
});
When starting my server I encounter
https.js:32
if (process.features.tls_npn && !opts.NPNProtocols) {
^
TypeError: Cannot read property 'NPNProtocols' of undefined
at new Server (https.js:32:40)
at Object.exports.createServer (https.js:56:10)
So, I tried to define NPNProtocols within options, but that did not work. Anyone have any pointers here?
Thank you.
try this once, i think you should have certificate in .crt format. and you will require tls module.
var sslOptions = {
key: fs.readFileSync('public/server.key'),
cert: fs.readFileSync('public/server.crt')
};
tls.createServer(sslOptions, function (cleartextStream) {
var cleartextRequest = net.connect({
port: port,
host: serverStr
}, function () {
cleartextStream.pipe(cleartextRequest);
cleartextRequest.pipe(cleartextStream);
});
}).listen(443);
port is you http port . and sercerStr is you server address.
IMO, the issue is not with the extension of the keys, rather the ssl configuration used. Use https node module with correct ssl options for ca, cert, and key to enable https with express.
// server/index.js
const express = require('express');
const fse = require('fs-extra');
const helmet = require('helmet');
const https = require('https');
const path = require('path');
// path to cert files
const paths = {
certFile: '/path/to/cert.pem',
chainFile: '/path/to/fullchain.pem',
privateFile: '/path/to/privkey.pem',
};
/* Express implementation (ignore) */
const app = express();
app.use(helmet());
app.use(express.static(path.join(__dirname, '..')));
app.get('/', (request, response) => {
response.sendFile(path.join('index.html'));
});
// setup https
const setupHttps = () => {
const promises = [
fse.readFile(paths.chainFile),
fse.readFile(paths.privateFile),
fse.readFile(paths.certFile),
];
return Promise
.all(promises)
.then(data => {
const [ chainData, privateData, certData ] = data;
const options = {
ca: chainData.toString('utf-8'),
cert: certData.toString('utf-8'),
key: privateData.toString('utf-8'),
};
return https.createServer(
options,
app
).listen(443);
})
.catch(err => console.log(err));
};
return setupHttps();
EDIT: I used helmetjs for better security with http headers.

Categories