simple-wsgi

Creates a webserver for development or production. Bring your own application!

Usage no npm install needed!

<script type="module">
  import simpleWsgi from 'https://cdn.skypack.dev/simple-wsgi';
</script>

README

Simple WSGI server for NodeJS

WSGI stands for Web Server Gateway Interface. It's a common pattern in Python web development, essentially you decouple the code that starts the web server from the application code that actually handles the incoming requests (and everything else your application does). That way you can easily deploy the same application tailored to different environments (providing that environment has a WGSI server available for it).

Unfortunately the NodeJS world has yet to catch up with this pattern. But the good news is that it's not hard to implement - and the better news is that it's not hard to modify existing projects to use this pattern!

Todo: Add yargs for port etc

// app.js

module.exports = function main(req, res) {
    res.end(`This is my WSGI application!`);
}
// server.js

module.exports = function startServer(application) {
    http.createServer(application, ()=>console.log('This is my WSGI server!'));
}

// Optional: Allow command line usage
if(require.main === module) {
    startServer(require(process.argv[2]));
}

Wow, two really simple interfaces! How do they combine?

// This is how they work together in a script!
const startServer = require('./server.js');
const main = require('./app.js');

startServer(main);
# This is how they work together on the command line!

node server.js ./app.js

This is the de-facto WSGI API for NodeJS (although it's not usually called that by name). It comes from Node's http.createServer function. The vast majority of NodeJS web applications at some point create a callback that is passed to this function. If we make all of our web server applications compatible with this function anyway, why not factor out the server setup to a separate library?

Maybe a library such as this one.

How to use this library

This library provides WSGI servers for two environments: Development and "Production". Actually the production server is quite naïve, it just starts up a cluster and runs the application on each worker.

First you need to make sure you are exporting a function that accepts the Request and Response arguments, as in the example.

Now you can start your server:

// Import the wsgi server
const startServer = require('simple-wsgi');

// Import the wsgi application
const app = require('./application.js');

// We automatically detect wherther the environment is dev or production
// by checking the NODE_ENV env variable
const port = 3000;
startServer(app, port);

The port argument is optional, it defaults to process.env.PORT if present, otherwise to 8080 on development and 80 on production.

Alternatively we can be explicit about which environment we want to use:

startServer.production(app);
startServer.development(app);

More fun things you can do

Once you have a lot of applications using this interface you can start to do some interesting things. Like having multiple distinct applications under different domain names listening on the same port. Take a look at this:

const applicationA = require('app-a');
const applicationB = require('app-b')({ example: 'Maybe this app takes some config' });

module.exports = function multiSite(req, res){
    switch(req.getHeader('host')) {
        case 'pokemon-red-cheat-codes.example':
            return applicationA(req, res);
        case 'family-recipes.example.com':
            return applicationB(req, res);
        default:
            res.end(`I'm not sure what you're looking for. We only have cheat codes and recipes.`);
            return;
    }
}

if(require.main === module) {
    require('simple-wsgi')(multiSite);
}

Isn't that better than writing another Apache/Nginx config? Well I think it is.

Questions

What about config options?

It's true, this pattern doesn't have the full capabilities of the Python WSGI specification. But I think for people to start adopting the WSGI pattern it needs to be familiar and easy to use. That said, there's already a de-facto standard of using environment variables for configuration. Try that! Once multiple WSGI servers start becoming available perhaps we can come to a consensus on how to handle config and other extras. Until then......... sorry!

I think I have an idea that would make this better?

Wow, I'd love to hear it! We are stronger when we work together and share our ideas! Please let me know your thoughts in an issue, or contact me by my contact details on mrkiddle.co.uk

You know someone else has already done the same thing?

What, exactly the same? I didn't know that! If I knew that I wouldn't have done it myself. Please let me know who!