This commit is contained in:
Lloyd Brookes
2016-06-15 21:02:52 +01:00
parent 88e441dba4
commit 789b82160d
4 changed files with 57 additions and 69 deletions

View File

@ -1,8 +1,8 @@
#!/usr/bin/env node #!/usr/bin/env node
'use strict' 'use strict'
const Cli = require('../') const LocalWebServer = require('../')
const ws = new Cli() const ws = new LocalWebServer()
ws.middleware ws.middleware
.addCors() .addCors()
.addJson() .addJson()

View File

@ -1,11 +1,11 @@
'use strict' 'use strict'
const Cli = require('../') const LocalWebServer = require('../')
const cacheControl = require('koa-cache-control') const cacheControl = require('koa-cache-control')
const cliData = require('../lib/cli-data') const cliData = require('../lib/cli-data')
cliData.optionDefinitions.push({ name: 'maxage', group: 'misc' }) cliData.optionDefinitions.push({ name: 'maxage', group: 'misc' })
const ws = new Cli() const ws = new LocalWebServer()
ws.middleware ws.middleware
.addLogging('dev') .addLogging('dev')
.add(cacheControl({ .add(cacheControl({

View File

@ -8,57 +8,47 @@ const Tool = require('command-line-tool')
const tool = new Tool() const tool = new Tool()
class Cli { class Cli {
constructor (options) { constructor () {
this.options = null this.options = collectOptions()
this.app = null this.app = null
this.middleware = null this.middleware = null
options = collectOptions() const options = this.options
this.options = options
if (options.misc.config) { if (options.misc.config) {
tool.stop(JSON.stringify(options.server, null, ' '), 0) tool.stop(JSON.stringify(options.server, null, ' '), 0)
} else { } else {
const Koa = require('koa') const Koa = require('koa')
const app = new Koa() const app = new Koa()
this.app = app
const MiddlewareStack = require('./middleware-stack')
this.middleware = new MiddlewareStack(options)
const a = {
compress: options.server.compress,
mime: options.server.mime,
forbid: options.server.forbid,
spa: options.server.spa,
'no-cache': options.server['no-cache'],
rewrite: options.server.rewrite,
verbose: options.server.verbose,
mocks: options.server.mocks
}
app.on('error', err => { app.on('error', err => {
if (options.server['log-format']) { if (options.server['log-format']) {
console.error(ansi.format(err.message, 'red')) console.error(ansi.format(err.message, 'red'))
} }
}) })
this.app = app
const MiddlewareStack = require('./middleware-stack')
this.middleware = new MiddlewareStack(options)
} }
} }
listen () { listen () {
this.app.use(this.middleware.getMiddleware()) this.app.use(this.middleware.compose())
const options = this.options const options = this.options
const key = this.options.server.key
const cert = this.options.server.cert
if (options.server.https) { if (options.server.https) {
options.server.key = path.resolve(__dirname, '..', 'ssl', '127.0.0.1.key') key = path.resolve(__dirname, '..', 'ssl', '127.0.0.1.key')
options.server.cert = path.resolve(__dirname, '..', 'ssl', '127.0.0.1.crt') cert = path.resolve(__dirname, '..', 'ssl', '127.0.0.1.crt')
} }
if (options.server.key && options.server.cert) { if (key && cert) {
const https = require('https') const https = require('https')
const fs = require('fs') const fs = require('fs')
const serverOptions = { const serverOptions = {
key: fs.readFileSync(options.server.key), key: fs.readFileSync(key),
cert: fs.readFileSync(options.server.cert) cert: fs.readFileSync(cert)
} }
const server = https.createServer(serverOptions, this.app.callback()) const server = https.createServer(serverOptions, this.app.callback())

View File

@ -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 () { addRewrite (rewriteRules) {
const options = this.options.rewrite 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 () { addBlacklist (forbidList) {
const options = this.options.forbid forbidList = arrayify(this.options.server.forbid || forbidList)
if (options.length) { if (forbidList.length) {
debug('forbid', options.join(', ')) const pathToRegexp = require('path-to-regexp')
this.push(mw.blacklist(options)) 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 () { addMimeType (mime) {
const options = this.options.mime mime = this.options.server.mime || mime
if (options) { if (mime) {
debug('mime override', JSON.stringify(options)) debug('mime override', JSON.stringify(mime))
this.push(mw.mime(options)) this.push(mw.mime(mime))
} }
return this return this
} }
/* compress response */ /* compress response */
addCompression () { addCompression (compress) {
if (this.options.compress) { compress = t.isDefined(this.options.server.compress)
const compress = require('koa-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 () { addMockResponses (mocks) {
const options = this.options.mocks mocks = arrayify(this.options.server.mocks || mocks)
options.forEach(mock => { 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 () { addSpa (spa) {
if (this.options.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)