Browse Source

added koa support

Andi Dittrich 7 years ago
parent
commit
0569f8d651

+ 7 - 0
CHANGES.md

@@ -1,6 +1,13 @@
 CHANGELOG
 CHANGELOG
 ======================================================
 ======================================================
 
 
+Version 2.X.X
+------------------------------------------------------
+* Added [koa](http://koajs.com/) support
+* Added support for multiple http frameworks
+* Changed: **express.js** error handler is encapsulated within the `express()` function
+* Changed: moved middleware example to `examples/`
+
 Version 1.X.X
 Version 1.X.X
 ------------------------------------------------------
 ------------------------------------------------------
 
 

+ 1 - 1
LICENSE.md

@@ -1,6 +1,6 @@
 The MIT License (X11 License)
 The MIT License (X11 License)
 
 
-Copyright (c) 2014-2017 Andi Dittrich
+Copyright (c) 2014-2018 Andi Dittrich
 
 
 Permission is hereby granted, free of charge, to any person
 Permission is hereby granted, free of charge, to any person
 obtaining a copy of this software and associated documentation
 obtaining a copy of this software and associated documentation

+ 89 - 29
README.md

@@ -1,14 +1,23 @@
 [nginx](#nginx-integration) | 
 [nginx](#nginx-integration) | 
-[expressjs](#expressjs-integration) | 
 [Apache HTTPD](#apache-httpd-integration) | 
 [Apache HTTPD](#apache-httpd-integration) | 
 [Lighttpd](#lighttpd-integration) | 
 [Lighttpd](#lighttpd-integration) | 
+[express.js](#expressjs-integration) | 
+[koa.js](#koajs-integration) | 
 [Customization](#customization)
 [Customization](#customization)
 
 
 # Simple HttpErrorPages #
 # Simple HttpErrorPages #
-Simple HTTP Error Page Generator. Create a bunch of custom error pages - suitable to use with Lighttpd, Nginx, expressjs, Apache-Httpd or any other Webserver.
+Simple HTTP Error Page Generator. Create a bunch of custom error pages - suitable to use with Lighttpd, Nginx, expressjs, koajs ,Apache-Httpd or any other Webserver.
 
 
 ![Screenshot](https://raw.githubusercontent.com/AndiDittrich/HttpErrorPages/master/assets/screenshot1.png)
 ![Screenshot](https://raw.githubusercontent.com/AndiDittrich/HttpErrorPages/master/assets/screenshot1.png)
 
 
+## Features ##
+
+* Static pages (for webservers)
+* Multi-Language (i18n) support
+* Generator script to customize pages
+* Native [express.js](http://expressjs.com/) middleware
+* Native [koa.js](http://koajs.com/) middleware
+
 ## Demo ##
 ## Demo ##
 * [HTTP400](https://andidittrich.github.io/HttpErrorPages/HTTP400.html)
 * [HTTP400](https://andidittrich.github.io/HttpErrorPages/HTTP400.html)
 * [HTTP401](https://andidittrich.github.io/HttpErrorPages/HTTP401.html)
 * [HTTP401](https://andidittrich.github.io/HttpErrorPages/HTTP401.html)
@@ -72,6 +81,36 @@ server {
     }
     }
 ```
 ```
 
 
+## Apache Httpd Integration ##
+[Apache Httpd 2.x](http://httpd.apache.org/) supports custom error-pages using multiple [ErrorDocument](http://httpd.apache.org/docs/2.4/mod/core.html#errordocument) directives.
+
+File: `httpd.conf` or `.htaccess`
+
+Example - assumes HttpErrorPages are located into your **document root** `/var/www/...docroot../ErrorPages`.
+
+```ApacheConf
+ErrorDocument 400 /ErrorPages/HTTP400.html
+ErrorDocument 401 /ErrorPages/HTTP401.html
+ErrorDocument 403 /ErrorPages/HTTP403.html
+ErrorDocument 404 /ErrorPages/HTTP404.html
+ErrorDocument 500 /ErrorPages/HTTP500.html
+ErrorDocument 501 /ErrorPages/HTTP501.html
+ErrorDocument 502 /ErrorPages/HTTP502.html
+ErrorDocument 503 /ErrorPages/HTTP503.html
+```
+
+## Lighttpd Integration ##
+
+[Lighttpd](http://www.lighttpd.net/) supports custom error-pages using the [server.errorfile-prefix](http://redmine.lighttpd.net/projects/lighttpd/wiki/Server_errorfile-prefixDetails) directive.
+
+File: `lighttpd.conf`
+
+Example - assumes HttpErrorPages are located into `/var/www/ErrorPages/`.
+
+```ApacheConf
+server.errorfile-prefix = "/var/www/ErrorPages/HTTP"
+```
+
 ## expressjs Integration ##
 ## expressjs Integration ##
 
 
 HttpErrorPages are available as NPM-Package - just install `http-error-pages` via **npm/yarn**
 HttpErrorPages are available as NPM-Package - just install `http-error-pages` via **npm/yarn**
@@ -79,17 +118,17 @@ HttpErrorPages are available as NPM-Package - just install `http-error-pages` vi
 **Installation**
 **Installation**
 
 
 ```terminal
 ```terminal
-npm install http-error-pages --save
+yarn add http-error-pages
 ```
 ```
 
 
 **Example**
 **Example**
 
 
+A ready-to-use example can be found in [examples/express.js](exmaples/express.js)
+
 ```js
 ```js
 const _express = require('express');
 const _express = require('express');
 const _webapp = _express();
 const _webapp = _express();
-
-// use require('http-error-pages') for regular apps!
-const _httpErrorPages = require('./lib/error-handler');
+const _httpErrorPages = require('http-error-pages');
 
 
 async function bootstrap(){
 async function bootstrap(){
     // demo handler
     // demo handler
@@ -111,7 +150,7 @@ async function bootstrap(){
 
 
     // use http error pages handler (final statement!)
     // use http error pages handler (final statement!)
     // because of the asynchronous file-loaders, wait until it has been executed
     // because of the asynchronous file-loaders, wait until it has been executed
-    await _httpErrorPages(_webapp, {
+    await _httpErrorPages.express(_webapp, {
         lang: 'en_US',
         lang: 'en_US',
         footer: 'Hello <strong>World</strong>'
         footer: 'Hello <strong>World</strong>'
     });
     });
@@ -132,43 +171,64 @@ bootstrap()
 
 
 **Options**
 **Options**
 
 
-Syntax: `Promise _httpErrorPages(expressWebapp [, options:Object])`
+Syntax: `Promise _httpErrorPages.express(expressWebapp [, options:Object])`
 
 
 * `template` - the path to a custom **EJS** template used to generate the pages. default [assets/template.ejs](assets/template.ejs)
 * `template` - the path to a custom **EJS** template used to generate the pages. default [assets/template.ejs](assets/template.ejs)
 * `css` - the path to a precompiled **CSS** file injected into the page. default [assets/layout.css](assets/layout.css)
 * `css` - the path to a precompiled **CSS** file injected into the page. default [assets/layout.css](assets/layout.css)
 * `footer` - optional page footer content (html allowed). default **null**
 * `footer` - optional page footer content (html allowed). default **null**
 * `lang` - language definition which should be used (available in the `i18n/` directory). default **en_US**
 * `lang` - language definition which should be used (available in the `i18n/` directory). default **en_US**
 
 
-## Apache Httpd Integration ##
-[Apache Httpd 2.x](http://httpd.apache.org/) supports custom error-pages using multiple [ErrorDocument](http://httpd.apache.org/docs/2.4/mod/core.html#errordocument) directives.
+## koajs Integration ##
 
 
-File: `httpd.conf` or `.htaccess`
+HttpErrorPages are available as NPM-Package - just install `http-error-pages` via **npm/yarn**
 
 
-Example - assumes HttpErrorPages are located into your **document root** `/var/www/...docroot../ErrorPages`.
+**Installation**
 
 
-```ApacheConf
-ErrorDocument 400 /ErrorPages/HTTP400.html
-ErrorDocument 401 /ErrorPages/HTTP401.html
-ErrorDocument 403 /ErrorPages/HTTP403.html
-ErrorDocument 404 /ErrorPages/HTTP404.html
-ErrorDocument 500 /ErrorPages/HTTP500.html
-ErrorDocument 501 /ErrorPages/HTTP501.html
-ErrorDocument 502 /ErrorPages/HTTP502.html
-ErrorDocument 503 /ErrorPages/HTTP503.html
+```terminal
+yarn add http-error-pages
 ```
 ```
 
 
-## Lighttpd Integration ##
-
-[Lighttpd](http://www.lighttpd.net/) supports custom error-pages using the [server.errorfile-prefix](http://redmine.lighttpd.net/projects/lighttpd/wiki/Server_errorfile-prefixDetails) directive.
+**Example**
 
 
-File: `lighttpd.conf`
+A ready-to-use example can be found in [examples/koa.js](exmaples/koa.js). 
+Keep in mind that the following example has to be executed within an async context!
 
 
-Example - assumes HttpErrorPages are located into `/var/www/ErrorPages/`.
+```js
+const _koa = require('koa');
+const _webapp = new _koa();
+const _httpErrorPages = require('http-error-pages');
+
+// use http error pages handler (INITIAL statement!)
+// because of the asynchronous file-loaders, wait until it has been executed - it returns an async handler
+_webapp.use(await _httpErrorPages.koa({
+    lang: 'en_US',
+    footer: 'Hello <strong>World</strong>'
+}));
+
+// add other middleware handlers
+_webapp.use(async (ctx, next) => {
+    if (ctx.path == '/'){
+        ctx.type = 'text';
+        ctx.body = 'HttpErrorPages Demo';
+    }else{
+        return next();
+    }
+});
 
 
-```ApacheConf
-server.errorfile-prefix = "/var/www/ErrorPages/HTTP"
+// start service
+_webapp.listen(8888);
 ```
 ```
 
 
+**Options**
+
+Syntax: `Promise _httpErrorPages.koa([options:Object])`
+
+* `template` - the path to a custom **EJS** template used to generate the pages. default [assets/template.ejs](assets/template.ejs)
+* `css` - the path to a precompiled **CSS** file injected into the page. default [assets/layout.css](assets/layout.css)
+* `footer` - optional page footer content (html allowed). default **null**
+* `lang` - language definition which should be used (available in the `i18n/` directory). default **en_US**
+
+
 ## Customization ##
 ## Customization ##
 
 
 First of all, [clone](https://github.com/AndiDittrich/HttpErrorPages.git) 
 First of all, [clone](https://github.com/AndiDittrich/HttpErrorPages.git) 
@@ -186,7 +246,7 @@ yarn install
 npm install
 npm install
 ```
 ```
 
 
-To customize the pages, you can edit any of the template files and **finally run the generator-script**.
+To customize the pages, you can edit any of the [template files](assets/) and **finally run the generator-script**.
 All generated html files are located into the `dist/` directory by default.
 All generated html files are located into the `dist/` directory by default.
 
 
 If you wan't to add custom pages/additional error-codes, just put a new entry into the `i18n/pages-en_US.json` file (its recommended to copy the file). 
 If you wan't to add custom pages/additional error-codes, just put a new entry into the `i18n/pages-en_US.json` file (its recommended to copy the file). 

File diff suppressed because it is too large
+ 0 - 0
dist/HTTP500.html


File diff suppressed because it is too large
+ 0 - 0
dist/HTTP502.html


File diff suppressed because it is too large
+ 0 - 0
dist/HTTP503.html


File diff suppressed because it is too large
+ 0 - 0
dist/HTTP521.html


File diff suppressed because it is too large
+ 0 - 0
dist/HTTP533.html


BIN
dist/pages.tar


File diff suppressed because it is too large
+ 0 - 0
docs/HTTP400.html


File diff suppressed because it is too large
+ 0 - 0
docs/HTTP401.html


File diff suppressed because it is too large
+ 0 - 0
docs/HTTP403.html


File diff suppressed because it is too large
+ 0 - 0
docs/HTTP404.html


File diff suppressed because it is too large
+ 0 - 0
docs/HTTP500.html


File diff suppressed because it is too large
+ 0 - 0
docs/HTTP501.html


File diff suppressed because it is too large
+ 0 - 0
docs/HTTP502.html


File diff suppressed because it is too large
+ 0 - 0
docs/HTTP503.html


File diff suppressed because it is too large
+ 0 - 0
docs/HTTP520.html


File diff suppressed because it is too large
+ 0 - 0
docs/HTTP521.html


File diff suppressed because it is too large
+ 0 - 0
docs/HTTP533.html


+ 2 - 2
express-demo.js → examples/express.js

@@ -2,7 +2,7 @@ const _express = require('express');
 const _webapp = _express();
 const _webapp = _express();
 
 
 // use require('http-error-pages') for regular apps!
 // use require('http-error-pages') for regular apps!
-const _httpErrorPages = require('./lib/error-handler');
+const _httpErrorPages = require('../lib/main');
 
 
 async function bootstrap(){
 async function bootstrap(){
     // demo handler
     // demo handler
@@ -24,7 +24,7 @@ async function bootstrap(){
 
 
     // use http error pages handler (final statement!)
     // use http error pages handler (final statement!)
     // because of the asynchronous file-loaders, wait until it has been executed
     // because of the asynchronous file-loaders, wait until it has been executed
-    await _httpErrorPages(_webapp, {
+    await _httpErrorPages.express(_webapp, {
         lang: 'en_US',
         lang: 'en_US',
         footer: 'Hello <strong>World</strong>'
         footer: 'Hello <strong>World</strong>'
     });
     });

+ 67 - 0
examples/koa.js

@@ -0,0 +1,67 @@
+const _koa = require('koa');
+const _webapp = new _koa();
+
+// use require('http-error-pages') for regular apps!
+const _httpErrorPages = require('../lib/main');
+
+async function bootstrap(){
+
+    // use http error pages handler (INITIAL statement!)
+    // because of the asynchronous file-loaders, wait until it has been executed - it returns an async handler
+    _webapp.use(await _httpErrorPages.koa({
+        lang: 'en_US',
+        footer: 'Hello <strong>World</strong>'
+    }));
+
+    // demo handler
+    _webapp.use(async (ctx, next) => {
+        if (ctx.path == '/'){
+            ctx.type = 'text';
+            ctx.body = 'HttpErrorPages Demo';
+        }else{
+            return next();
+        }
+    });
+
+    // throw an 403 error
+    _webapp.use(async (ctx, next) => {
+        if (ctx.path == '/my403error'){
+            ctx.throw(403);
+        }else{
+            return next();
+        }
+    });
+
+    // throw an 533 error with status 500
+    _webapp.use(async (ctx, next) => {
+        if (ctx.path == '/x533'){
+            const e = new Error("custom");
+            e.errorpage = '533';
+            e.status = 500;
+            throw e;
+        }else{
+            return next();
+        }
+    });
+
+    // throw an internal error
+    _webapp.use(async (ctx, next) => {
+        if (ctx.path == '/500'){
+            throw new Error('Server Error');
+        }else{
+            return next();
+        }
+    });
+
+    // start service
+    _webapp.listen(8888);
+}
+
+// invoke bootstrap operation
+bootstrap()
+    .then(function(){
+        console.log('Running Demo on Port 8888');
+    })
+    .catch(function(e){
+        console.error(e);
+    });

+ 0 - 24
lib/error-handler.js

@@ -1,24 +0,0 @@
-const _dispatcher = require('./dispatcher');
-
-module.exports = async function(router, options={}){
-    // create new disptacher with given options
-    const dispatch = await _dispatcher(options);
-
-    // default 404 error - no route matches
-    router.all('*', function(req, res){
-        dispatch('404', 404, req, res);
-    });
-
-    // internal errors (all)
-    router.use(function(err, req, res, next){
-        // status code given ?
-        if (err.status){
-            // custom errorpage set ?
-            dispatch(err.errorpage || err.status, err.status, req, res);
-    
-        // use default http500 page
-        }else{
-            dispatch('500', 500, req, res);
-        }
-    });
-};

+ 22 - 1
lib/dispatcher.js → lib/express.js

@@ -68,5 +68,26 @@ async function createDispatcher(options={}){
     }
     }
 }
 }
 
 
+module.exports = async function httpErrorPages(router, options={}){
+    
+    // create new disptacher with given options
+    const dispatch = await createDispatcher(options);
+
+    // default 404 error - no route matches
+    router.all('*', function(req, res){
+        dispatch('404', 404, req, res);
+    });
 
 
-module.exports = createDispatcher;
+    // internal errors (all)
+    router.use(function(err, req, res, next){
+        // status code given ?
+        if (err.status){
+            // custom errorpage set ?
+            dispatch(err.errorpage || err.status, err.status, req, res);
+    
+        // use default http500 page
+        }else{
+            dispatch('500', 500, req, res);
+        }
+    });
+};

+ 100 - 0
lib/koa.js

@@ -0,0 +1,100 @@
+const _render = require('./page-renderer');
+const _path = require('path');
+const _fs = require('fs-magic');
+const _jsonReader = require('./json-reader');
+
+// wrapper to add custom options
+async function createDispatcher(options={}){
+
+    // merge options
+    const opt = {
+        template: options.template || _path.join(__dirname, '../assets/template.ejs'),
+        css: options.css || _path.join(__dirname, '../assets/layout.css'),
+        lang: options.lang || 'en_US',
+        footer: options.footer || null
+    };
+
+    // load page template
+    const tpl = await _fs.readFile(opt.template, 'utf8');
+
+    // load styles
+    const css = await _fs.readFile(opt.css, 'utf8');
+    
+    // load page definitions
+    const pages = await _jsonReader(_path.join(__dirname, '../i18n/pages-' + opt.lang + '.json'));
+
+    // multi-type support
+    // @see https://github.com/koajs/koa/blob/master/docs/api/response.md#responseistypes
+    return function dispatchRequest(page, httpStatusCode, ctx){
+        // page available ?
+        if (!pages[page]){
+            // use "internal server error" as default
+            page = '500';
+            httpStatusCode = null;
+        }
+
+        // set http status code
+        ctx.status = httpStatusCode || 500;
+
+        // extract page date
+        const pageData = pages[page];
+
+        // multiple response formats
+        switch (ctx.accepts('json', 'html', 'text')){
+
+            // jsonn response
+            case 'json':
+                ctx.type = 'json';
+                ctx.body = {
+                    error: pageData.title + ' - ' + pageData.message
+                }
+                break;
+
+            // html response
+            case 'html':
+                ctx.type = 'html';
+                ctx.body = _render(tpl, css, {
+                    code: httpStatusCode,
+                    title: pageData.title,
+                    message: pageData.message,
+                    footer: opt.footer
+                });
+                break;
+            
+            // default: text response
+            default:
+                ctx.type = 'text/plain';
+                ctx.body = pageData.title + ' - ' + pageData.message;
+          }
+    }
+}
+
+module.exports = async function httpErrorPages(options={}){
+
+    // create new disptacher with given options
+    const dispatch = await createDispatcher(options);
+
+    // create error handler
+    // @see https://github.com/koajs/koa/blob/master/docs/error-handling.md
+    return async (ctx, next) => {
+        try{
+            // dispatch middleware chain
+            await next();
+
+            // route not found ?
+            if (ctx.status === 404) {
+                dispatch('404', 404, ctx);
+            }
+        }catch(err){
+            // status code given ?
+            if (err.status){
+                // custom errorpage set ?
+                dispatch(err.errorpage || err.status, err.status, ctx);
+
+            // use default http500 page
+            }else{
+                dispatch('500', 500, ctx);
+            }
+        }
+    }
+}

+ 8 - 0
lib/main.js

@@ -0,0 +1,8 @@
+const _express = require('./express');
+const _koa = require('./koa');
+
+// framework specific error-handler
+module.exports = {
+    koa: _koa,
+    express: _express
+};

+ 5 - 4
package.json

@@ -1,7 +1,7 @@
 {
 {
     "name": "http-error-pages",
     "name": "http-error-pages",
-    "version": "1.0.0",
-    "description": "Simple HTTP Error Pages for expressjs",
+    "version": "2.0.0",
+    "description": "Simple HTTP Error Pages. standalone + static + koa + express",
     "engines": {
     "engines": {
         "node": ">=7.6"
         "node": ">=7.6"
     },
     },
@@ -27,7 +27,7 @@
         "i18n",
         "i18n",
         "assets",
         "assets",
         "bin",
         "bin",
-        "express-demo.js",
+        "examples",
         "CHANGES.md",
         "CHANGES.md",
         "LICENSE.md",
         "LICENSE.md",
         "README.md"
         "README.md"
@@ -35,7 +35,7 @@
     "bin": {
     "bin": {
         "http-error-pages": "./bin/generator.js"
         "http-error-pages": "./bin/generator.js"
     },
     },
-    "main": "./lib/error-handler.js",
+    "main": "./lib/main.js",
     "author": "Andi Dittrich (https://andidittrich.de)",
     "author": "Andi Dittrich (https://andidittrich.de)",
     "homepage": "https://github.com/AndiDittrich/HttpErrorPages",
     "homepage": "https://github.com/AndiDittrich/HttpErrorPages",
     "bugs": "https://github.com/AndiDittrich/HttpErrorPages/issues",
     "bugs": "https://github.com/AndiDittrich/HttpErrorPages/issues",
@@ -51,6 +51,7 @@
         "gulp-concat-util": "^0.5.5",
         "gulp-concat-util": "^0.5.5",
         "gulp-prettyerror": "^1.2.1",
         "gulp-prettyerror": "^1.2.1",
         "gulp-sass": "^3.1.0",
         "gulp-sass": "^3.1.0",
+        "koa": "^2.4.1",
         "less": "^2.7.3"
         "less": "^2.7.3"
     },
     },
     "dependencies": {
     "dependencies": {

+ 144 - 12
yarn.lock

@@ -6,6 +6,13 @@ abbrev@1:
   version "1.1.1"
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
   resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
 
 
+accepts@^1.2.2:
+  version "1.3.4"
+  resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.4.tgz#86246758c7dd6d21a6474ff084a4740ec05eb21f"
+  dependencies:
+    mime-types "~2.1.16"
+    negotiator "0.6.1"
+
 accepts@~1.3.3:
 accepts@~1.3.3:
   version "1.3.3"
   version "1.3.3"
   resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca"
   resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca"
@@ -73,6 +80,10 @@ ansi-styles@^3.1.0:
   dependencies:
   dependencies:
     color-convert "^1.9.0"
     color-convert "^1.9.0"
 
 
+any-promise@^1.1.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
+
 aproba@^1.0.3:
 aproba@^1.0.3:
   version "1.2.0"
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
   resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
@@ -390,10 +401,14 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0:
   version "1.1.0"
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
   resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
 
 
-content-disposition@0.5.2:
+content-disposition@0.5.2, content-disposition@~0.5.0:
   version "0.5.2"
   version "0.5.2"
   resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
   resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
 
 
+content-type@^1.0.0:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
+
 content-type@~1.0.2:
 content-type@~1.0.2:
   version "1.0.2"
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.2.tgz#b7d113aee7a8dd27bd21133c4dc2529df1721eed"
   resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.2.tgz#b7d113aee7a8dd27bd21133c4dc2529df1721eed"
@@ -406,6 +421,13 @@ cookie@0.3.1:
   version "0.3.1"
   version "0.3.1"
   resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
   resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
 
 
+cookies@~0.7.0:
+  version "0.7.1"
+  resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.7.1.tgz#7c8a615f5481c61ab9f16c833731bcb8f663b99b"
+  dependencies:
+    depd "~1.1.1"
+    keygrip "~1.0.2"
+
 core-util-is@1.0.2, core-util-is@~1.0.0:
 core-util-is@1.0.2, core-util-is@~1.0.0:
   version "1.0.2"
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
   resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
@@ -453,6 +475,12 @@ dateformat@^2.0.0:
   version "2.2.0"
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062"
   resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062"
 
 
+debug@*, debug@^3.0.1:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
+  dependencies:
+    ms "2.0.0"
+
 debug@2.6.1:
 debug@2.6.1:
   version "2.6.1"
   version "2.6.1"
   resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.1.tgz#79855090ba2c4e3115cc7d8769491d58f0491351"
   resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.1.tgz#79855090ba2c4e3115cc7d8769491d58f0491351"
@@ -465,16 +493,14 @@ debug@2.6.4:
   dependencies:
   dependencies:
     ms "0.7.3"
     ms "0.7.3"
 
 
-debug@^3.0.1:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
-  dependencies:
-    ms "2.0.0"
-
 decamelize@^1.1.1, decamelize@^1.1.2:
 decamelize@^1.1.1, decamelize@^1.1.2:
   version "1.2.0"
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
   resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
 
 
+deep-equal@~1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
+
 deep-is@~0.1.3:
 deep-is@~0.1.3:
   version "0.1.3"
   version "0.1.3"
   resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
   resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
@@ -509,11 +535,19 @@ depd@1.1.0, depd@~1.1.0:
   version "1.1.0"
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3"
   resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3"
 
 
+depd@1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359"
+
+depd@^1.1.0, depd@~1.1.1:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
+
 deprecated@^0.0.1:
 deprecated@^0.0.1:
   version "0.0.1"
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/deprecated/-/deprecated-0.0.1.tgz#f9c9af5464afa1e7a971458a8bdef2aa94d5bb19"
   resolved "https://registry.yarnpkg.com/deprecated/-/deprecated-0.0.1.tgz#f9c9af5464afa1e7a971458a8bdef2aa94d5bb19"
 
 
-destroy@~1.0.4:
+destroy@^1.0.3, destroy@~1.0.4:
   version "1.0.4"
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
   resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
 
 
@@ -593,7 +627,11 @@ error-ex@^1.2.0:
   dependencies:
   dependencies:
     is-arrayish "^0.2.1"
     is-arrayish "^0.2.1"
 
 
-escape-html@~1.0.3:
+error-inject@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/error-inject/-/error-inject-1.0.0.tgz#e2b3d91b54aed672f309d950d154850fa11d4f37"
+
+escape-html@~1.0.1, escape-html@~1.0.3:
   version "1.0.3"
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
   resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
 
 
@@ -922,6 +960,10 @@ fresh@0.5.0:
   version "0.5.0"
   version "0.5.0"
   resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.0.tgz#f474ca5e6a9246d6fd8e0953cfa9b9c805afa78e"
   resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.0.tgz#f474ca5e6a9246d6fd8e0953cfa9b9c805afa78e"
 
 
+fresh@^0.5.2:
+  version "0.5.2"
+  resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
+
 fs-exists-sync@^0.1.0:
 fs-exists-sync@^0.1.0:
   version "0.1.0"
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add"
   resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add"
@@ -1303,6 +1345,22 @@ hosted-git-info@^2.1.4:
   version "2.5.0"
   version "2.5.0"
   resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c"
   resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c"
 
 
+http-assert@^1.1.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/http-assert/-/http-assert-1.3.0.tgz#a31a5cf88c873ecbb5796907d4d6f132e8c01e4a"
+  dependencies:
+    deep-equal "~1.0.1"
+    http-errors "~1.6.1"
+
+http-errors@^1.2.8:
+  version "1.6.2"
+  resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736"
+  dependencies:
+    depd "1.1.1"
+    inherits "2.0.3"
+    setprototypeof "1.0.3"
+    statuses ">= 1.3.1 < 2"
+
 http-errors@~1.6.1:
 http-errors@~1.6.1:
   version "1.6.1"
   version "1.6.1"
   resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.1.tgz#5f8b8ed98aca545656bf572997387f904a722257"
   resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.1.tgz#5f8b8ed98aca545656bf572997387f904a722257"
@@ -1459,6 +1517,10 @@ is-fullwidth-code-point@^2.0.0:
   version "2.0.0"
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
   resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
 
 
+is-generator-function@^1.0.3:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.7.tgz#d2132e529bb0000a7f80794d4bdf5cd5e5813522"
+
 is-glob@^2.0.0, is-glob@^2.0.1:
 is-glob@^2.0.0, is-glob@^2.0.1:
   version "2.0.1"
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
   resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
@@ -1625,6 +1687,10 @@ jsprim@^1.2.2:
     json-schema "0.2.3"
     json-schema "0.2.3"
     verror "1.10.0"
     verror "1.10.0"
 
 
+keygrip@~1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.0.2.tgz#ad3297c557069dea8bcfe7a4fa491b75c5ddeb91"
+
 kind-of@^3.0.2:
 kind-of@^3.0.2:
   version "3.2.2"
   version "3.2.2"
   resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
   resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
@@ -1637,6 +1703,56 @@ kind-of@^4.0.0:
   dependencies:
   dependencies:
     is-buffer "^1.1.5"
     is-buffer "^1.1.5"
 
 
+koa-compose@^3.0.0:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/koa-compose/-/koa-compose-3.2.1.tgz#a85ccb40b7d986d8e5a345b3a1ace8eabcf54de7"
+  dependencies:
+    any-promise "^1.1.0"
+
+koa-compose@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/koa-compose/-/koa-compose-4.0.0.tgz#2800a513d9c361ef0d63852b038e4f6f2d5a773c"
+
+koa-convert@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/koa-convert/-/koa-convert-1.2.0.tgz#da40875df49de0539098d1700b50820cebcd21d0"
+  dependencies:
+    co "^4.6.0"
+    koa-compose "^3.0.0"
+
+koa-is-json@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/koa-is-json/-/koa-is-json-1.0.0.tgz#273c07edcdcb8df6a2c1ab7d59ee76491451ec14"
+
+koa@^2.4.1:
+  version "2.4.1"
+  resolved "https://registry.yarnpkg.com/koa/-/koa-2.4.1.tgz#d449cfb970a7e9da571f699eda40bb9e32eb1484"
+  dependencies:
+    accepts "^1.2.2"
+    content-disposition "~0.5.0"
+    content-type "^1.0.0"
+    cookies "~0.7.0"
+    debug "*"
+    delegates "^1.0.0"
+    depd "^1.1.0"
+    destroy "^1.0.3"
+    error-inject "~1.0.0"
+    escape-html "~1.0.1"
+    fresh "^0.5.2"
+    http-assert "^1.1.0"
+    http-errors "^1.2.8"
+    is-generator-function "^1.0.3"
+    koa-compose "^4.0.0"
+    koa-convert "^1.2.0"
+    koa-is-json "^1.0.0"
+    mime-types "^2.0.7"
+    on-finished "^2.1.0"
+    only "0.0.2"
+    parseurl "^1.3.0"
+    statuses "^1.2.0"
+    type-is "^1.5.5"
+    vary "^1.0.0"
+
 lcid@^1.0.0:
 lcid@^1.0.0:
   version "1.0.0"
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
   resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
@@ -1914,7 +2030,7 @@ mime-db@~1.30.0:
   version "1.30.0"
   version "1.30.0"
   resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01"
   resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01"
 
 
-mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.7:
+mime-types@^2.0.7, mime-types@^2.1.12, mime-types@~2.1.16, mime-types@~2.1.17, mime-types@~2.1.7:
   version "2.1.17"
   version "2.1.17"
   resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a"
   resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a"
   dependencies:
   dependencies:
@@ -2118,7 +2234,7 @@ object.pick@^1.2.0:
   dependencies:
   dependencies:
     isobject "^3.0.1"
     isobject "^3.0.1"
 
 
-on-finished@~2.3.0:
+on-finished@^2.1.0, on-finished@~2.3.0:
   version "2.3.0"
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
   resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
   dependencies:
   dependencies:
@@ -2142,6 +2258,10 @@ onetime@^2.0.0:
   dependencies:
   dependencies:
     mimic-fn "^1.0.0"
     mimic-fn "^1.0.0"
 
 
+only@0.0.2:
+  version "0.0.2"
+  resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4"
+
 optionator@^0.8.2:
 optionator@^0.8.2:
   version "0.8.2"
   version "0.8.2"
   resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
   resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
@@ -2213,6 +2333,10 @@ parse-passwd@^1.0.0:
   version "1.0.0"
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
   resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
 
 
+parseurl@^1.3.0:
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3"
+
 parseurl@~1.3.1:
 parseurl@~1.3.1:
   version "1.3.1"
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56"
   resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56"
@@ -2705,6 +2829,10 @@ sshpk@^1.7.0:
   version "1.3.1"
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e"
   resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e"
 
 
+statuses@^1.2.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
+
 stdout-stream@^1.4.0:
 stdout-stream@^1.4.0:
   version "1.4.0"
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.0.tgz#a2c7c8587e54d9427ea9edb3ac3f2cd522df378b"
   resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.0.tgz#a2c7c8587e54d9427ea9edb3ac3f2cd522df378b"
@@ -2905,7 +3033,7 @@ type-check@~0.3.2:
   dependencies:
   dependencies:
     prelude-ls "~1.1.2"
     prelude-ls "~1.1.2"
 
 
-type-is@~1.6.14:
+type-is@^1.5.5, type-is@~1.6.14:
   version "1.6.15"
   version "1.6.15"
   resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410"
   resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410"
   dependencies:
   dependencies:
@@ -2957,6 +3085,10 @@ validate-npm-package-license@^3.0.1:
     spdx-correct "~1.0.0"
     spdx-correct "~1.0.0"
     spdx-expression-parse "~1.0.0"
     spdx-expression-parse "~1.0.0"
 
 
+vary@^1.0.0:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
+
 vary@~1.1.0:
 vary@~1.1.0:
   version "1.1.1"
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37"
   resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37"

Some files were not shown because too many files changed in this diff