Helps you to compose a single http server program from multiple constituent server programs (http or not).
MIT License
Helps you to compose a single http server program from multiple constituent server programs (http or not).
Given a declarative configuration, including a description of a collection of constituent servers
, it will:
Define your composite server in a script like this one...
// composite.js
const { startCompositeServer } = require('composite-http-server')
startCompositeServer({
defaultPort: 3000,
servers: [
{
label: 'my-service',
command: 'node my-service/server.js',
port: 3001,
httpProxyPaths: ['/api/my-service'],
},
{
label: 'web',
command: 'node web/server.js',
port: 3002,
httpProxyPaths: ['/'],
httpProxyOptions: {}
},
],
})
Run it...
$ node composite.js
Starting server 'my-service'...
Starting server 'web'...
my-service | [out] Started 🚀
web | [out] Started 🚀
Started server 'web' @ http://localhost:3002
Started server 'my-service' @ http://localhost:3001
Starting server '$proxy'...
Started server '$proxy' @ http://localhost:3000
Ready
Now you have an http server running at http://localhost:3000 which proxies requests to either of two underlying "constituent" servers:
/api/my-service
go to "my-service"/
go to "web"httpProxyPaths
, if it is meant to be used only by other constituent servers and not accessible via the http proxy.This describes behavior which is expected of the constituent servers you define, and which you can expect of the composite server.
PORT
environment variableconfig.printConfig
(type: boolean
; optional; default: false
) If set to true
, the effective configuration will be printed before starting the composite server. Useful for debugging dynamic configurations.config.defaultPort
(type: number
; optional; default: 3000
) Default port on which to start the composite server. This is only used if the PORT
environment variable is not defined.config.httpProxyOptions
(type: HttpProxyOptions
; optional; default: {}
) http-proxy-middleware options (without target
or router
) to be used when proxying to any of the described servers
. You can also set these options per-server with config.servers[].httpProxyOptions
.config.servers[]
(required) Description of constituent servers. Must contain one or more elements.config.servers[].label
(type: string
; optional; default: server's index in the array) Symbol used to identify this server.config.servers[].env
(type: object
; optional; default: {}
) Environment variables to define for this server's process. It will already inherit all the environment variables of it's parent (the composite server process), so there's no need to explicitly propagate environment variables in your configuration. The constituent server process will also already have PORT
defined appropriately.config.servers[].command
(type: string | string[]
; required) Command used to run the server. If it's a single string, it will be parsed into binary and argument strings. If it's an array of strings, the first element is the binary, and the remaining elements are the arguments. The server should behave according to "Specs for generic 'http server program'" (above).config.servers[].host
(type: string
; optional; default: 'localhost'
) Hostname that this server can be expected to start on.config.servers[].port
(type: number
; required) Port number that this server can be expected to start on. This is passed to the constituent server process as the PORT
environment variable.config.servers[].httpProxyPaths
(type: string[]
; optional; default: []
) Absolute paths to check when determining which server to proxy an http request to. Each request is proxied to the first server that has a path that the request path is within.config.servers[].httpProxyOptions
(type: HttpProxyOptions
; optional; default: {}
) http-proxy-middleware options (without target
or router
) to be used for the http proxy to this server. You can also set these options globally with config.httpProxyOptions
.Sometimes we may want to use some open-source (or just reusable) http server as a component of our app or service. If we are thinking of that server as a component of our overall server, then we might want to include it in our overall server, rather than deploying it as its own independent service.
Advantages of the "single server" (or "monolith") approach:
There some real advantages of the "multiple servers" (or "microservices") approach too, which you should research for yourself. I think you will find that these benefits generally apply more to large-scale projects with many services, and maybe multiple teams. For smaller projects, it seems that the "single service" approach provides more advantage. Bear in mind that serious projects can often benefit from starting out small, and splitting out into separate services only as needed.
If you are unable build everything into a single http server program running as a single process type (by calling the server code from your own code) for whatever reason (maybe the constituent server is written in a different language than the rest of the project, maybe its source code is not available, maybe something else) then you can use composite-http-server to build everything into a single http server program running multiple process types internally.
npm-run-path
packagestart
)
servers[].port
proc
, don't wait whole time for proc to have exited
httpProxyPaths
httpProxyPaths
server[].httpProxyOptions
config.server[].handleExit
'exit', 'restart', or function. Default 'exit' (which is only current behavior)config.server[].startupTimeout
milliseconds to wait for port to open before timeout error (currently it waits basically forever)$proxy
serverconfig.server[].forceKillTimeout
option (milliseconds to wait before sending SIGKILL)config.server[].scale
config.server[].dependencies
: array of labels of servers to wait for to be ready before starting this serverv2.0.0
v1.1.0
v1.0.0