|
@ -4,30 +4,16 @@ const path = require('path') |
|
|
const url = require('url') |
|
|
const url = require('url') |
|
|
const debug = require('debug')('local-web-server') |
|
|
const debug = require('debug')('local-web-server') |
|
|
const mw = require('./middleware') |
|
|
const mw = require('./middleware') |
|
|
|
|
|
const t = require('typical') |
|
|
|
|
|
|
|
|
class MiddlewareStack extends Array { |
|
|
class MiddlewareStack extends Array { |
|
|
constructor (options) { |
|
|
constructor (options) { |
|
|
super() |
|
|
super() |
|
|
this.options = options |
|
|
this.options = options |
|
|
|
|
|
|
|
|
options = Object.assign({ |
|
|
|
|
|
cacheControl: {}, |
|
|
|
|
|
spa: null, |
|
|
|
|
|
compress: false, |
|
|
|
|
|
mime: {}, |
|
|
|
|
|
forbid: [], |
|
|
|
|
|
rewrite: [], |
|
|
|
|
|
verbose: false, |
|
|
|
|
|
mocks: [] |
|
|
|
|
|
}, options) |
|
|
|
|
|
|
|
|
|
|
|
if (options.verbose) { |
|
|
if (options.verbose) { |
|
|
process.env.DEBUG = '*' |
|
|
process.env.DEBUG = '*' |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
options.rewrite = arrayify(options.rewrite) |
|
|
|
|
|
options.forbid = arrayify(options.forbid) |
|
|
|
|
|
options.mocks = arrayify(options.mocks) |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
add (middleware) { |
|
|
add (middleware) { |
|
@ -50,8 +36,8 @@ class MiddlewareStack extends Array { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* rewrite rules */ |
|
|
/* rewrite rules */ |
|
|
addRewrite () { |
|
|
|
|
|
const options = this.options.rewrite |
|
|
|
|
|
|
|
|
addRewrite (rewriteRules) { |
|
|
|
|
|
const options = arrayify(this.options.server.rewrite || rewriteRules) |
|
|
if (options.length) { |
|
|
if (options.length) { |
|
|
options.forEach(route => { |
|
|
options.forEach(route => { |
|
|
if (route.to) { |
|
|
if (route.to) { |
|
@ -80,18 +66,26 @@ class MiddlewareStack extends Array { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* path blacklist */ |
|
|
/* path blacklist */ |
|
|
addBlacklist () { |
|
|
|
|
|
const options = this.options.forbid |
|
|
|
|
|
if (options.length) { |
|
|
|
|
|
debug('forbid', options.join(', ')) |
|
|
|
|
|
this.push(mw.blacklist(options)) |
|
|
|
|
|
|
|
|
addBlacklist (forbidList) { |
|
|
|
|
|
forbidList = arrayify(this.options.server.forbid || forbidList) |
|
|
|
|
|
if (forbidList.length) { |
|
|
|
|
|
const pathToRegexp = require('path-to-regexp') |
|
|
|
|
|
debug('forbid', forbidList.join(', ')) |
|
|
|
|
|
this.push(function blacklist (ctx, next) { |
|
|
|
|
|
if (forbidList.some(expression => pathToRegexp(expression).test(ctx.path))) { |
|
|
|
|
|
ctx.throw(403, http.STATUS_CODES[403]) |
|
|
|
|
|
} else { |
|
|
|
|
|
return next() |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
} |
|
|
} |
|
|
return this |
|
|
return this |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* cache */ |
|
|
/* cache */ |
|
|
addCache () { |
|
|
addCache () { |
|
|
if (!this.options['no-cache']) { |
|
|
|
|
|
|
|
|
const noCache = this.options.server['no-cache'] |
|
|
|
|
|
if (!noCache) { |
|
|
this.push(require('koa-conditional-get')()) |
|
|
this.push(require('koa-conditional-get')()) |
|
|
this.push(require('koa-etag')()) |
|
|
this.push(require('koa-etag')()) |
|
|
} |
|
|
} |
|
@ -99,21 +93,23 @@ class MiddlewareStack extends Array { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* mime-type overrides */ |
|
|
/* mime-type overrides */ |
|
|
addMimeType () { |
|
|
|
|
|
const options = this.options.mime |
|
|
|
|
|
if (options) { |
|
|
|
|
|
debug('mime override', JSON.stringify(options)) |
|
|
|
|
|
this.push(mw.mime(options)) |
|
|
|
|
|
|
|
|
addMimeType (mime) { |
|
|
|
|
|
mime = this.options.server.mime || mime |
|
|
|
|
|
if (mime) { |
|
|
|
|
|
debug('mime override', JSON.stringify(mime)) |
|
|
|
|
|
this.push(mw.mime(mime)) |
|
|
} |
|
|
} |
|
|
return this |
|
|
return this |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* compress response */ |
|
|
/* compress response */ |
|
|
addCompression () { |
|
|
|
|
|
if (this.options.compress) { |
|
|
|
|
|
const compress = require('koa-compress') |
|
|
|
|
|
|
|
|
addCompression (compress) { |
|
|
|
|
|
compress = t.isDefined(this.options.server.compress) |
|
|
|
|
|
? this.options.server.compress |
|
|
|
|
|
: compress |
|
|
|
|
|
if (compress) { |
|
|
debug('compression', 'enabled') |
|
|
debug('compression', 'enabled') |
|
|
this.push(compress()) |
|
|
|
|
|
|
|
|
this.push(require('koa-compress')()) |
|
|
} |
|
|
} |
|
|
return this |
|
|
return this |
|
|
} |
|
|
} |
|
@ -148,10 +144,11 @@ class MiddlewareStack extends Array { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* Mock Responses */ |
|
|
/* Mock Responses */ |
|
|
addMockResponses () { |
|
|
|
|
|
const options = this.options.mocks |
|
|
|
|
|
options.forEach(mock => { |
|
|
|
|
|
|
|
|
addMockResponses (mocks) { |
|
|
|
|
|
mocks = arrayify(this.options.server.mocks || mocks) |
|
|
|
|
|
mocks.forEach(mock => { |
|
|
if (mock.module) { |
|
|
if (mock.module) { |
|
|
|
|
|
// TODO: ENSURE this.options.static.root is correct value
|
|
|
mock.responses = require(path.resolve(path.join(this.options.static.root, mock.module))) |
|
|
mock.responses = require(path.resolve(path.join(this.options.static.root, mock.module))) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -169,12 +166,13 @@ class MiddlewareStack extends Array { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* for any URL not matched by static (e.g. `/search`), serve the SPA */ |
|
|
/* for any URL not matched by static (e.g. `/search`), serve the SPA */ |
|
|
addSpa () { |
|
|
|
|
|
if (this.options.spa) { |
|
|
|
|
|
|
|
|
addSpa (spa) { |
|
|
|
|
|
spa = t.isDefined(this.options.server.spa) ? this.options.server.spa : spa |
|
|
|
|
|
if (spa) { |
|
|
const historyApiFallback = require('koa-connect-history-api-fallback') |
|
|
const historyApiFallback = require('koa-connect-history-api-fallback') |
|
|
debug('SPA', this.options.spa) |
|
|
|
|
|
|
|
|
debug('SPA', spa) |
|
|
this.push(historyApiFallback({ |
|
|
this.push(historyApiFallback({ |
|
|
index: this.options.spa, |
|
|
|
|
|
|
|
|
index: spa, |
|
|
verbose: this.options.verbose |
|
|
verbose: this.options.verbose |
|
|
})) |
|
|
})) |
|
|
} |
|
|
} |
|
@ -203,7 +201,7 @@ class MiddlewareStack extends Array { |
|
|
return this |
|
|
return this |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
getMiddleware (options) { |
|
|
|
|
|
|
|
|
compose (options) { |
|
|
const compose = require('koa-compose') |
|
|
const compose = require('koa-compose') |
|
|
const convert = require('koa-convert') |
|
|
const convert = require('koa-convert') |
|
|
const middlewareStack = this.map(convert) |
|
|
const middlewareStack = this.map(convert) |
|
|