Monument Versions Save

event based http server for nodejs

v2.3.3

8 years ago

This release also covers v2.2.3, v2.1.2

A bug was discovered that caused Content Security Policy generation to crash the server if CSPs were set as strings in the security config object instead of as an array of values. This is now corrected. The real problem was that this lacked documentation, and so was something that caused real world problems.

Now either arrays of options, or strings containing the options are supported.

This crash also only happened if someone using a version of Firefox between 4 and 23 visited the site in question and the site was using 'unsafe-inline' in its styleSrc directive.

v2.3.0

8 years ago

v2.3.0

The big enhancement for Liège–Bastogne–Liège (2.3.0) is the addition of file upload handling courtesy of busboy. The handling is essentially the same as it used to be but using busboy means that the form handling now appropriately handles file upload fields.

New form handling information

The files that are uploaded are sent to the OS's temp file directory and the object that contains the references to them looks like this:

{
    "file1": {
        "tempFile": "/tmp/some/file.jpg"
        , "mimetype": "image/jpg"
        , "file": //this is the file stream
        , "encoding": "UTF-8"
    }
}

It also welcome some new contributors with their first commits to the project! Welcome Kelly Innes and Adrian Bobev! Contributor 4 and 5 respectively.

The last real notable change is the addition of some more information around contributing in the contributing.md file. That's it. Not a whole ton of stuff this time around.

v2.2.1

8 years ago

