Lloyd Brookes
9 years ago
3 changed files with 155 additions and 146 deletions
-
143lib/local-web-server.js
-
120lib/middleware.js
-
20test/test.js
@ -0,0 +1,120 @@ |
|||||
|
'use strict' |
||||
|
const path = require('path') |
||||
|
const http = require('http') |
||||
|
const url = require('url') |
||||
|
const arrayify = require('array-back') |
||||
|
const pathToRegexp = require('path-to-regexp') |
||||
|
const debug = require('debug')('local-web-server') |
||||
|
|
||||
|
/** |
||||
|
* @module middleware |
||||
|
*/ |
||||
|
exports.proxyRequest = proxyRequest |
||||
|
exports.blacklist = blacklist |
||||
|
exports.mockResponses = mockResponses |
||||
|
exports.mime = mime |
||||
|
|
||||
|
function proxyRequest (route, app) { |
||||
|
const httpProxy = require('http-proxy') |
||||
|
const proxy = httpProxy.createProxyServer({ |
||||
|
changeOrigin: true |
||||
|
}) |
||||
|
|
||||
|
return function * proxyMiddleware () { |
||||
|
const next = arguments[arguments.length - 1] |
||||
|
const keys = [] |
||||
|
route.re = pathToRegexp(route.from, keys) |
||||
|
route.new = this.url.replace(route.re, route.to) |
||||
|
|
||||
|
keys.forEach((key, index) => { |
||||
|
const re = RegExp(`:${key.name}`, 'g') |
||||
|
route.new = route.new |
||||
|
.replace(re, arguments[index] || '') |
||||
|
}) |
||||
|
|
||||
|
/* test no keys remain in the new path */ |
||||
|
keys.length = 0 |
||||
|
pathToRegexp(url.parse(route.new).path, keys) |
||||
|
if (keys.length) { |
||||
|
this.throw(500, `[PROXY] Invalid target URL: ${route.new}`) |
||||
|
return next() |
||||
|
} |
||||
|
|
||||
|
this.response = false |
||||
|
debug('proxy request', `from: ${this.path}, to: ${url.parse(route.new).href}`) |
||||
|
|
||||
|
proxy.once('error', err => { |
||||
|
this.throw(500, `[PROXY] ${err.message}: ${route.new}`) |
||||
|
}) |
||||
|
proxy.once('proxyReq', function (proxyReq) { |
||||
|
proxyReq.path = url.parse(route.new).path |
||||
|
}) |
||||
|
proxy.web(this.req, this.res, { target: route.new }) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function blacklist (forbid) { |
||||
|
return function blacklist (ctx, next) { |
||||
|
if (forbid.some(expression => pathToRegexp(expression).test(ctx.path))) { |
||||
|
ctx.throw(403, http.STATUS_CODES[403]) |
||||
|
} else { |
||||
|
return next() |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function mockResponses (options) { |
||||
|
options = options || { root: process.cwd() } |
||||
|
return function mockResponses (ctx, next) { |
||||
|
if (/\.mock.js$/.test(ctx.path)) { |
||||
|
const mocks = arrayify(require(path.join(options.root, ctx.path))) |
||||
|
const testValue = require('test-value') |
||||
|
const t = require('typical') |
||||
|
|
||||
|
/* find a mock with compatible method and accepts */ |
||||
|
let mock = mocks.find(mock => { |
||||
|
return testValue(mock, { |
||||
|
request: { |
||||
|
method: [ ctx.method, undefined ], |
||||
|
accepts: type => ctx.accepts(type) |
||||
|
} |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
|
/* else take the first mock without a request (no request means 'all requests') */ |
||||
|
if (!mock) { |
||||
|
mock = mocks.find(mock => !mock.request) |
||||
|
} |
||||
|
|
||||
|
const mockedReponse = {} |
||||
|
/* resolve any functions on the mock */ |
||||
|
Object.keys(mock.response).forEach(key => { |
||||
|
if (t.isFunction(mock.response[key])) { |
||||
|
mockedReponse[key] = mock.response[key](ctx) |
||||
|
} else { |
||||
|
mockedReponse[key] = mock.response[key] |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
if (mock) { |
||||
|
Object.assign(ctx.response, mockedReponse) |
||||
|
// debug('mocked response', JSON.stringify(mockedReponse))
|
||||
|
// debug('actual response', JSON.stringify(ctx.response))
|
||||
|
} |
||||
|
} else { |
||||
|
return next() |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function mime (mimeTypes) { |
||||
|
return function mime (ctx, next) { |
||||
|
return next().then(() => { |
||||
|
const reqPathExtension = path.extname(ctx.path).slice(1) |
||||
|
Object.keys(mimeTypes).forEach(mimeType => { |
||||
|
const extsToOverride = mimeTypes[mimeType] |
||||
|
if (extsToOverride.indexOf(reqPathExtension) > -1) ctx.type = mimeType |
||||
|
}) |
||||
|
}) |
||||
|
} |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue