I wanted to create a loop that creates HTTP servers in Node.JS, where it creates server1, server2, etc. as const's. My problem is that I cannot get it to create a new server with a specific name based on a var. This is what I have right now.
const http = require('http')
const server=new http.createServer(function(res,req){res.write('Hi');res.end()})
for (let i=1001;i<9999;i++){
if (i=8080||i==3000||) return; //I'm already using 8080, 3000, and I don't want to use less than 1000.
const server${i}=new http.createServer(function(res,req){res.write('Hi');res.end()})
}
Obviously the ${i} thing won't work,
One approach would be to create an array of servers, and push to it a server object like:
const servers = []
for (let i=1001;i<9999;i++){
servers.push({
name: `server${i}`,
server: new http.createServer(function(res,req){res.write('Hi');res.end()})
})
}
now to access a specific server you could do servers.find(s => s.name === 'server999')?.server
Related
I create a TCP IVP4 socket server in Node.js using the 'net' module, and it works great for almost all of my clients, but one client has an IP similar to (I won't disclose the real one):
180.190.154.97
but when they connect to my socket server and I console.log(socket.remoteAddress), the value is this:
180.190.193.2
Why would this be happening?
// Import dependencies
let net = require('net')
// Create socket server.
const SERVER = net.createServer(socketConnection)
function socketConnection(client) {
console.log(client.remoteAddress)
}
// Server code snippet
let SERVER_LISTEN_ADDRESS = '0.0.0.0'
if (Game.local) {
SERVER_LISTEN_ADDRESS = '127.0.0.1'
Game.port = 42480
}
SERVER.listen(Game.port, SERVER_LISTEN_ADDRESS, () => {
console.log('Listening on port ' + Game.port)
if (!Game.local)
postServer()
else
console.log('Running server locally.')
})
Expected result is that it should print their IPV4 value from a site like:
https://whatismyipaddress.com/
But instead it says something completely different.
The result shown by whatipmyaddress it is not always the public IP of the single host. It could be rather also the IP of the subnet or if there's a proxy the IP of the proxy server. The fact that the address differs by a few units suggests that those particular hosts are in a subnet where a NAT service is active, or protected by a proxy or where the router acts as a VPN to the outside, encapsulating and sending the message to the server. In this case probably the entire subnet is seen as a single host.
In case you're using Express, you may want to use request-ip package in order to retrieve the IP in a more robust way. Since it seems you're not using express you should implement something similar to the first example shown in the link. For your specific case according the code you give:
const requestIp = require('request-ip');
function socketConnection(client) {
const clientIp = requestIp.getClientIp(client);
console.log(client);
}
When starting an http server in Node.js, developers can listen on a randomly available port by passing 0 like so:
const http = require('http')
const service = require('../my/service);
const server = http.createServer(service)
server.listen(process.env.PORT || 0) // <-- Random port by default!
I wonder how I can do the same thing with gRPC? Something like...
const grpc = require('grpc')
const services = require('./service_grpc_pb')
const server = new grpc.Server()
server.addService(services.MyService, { ... })
server.bind('0.0.0.0:0', grpc.ServerCredentials.createInsecure())
server.start()
Does that work? I've yet to find out. My goal is to get a random port and then query the server to get the assigned port in order to register the service with a central microservice registry.
Thanks for your help in advance.
Yes, you can use a port number of 0 to assign a random port to a gRPC server. The server.bind method returns the port number that was actually assigned. If you want to use the bindAsync method instead, the assigned port number will be passed to the callback.
This question already has answers here:
How do I host multiple Node.js sites on the same IP/server with different domains?
(13 answers)
Closed 4 years ago.
I would like to create a system of multiple web applications (probably around 3-5 node.js + express applications) on one server. I also only have one domain. So I figured that I need to create subdomains for each of my application apart from the main one.
My question is - how do I redirect users coming to certain subdomains to the right application? Do I need to use virtual machines and then redirect each user to a different VM (ip address) depending on their subdomain? How would I even do that?
Or could I just run every application on the same server just with a different port number? Or is there any other way that I'm not really thinking of?
Which way would be the cleanest and how would I implement it?
A very common way to achieve this is to run each of your node servers on a different port, and then set up a reverse proxy like nginx to have it forward requests based on matching the host header of incoming HTTP requests.
You could of course handle this manually with node, by checking the host header yourself and forwarding each request to the proper node server on the associated port.
Here is some Node code which illustrates what I'm referring to:
const http = require('http')
const url = require('url')
const port = 5555
const sites = {
exampleSite1: 544,
exampleSite2: 543
}
const proxy = http.createServer( (req, res) => {
const { pathname:path } = url.parse(req.url)
const { method, headers } = req
const hostname = headers.host.split(':')[0].replace('www.', '')
if (!sites.hasOwnProperty(hostname)) throw new Error(`invalid hostname ${hostname}`)
const proxiedRequest = http.request({
hostname,
path,
port: sites[hostname],
method,
headers
})
proxiedRequest.on('response', remoteRes => {
res.writeHead(remoteRes.statusCode, remoteRes.headers)
remoteRes.pipe(res)
})
proxiedRequest.on('error', () => {
res.writeHead(500)
res.end()
})
req.pipe(proxiedRequest)
})
proxy.listen(port, () => {
console.log(`reverse proxy listening on port ${port}`)
})
Correct me if I am wrong, but it isn't possible to start multiple http-servers on the same port.
Based on this it is interesting the NodeJS cluster may fork. Of cause I know there is the master what is passing the request to one of the forked workers. What worker is managed by operating system or cluster.schedulingPolicy= "rr" for "round robin".
The point is: Every worker needs its own memory, so you need x-times much memory where x is the number of workers.
But if I like to run different (sub)domains out of my node app, I also like to hold different parts of an in_memory database (e.g. a simple JSON file) bound to a (sub)domain. OR based on resources like subdomain.example.tdl/resource1/whatever.
It doesn't seams to be possible. Either resource based nor domain based.
In my opinion it should be possible, because I can route based on request-objects (res.url) and resources (params) by different existing middleware.
So that way it should be possible to tell the master to pass the request to a specific forked instance.
It's possible: you need create net server at master, and pass connection by you rules to workers http server:
var cluster = require('cluster');
if (cluster.isMaster) {
var workers = [];
// Create workers
for (var i=0; i<require('os').cpus().length; i++) {
workers[i] = cluster.fork({WORKER_INDEX:i, JSON_INDEX:i});
}
// Create net server at master
var server = require('net').createServer({pauseOnConnect:true}, function(c) {
var b = Math.floor( Math.random()*workers.length );
workers[b].send("doit",c);
}).listen(3000);
} else {
// Load specific data for worker (pass parametr JSON_INDEX)
var json = "{default:default}";
try {
json = require("fs").readFileSync('./data_'+process.env.JSON_INDEX+'.json');
} catch (e) {}
// Create http server and pass specific json to client
var server = require('http').createServer( function(req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(json);
}).listen(0,'127.0.0.1');
// Get message from master and check if need pass to http server
process.on('message', function(m,c) {
if ( "doit" === m ) {
server.emit('connection', c);
c.resume();
}
});
}
I'm trying to implement a TCP proxy in Node JS. I only have some experience with Javascript so I met a lot of problems along the way. I've done a lot of searching for this one but had no luck.
The problem occurs when browser sends a CONNECT request for HTTPS. My proxy will parse the host name and port, and then create a new socket that connects to the server. If all these steps went well, I will start forwarding message.
Part of my code looks like this:
var net = require('net');
var server = net.createServer(function(clientSock) {
clientSock.on('data', function(clientData) {
var host = // get from data
var port = // get from data
if (data is a CONNECT request) {
// Create a new socket to server
var serverSock = new net.Socket();
serverSock.connect(port, host, function() {
serverSock.write(clientData);
clientSock.write('HTTP/1.1 200 OK\r\n');
}
serverSock.on('data', function(serverData) {
clientSock.write(serverData);
}
}
}
}
Since the CONNECT request needs both client socket and server socket open until one side closes the connection, the code above doesn't have this behavior. Every time I receive some data from client, I will create a new socket to server and the old one is closed.
Is there a way to store the server socket as a global variable so that the data event handler can reuse it? Or is there any other way to solve this?
Thanks a lot!!!!
You can just move the variable up to a higher scope so it survives across multiple events and then you can test to see if its value is already there:
var net = require('net');
var server = net.createServer(function(clientSock) {
var serverSock;
clientSock.on('data', function(clientData) {
var host = // get from data
var port = // get from data
if (data is a CONNECT request) {
// Create a new socket to server
if (!serverSock) {
serverSock = new net.Socket();
serverSock.connect(port, host, function() {
serverSock.write(clientData);
clientSock.write('HTTP/1.1 200 OK\r\n');
}
serverSock.on('data', function(serverData) {
clientSock.write(serverData);
}
} else {
serverSock.write(clientData);
}
}
}
}