@alvitrjs/server v1.0.3
If you want to create one or multiple node servers the easy way.
A package that creates a configurable http and/or https servers so you can also load balance and cluster them.
If you do not want to do this:
// httpApp.ts
import http from 'http';
const server = http.createServer(function(req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
});
export default server;
// httpsApp.ts
import https from 'http';
import fs from 'fs';
const options = {
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.cert')
};
const server = https.createServer(options, function(req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
});
export default server;
// server.ts
import cluster from 'cluster';
import os from 'os';
import httpServer from './httpApp';
import httpsServer from './httpsApp';
const numCores = os.cpus().length;
if (cluster.isMaster) {
for (let i = 0; i < numCores; i++) {
cluster.fork();
}
cluster.on('exit', () => {
cluster.fork();
})
} else {
httpServer.listen(80);
httpsServer.listen(443);
}
Do this:
// server.ts
import fs from 'fs';
import Server from '@alvitrjs/server';
import Servers from '@alvitrjs/server/Servers';
import Cluster from '@alvitrjs/server/Cluster';
const httpServer = new Server(80, (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
});
const httpsServer = new Server(443, (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}, {
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.cert'),
});
const serverObjects = {
httpServer,
httpsServer
}
const servers = new Servers(serverObjects);
new Cluster({
numCores: Cluster.howManyCores(),
restartOnExit: true
}, servers).start();
Getting Started
Prerequisites
- NodeJS : >= 10.16.1
- NPM : >= 6.9.0
On Windows go to NodeJS and download the LTS version, execute and that is it!
On Ubuntu you can install via NodeSource:
curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
sudo apt install nodejs
On MacOS you can install via brew:
brew install node
Or you can go to NodeJS and download the LTS version, execute and that is it!
Instalation
You can use NPM or Yarn to install Server
npm i --save @alvitrjs/server
yarn add @alvitrjs/server
Usage
Using Typescript
import fs from 'fs';
import Server from '@alvitrjs/server';
import Servers from '@alvitrjs/server/Servers';
import Cluster from '@alvitrjs/server/Cluster';
const httpServer = new Server(80, (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}, undefined , 'localtest.test');
const httpsServer = new Server(443, (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}, {
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.cert'),
} , 'localtest.test');
const servers = new Servers();
servers.addServer('httpServer', httpServer);
servers.addServer('httpsServer', httpsServer);
new Cluster({
numCores: 8,
restartOnExit: true
}, servers).start();
Using Javascript
const fs = require('fs');
const Server = require('@alvitrjs/server');
const Servers = require('@alvitrjs/server/Servers');
const Cluster = require('@alvitrjs/server/Cluster');
const httpServer = new Server(80, (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}, undefined , 'localtest.test');
const httpsServer = new Server(443, (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}, {
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.cert'),
} , 'localtest.test');
const servers = new Servers();
servers.addServer('httpServer', httpServer);
servers.addServer('httpsServer', httpsServer);
new Cluster(servers, {
numCores: 8,
restartOnExit: true
}).start();
Table of Contents
Server
The server class is made so you can both create http and https servers and customize it.
import path from 'path';
import fs from 'fs';
import Server from '@alvitrjs/server';
// HTTP Server
const httpServer = new Server(80, (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}).start();
// HTTPS Server
const httpsServer = new Server(443, (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}, {
key: fs.readFileSync(path.join(path.resolve(__dirname), 'server.key')),
cert: fs.readFileSync(path.join(path.resolve(__dirname), 'server.cert')),
}).start();
Customize
You can customize your server by passing to its constructor parameters. Server accepts: port, requestListener, options, host and cbListen.
const httpServer = new Server(80, (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}, {
IncomingMessage: CustomIncommingMessage,
ServerResponse: CustomServerResponse
}, 'server.test', () => {console.log('listening')}).start();
To create an https server you need to pass both a valid server key and certificate
const httpsServer = new Server(80, (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}, {
key: fs.readFileSync(path.join(path.resolve(__dirname), 'server.key')),
cert: fs.readFileSync(path.join(path.resolve(__dirname), 'server.cert')),
IncomingMessage: CustomIncommingMessage,
ServerResponse: CustomServerResponse
}, 'server.test', () => {console.log('listening')}).start();
You can change any of those parameters before starting the server by accessing its public property.
const httpsServer = new Server(80, (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}, {
key: fs.readFileSync(path.join(path.resolve(__dirname), 'server.key')),
cert: fs.readFileSync(path.join(path.resolve(__dirname), 'server.cert')),
IncomingMessage: CustomIncommingMessage,
ServerResponse: CustomServerResponse
}, 'server.test', () => {console.log('listening')});
httpsServer.port = 443;
httpsServer.requestListener = (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World From Https Server\n');
};
// This will create an https server with port 443 and the requests will end with "Hello World From Https Server".
httpsServer.start();
You can check what you can pass to options at http.ServerOptions and tls.TlsOptions.
Extending IncomingMessage and ServerResponse
By default Server will be using http.IncommingMessage for Request and http.ServerResponse for Response. But you can change this behaviour by setting an extended request and response classes.
They will be used as the injected arguments to the requestListener.
class CustomIncommingMessage extends http.IncomingMessage {};
class CustomServerResponse extends http.ServerResponse {};
const httpServer = new Server(80, (req, res) => {
// req will be an instance of CustomIncommingMessage, and res an instance of CustomServerResponse
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}, {
IncomingMessage: CustomIncommingMessage,
ServerResponse: CustomServerResponse
}, 'server.test').start();
Servers
If you want to load balance servers or simple want to have two different servers running, you should use the Servers class.
import Server from '@alvitrjs/server';
import Servers from '@alvitrjs/server/Servers';
const httpServer = new Server(80, (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}, undefined , 'localtest.test');
const httpServer2 = new Server(81, (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}, undefined , 'localtest.test');
const servers = new Servers({
httpServer,
httpServer2
}).start();
Adding new Servers
You can add your servers to be created by passing an object with name and Server to the constructor.
const servers = new Servers({
httpServer,
httpServer2
}).start();
You can also call addServer to add a new server to be started.
const servers = new Servers();
servers.addServer('http1', httpServer);
servers.addServer('http2', httpServer2);
All servers need to be named
Setting Prefix and Suffix
You can add a prefix or a suffix to all the servers hosts, by passing an options to the constructor. The prefix will be added to the start of the host of every server and a dot after. The suffix will be added to the end of the host of every server with a slash before.
const servers = new Servers({
httpServer,
httpServer2
}, {
prefix: 'en',
suffix: 'api'
}).start();
every server host will be: en.${host}/api in this case host will be: en.localtest.test/api
You can change options before starting the servers by accessing its public property.
const servers = new Servers({
httpServer,
httpServer2
}, {
prefix: 'en',
suffix: 'api'
});
servers.options = {
prefix: 'en2',
suffix: 'api2'
};
// host will be: en2.localtest.test/api2
servers.start();
Running Servers
After starting multiple servers, the result of start will be a RunningServers instance.
import Server from '@alvitrjs/server';
import Servers from '@alvitrjs/server/Servers';
const httpServer = new Server(80, (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}, undefined , 'localtest.test');
const httpServer2 = new Server(81, (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}, undefined , 'localtest.test');
const servers = new Servers({
httpServer,
httpServer2
}).start();
Getting an Instance
You can get your server instance by using its name, it will be an http.Server or https.Server instance.
Check NodeJS documentation about http.Server and https.Server
const httpServer = servers.getInstance('httpServer');
httpServer.on('connection', () => {
console.log('new connection');
})
Closing All Servers
If you need to stop all server you can call closeAll. You can also pass a callback to it, if you need to know when all connections are closed.
// It will start to close all conections, and servers.
servers.closeAll();
Cluster
By default Server and Servers are a single threaded, this isn't the best when your cpu can handle 8 cores. So you can create a cluster to fully use your machine.
Cluster accepts both Server and Servers.
import path from 'path';
import fs from 'fs';
import Server from '@alvitrjs/server';
import Servers from '@alvitrjs/server/Servers';
import Cluster from '@alvitrjs/server/Cluster';
const httpServer = new Server(80, (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}, undefined , 'localtest.test');
const httpsServer = new Server(443, (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}, {
key: fs.readFileSync(path.join(path.resolve(__dirname), 'server.key')),
cert: fs.readFileSync(path.join(path.resolve(__dirname), 'server.cert')),
} , 'localtest.test');
const servers = new Servers();
servers.addServer('httpServer', httpServer);
servers.addServer('httpsServer', httpsServer);
new Cluster(servers).start();
Number of Cores
By default cluster will use all machine cores, but you can change by passing an object as a second argument, with numCores with the number of cores you need.
new Cluster(servers, {
numCores: 8
});
Restart Fork on Exit
By default when a fork stops, it stops, but you can make it create a new fork when one dies, by passing an object as a second argument with restartOnExit to true.
new Cluster(servers, {
numCores: 8,
restartOnExit: true
});
You can change both options before starting the cluster by accessing its public property.
How Many Cores
If you want to know how many cores cluster will be using as default or the max your machine can run, you can call Cluster static method howManyCores.
const maxCores = Cluster.howManyCores();
How to Contribute
We at AlvitrJS would LOVE for you to contribute for our projects, we think that the more the merrier.
Please read our contribution guide lines for details on our code of conduct, and the process for submitting pull requests and issues to us.
In development
These are what I'm currently working on, and possible new features.
- Error Handling
- Events
- Socket.io Servers
- Realtime Events
- Running Servers Events
- Docker Integration for Load Balance
- PM2 for Clustering
- Performance
- Security
Authors
- Gustavo Fenilli - Owner - Gustavo Fenilli
You should also check the list of all the nice contributors who participated in this project.