2 days ago ws released a fix for a security vulnerability (https://github.com/websockets/ws/releases/tag/1.0.1). This patch release upgrades to the non-vulnerable version of ws.

If you are using 2.2.0 with Web Sockets then you should update asap.

v2.2.0

8 years ago

v2.2.0

The main focus of this release is expanding the available protocol stack that monument can use to communicate. It adds a builtin Web Socket server and the ability to drop in any http-like server that adheres to the API made popular by the builtin http and https modules. This includes spdy and http2!

Config changes:

Current state of the config object is right below this. Explanations about the new items in the server section of the config is below.

{
    port: 3000 // the port for the server to run on
    , compress: true // turns on or off compression for static files (deflate/gzip)
    , routePath: './routes' // the folder your routes live in
    , templatePath: './templates' // the folder where your templates live
    , dotjs: {
        //dotjs defaults
        // see [doT.js documentation](https://olado.github.io/doT/index.html) for available options.
    }
    , publicPath: './public' // the folder where your static files live
    , maxAge: 31536000 // time to cache static files client side in milliseconds
    , etags: true // turns on or off etag generation and headers
    , security: {
        xssProtection: true //default, can be set to false to disable
        , poweredBy: 'bacon' //the default is blank can be any string
        , noSniff: true //default, can be set to false to disable
        , frameguard: {
            action: 'SAMEORIGIN' //the default allows iframes from same domain
            , domain: '' //defaults to not used. Only used for 'ALLOW-ORIGIN' 
        }
        , hsts: {
            maxAge: 86400 // defaults to 1 day in seconds. All times in seconds
            , includeSubDomains: true // optional. Defaults to true
            , preload: true // optional. Defaults to true
        }
        , noCache: false // defaults to off. This is the nuclear option for caching
        , publicKeyPin: { // default is off. This one is complicated read below...
            sha256s: ['keynumberone', 'keynumbertwo'] // an array of SHA-256 public key pins see below for how to obtain
            , maxAge: 100 // time in seconds for the pin to be in effect
            , includeSubdomains: false // whether or not to pin for sub domains as well defaults to false
            , reportUri: false // whether or not to report problems to a URL more details below. Defaults to false
            , reportOnly: false // if a reportURI is passed and this is set to true it reports and terminates connection
        }
        , contentSecurity: {
            defaultSrc: `'self'` // optional. This is the default setting and is very strict
        }
    }

    // Web Sockets is new for this release!
    , webSockets: false // default setting disables websockets. can be (false, true, 'passthrough', 'data')

    // Server and ServerOptions are new for this release!
    , server: spdy
    , serverOptions: { // anything set in this object will be passed to the server
        key: fs.readFileSync('./server.key')
        , cert: fs.readFileSync('./server.crt')
        , ca: fs.readFileSync(./ca.pem)
    }
}

Web Sockets

Web Sockets are awesome and generally pretty straightforward. monument does have some opinions about how to handle them and the settings allow for quite a bit of flexibility when it comes down to it so let's take a deep dive into working with them. If you aren't familiar with how web sockets work the HTML5 rocks article is a good place to start.

Web Sockets allow a low latency, low overhead two-way connection between youe client and server. It dramatically reduces the overhead of normal connections, by staying open and by not involving the transmission of headers with every piece of data. They are pretty fantastic.

The idea of events or messages in Web Sockets meshes very well with monument's own concept of events so it seems like a natural fit here.

Settings

There are four possible settings for web socket config.

  • false which turns off the web socket server
  • true which turns it on with data and passthrough style handling enabled
  • data which turns on the server but only for data style handling
  • passthrough which turn on the server but only for passthrough style handling

Any other value passed to the config.webSocket will be treated as true turning on the server for both handlings. The default setting is false.

For more information check out the web sockets documentation.

spdy and http2

monument now ships with support for running a variety of different server types and protocols. At the top of the list is http2/spdy! One of many nice features is the ability to push multiple assets to users over the same connection. Now you can get that in monument.

For local use the simplest way to go is generating a self signed certificate. Your browser will complain about it, but you will still be able to test everything and do your development without buying an actual certificate.

Heroku has a great writeup on the process that will get you up and running. If you are using the spdy module then you will need to create a CA as well. Once you have a cert generated in the root of your new monument project you will need to setup your server config appropriately. Your new app.js file should look something like this:

'use strict';

const monument = require('monument')
    , defaultPort = 4000
    , spdy = require('spdy')
    , fs = require('fs');

monument.server({
    routePath: './routes'
    , templatePath: './templates'
    , publicPath: './public'
    , port: process.env.PORT || defaultPort
    , security: {
        contentSecurity: false
    }
    , webSockets: true

    , server: spdy
    , serverOptions: {
        key: fs.readFileSync('./server.key')
        , cert: fs.readFileSync('./server.crt')
        , ca: fs.readFileSync(./ca.pem)
    }
});

For more information including the documentation for connection.res.push.

UUID generator

We added a V4 UUID generator to monument (require('monument').createUUID). It's handy for dealing with data and lots of other things. It was mostly added for use when creating new data through events.

isUndefined

If you are working on the core of monument you now have a utils.isUndefined function for checking if a value is undefined. Handy and simplified a lot of the code in the server.

Code Climate

We added Code Climate checks to the project!

Cleans up bugs in testing

There were some bugs in the unit tests that manifest themselves once we started testing with multiple types of servers for the http2/spdy stuff. These bugs were fixed and the tests now hum along nicely.

Tons of documentation

There is a lot more documentation now and it is much more in depth!

v2.1.0

8 years ago

v2.1.0

This is a big release that improves the security of the app server in lots of ways. Basically all the protection of helmet and express as defaults without a separate library.

Config changes:

Current state of the config object is right below this. Explanations about the new items in the security object are explained in more depth below. Most of the settings in security turn headers on and off, and documentation around those headers can be found on OWASP and n helmet and its source code. Much of the code here is inspired by helmet.

{
    port: 3000 // the port for the server to run on
    , compress: true // turns on or off compression for static files (deflate/gzip)
    , routePath: './routes' // the folder your routes live in
    , templatePath: './templates' // the folder where your templates live
    , dotjs: {
        //dotjs defaults
        // see [doT.js documentation](https://olado.github.io/doT/index.html) for available options.
    }
    , publicPath: './public' // the folder where your static files live
    , maxAge: 31536000 // time to cache static files client side in milliseconds
    , etags: true // turns on or off etag generation and headers

    //the security object is brand new in this release
    , security: {
        xssProtection: true //default, can be set to false to disable
        , poweredBy: 'bacon' //the default is blank can be any string
        , noSniff: true //default, can be set to false to disable
        , frameguard: {
            action: 'SAMEORIGIN' //the default allows iframes from same domain
            , domain: '' //defaults to not used. Only used for 'ALLOW-ORIGIN' 
        }
        , hsts: {
            maxAge: 86400 // defaults to 1 day in seconds. All times in seconds
            , includeSubDomains: true // optional. Defaults to true
            , preload: true // optional. Defaults to true
        }
        , noCache: false // defaults to off. This is the nuclear option for caching
        , publicKeyPin: { // default is off. This one is complicated read below...
            sha256s: ['keynumberone', 'keynumbertwo'] // an array of SHA-256 public key pins see below for how to obtain
            , maxAge: 100 // time in seconds for the pin to be in effect
            , includeSubdomains: false // whether or not to pin for sub domains as well defaults to false
            , reportUri: false // whether or not to report problems to a URL more details below. Defaults to false
            , reportOnly: false // if a reportURI is passed and this is set to true it reports and terminates connection
        }
        , contentSecurity: {
            defaultSrc: `'self'` // optional. This is the default setting and is very strict
        }
    }
}

poweredBy

You can set this value to whatever you want it to look like your server is powered by. By default it is off and the server does not return the X-Powered-By header. This is more secure then specifying it so we receommend you leave this alone, but since you are an adult you are free to set a value here. Any string passed here will become the value of the X-Powered-By header.

xssProtection

If set to false this turns off the X-XSS-Protection header for all browsers. This header is disabled in IE < 9 because it opens up vulnerabilities. In everything else it is enabled by default.

noSniff

If set to false this turns off the X-Content-Type-Options header for all browsers. This header prevents browsers from trying to infer mime type when a file with a mime type is downloaded. This helps prevent download related vulnerabilities and the misinterpretation of file types.

frameguard

Guard is a weird looking word. Not that we have that out of the way frameguard allows you to specify under what conditions your application may be wrapped in an iframe. Setting action: 'DENY' means that your site may never be wrapped in an iframe. The default is 'SAMEORIGIN' which allows wrapping of your site by essentially your app. The last allowed setting, action: 'ALLOW-ORIGIN', requires that you pass a domain value as well. It allows the specified domain to wrap your application in an iframe. All the calculations for SAMEORIGIN and ALLOW-ORIGIN follow the CORS rules for determining origin. So www.designfrontier.net and designfrontier.net are different origins.

hsts (HTTP Strict Transport Security)

This tells browsers to require HTTPS security if the connection started out as an HTTPS connection. It does not force the connection to switch, it just requires all subsequent requests by the page to use HTTPS if the page was requested with HTTPS. To disable it set config.security.hsts to false. It is set with a maxAge much like caching. The maxAge is set in seconds (not ms) and must be a positive number.

The two optional settings: includeSubDomains and preload are turned on by default. includeSubDomains requires any request to a subdmain of the current domain to be HTTPS as well. preload is a Google Chrome specific extension that allows you to submit your site for baked-into-the-browser HSTS. With it set you can submit your site to this page. Both of these can be individually turned off by setting them to false in the config object.

For more information the spec is available.

noCache

Before using this think long and hard about it. It shuts down all client side caching for the server. All of it. As best as it can be shut down. You can set it to an object {noEtag: true} if you want to remove etags as well. If you merely set it to true then all no cache headers will be set but the ETag header will not be removed.

There is now also a res.noCache function that allows you to do the same thing but on a per request/route/user (however you program it) basis. This is a much better option then setting noCache server wide.

publicKeyPin

This one is a bit of a beast. Before setting it and using it please read: the spec, this mdn article and this tutorial. It's a great security feature to help prevent man in the middle attacks, but it is also complex.

Enough of the warnings! How do you configure it? The config object above explains it pretty well. Some details about includeSubdomains: it pins all sub domains of your site if it is set to true. Turned off by setting it to false.

reportUri takes a URL and changes the header so that the browser can corretly handle the reporting of mismatches between pins and your certificate keys. If this is set without reportOnly being set to false then it only reports it does not also terminate the connection. Setting reportOnly to false means that the connection will be terminated if it does not match the pins as well as reporting.

If you specify a report URI it should be ready to recieve a POST from browsers in the form (described here)[https://tools.ietf.org/html/rfc7469#section-3]. The object you should expect looks like this (sourced from previous link):

{
    "date-time": date-time,
    "hostname": hostname,
    "port": port,
    "effective-expiration-date": expiration-date,
    "include-subdomains": include-subdomains,
    "noted-hostname": noted-hostname,
    "served-certificate-chain": [
        pem1, ... pemN
    ],
    "validated-certificate-chain": [
        pem1, ... pemN
    ],
    "known-pins": [
        known-pin1, ... known-pinN
    ]
}

contentSecurity

This is the Content Security Policy configuration. Content Security Policies are amazing and if you aren't familiar with them you should go read up on them. Firefox pioneered them a long time ago and they have become a powerful standard for protecting your end users.

Because of the extensive options available in configuring your CSP we recommend that you go take a look at the MDN article on directives. All of the options they spell out are supported. The directives need to be passed in camelCase though (defaultSrc not default-src).

The default is a very strict default-src 'self' which prevents any files from outside the current domain from being loaded and/or executed. You will probably want to ease that off a hair.

In the event that you don't want a Content Security Policy (why!? WHY!? Trust us you want one) you can disable it by setting config.security.contentSecurity to false in the config section of your server. This is not a good idea.

v2.0.0

8 years ago

originally discussed as 1.6.x Paris-Roubaix is 2.0.0 because of the shift to ES6. The actual API is stable from 1.5 to 2.0. But wanted a clear representation of the shift in required platform.