From db07dc08c974861cb4c5df74361a49928c907b1d Mon Sep 17 00:00:00 2001 From: William Hilton Date: Fri, 11 Jan 2019 22:40:38 -0500 Subject: [PATCH 1/2] feat: add static server --- http-server.js | 19 ++++++- logger.js | 32 ++++++++++++ middleware.js | 6 --- package-lock.json | 130 ++++++++++++++++++++++++++++++++++++++++++++-- package.json | 7 ++- 5 files changed, 181 insertions(+), 13 deletions(-) create mode 100644 logger.js diff --git a/http-server.js b/http-server.js index f4f63ff..cef31ef 100755 --- a/http-server.js +++ b/http-server.js @@ -1,9 +1,14 @@ #!/usr/bin/env node // Standalone server for use without karma! +var fs = require('fs') var http = require('http') var path = require('path') -var factory = require('./middleware') +var stack = require('stack') +var static = require('serve-static') + var cors = require('./cors') +var logger = require('./logger') +var factory = require('./middleware') var config = { root: path.resolve(process.cwd(), process.env.GIT_HTTP_MOCK_SERVER_ROOT || '.'), @@ -11,5 +16,15 @@ var config = { route: process.env.GIT_HTTP_MOCK_SERVER_ROUTE || '/' } -var server = http.createServer(cors(factory(config))) +var server = http.createServer( + cors( + stack( + logger.log(), + logger.handler('git-http-server'), + factory(config), + logger.handler('serve-static'), + static(config.root) + ) + ) +) server.listen(process.env.GIT_HTTP_MOCK_SERVER_PORT || 8174) diff --git a/logger.js b/logger.js new file mode 100644 index 0000000..9f30c52 --- /dev/null +++ b/logger.js @@ -0,0 +1,32 @@ +var chalk = require('chalk') +var onFinished = require('on-finished') + +function padHandler (str) { + return (str + ' ').slice(0, 18) +} + +function padMethod (str) { + return (str + ' ').slice(0, 7) +} + +function log () { + return function (req, res, next) { + onFinished(res, function () { + var color = (res.statusCode === 401 || res.statusCode < 400) ? chalk.green : chalk.red + console.log(color(padHandler('[' + res.handler + '] ') + res.statusCode + ' ' + padMethod(req.method) + ' ' + req.url)) + }) + next() + } +} + +function handler (label) { + return function (req, res, next) { + res.handler = label + next() + } +} + +module.exports = { + log: log, + handler: handler +} diff --git a/middleware.js b/middleware.js index 77b3d2c..556217e 100644 --- a/middleware.js +++ b/middleware.js @@ -47,7 +47,6 @@ function factory (config) { if (req.method === 'OPTIONS') { res.statusCode = 204 res.end('') - console.log(chalk.green('[git-http-server] 204 ' + pad(req.method) + ' ' + req.url)) return } if (!next) next = () => void(0) @@ -56,7 +55,6 @@ function factory (config) { } catch (err) { res.statusCode = 404 res.end(err.message + '\n') - console.log(chalk.red('[git-http-server] 404 ' + pad(req.method) + ' ' + req.url)) return } if (gitdir == null) return next() @@ -79,7 +77,6 @@ function factory (config) { res.statusMessage = 'Authorization Required' res.setHeader('WWW-Authenticate', 'Basic') res.end('Unauthorized' + '\n') - console.log(chalk.green('[git-http-server] 401 ' + pad(req.method) + ' ' + req.url)) return } let valid = await htpasswd.authenticate({ @@ -94,7 +91,6 @@ function factory (config) { res.statusMessage = 'Authorization Required' res.setHeader('WWW-Authenticate', 'Basic') res.end('Bad credentials' + '\n') - console.log(chalk.green('[git-http-server] 401 ' + pad(req.method) + ' ' + req.url)) return } } @@ -103,12 +99,10 @@ function factory (config) { if (err) { res.statusCode = 500 res.end(err + '\n') - console.log(chalk.red('[git-http-server] 500 ' + pad(req.method) + ' ' + req.url)) return } res.setHeader('content-type', service.type) - console.log(chalk.green('[git-http-server] 200 ' + pad(req.method) + ' ' + req.url)) // console.log('[git-http-server] ' + service.cmd + ' ' + service.args.concat(gitdir).join(' ')) var ps = spawn(service.cmd, service.args.concat(gitdir)) ps.stdout.pipe(service.createStream()).pipe(ps.stdin) diff --git a/package-lock.json b/package-lock.json index 33803e2..58590be 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1775,6 +1775,16 @@ } } }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, "detect-indent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", @@ -1826,12 +1836,22 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, "electron-to-chromium": { "version": "1.3.62", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.62.tgz", "integrity": "sha512-x09ndL/Gjnuk3unlAyoGyUg3wbs4w/bXurgL7wL913vXHAOWmMhrLf1VNGRaMLngmadd5Q8gsV9BFuIr6rP+Xg==", "dev": true }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, "env-ci": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-1.7.2.tgz", @@ -1866,6 +1886,11 @@ "es6-promise": "^4.0.3" } }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -1883,6 +1908,11 @@ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, "execa": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", @@ -2100,6 +2130,11 @@ "map-cache": "^0.2.2" } }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, "from2": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", @@ -2457,6 +2492,17 @@ "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", "dev": true }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, "http-proxy-agent": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", @@ -3336,8 +3382,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "nanomatch": { "version": "1.2.13", @@ -3473,6 +3518,14 @@ "isobject": "^3.0.1" } }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3718,6 +3771,11 @@ "protocols": "^1.4.0" } }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", @@ -3831,6 +3889,11 @@ "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", "dev": true }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -4122,6 +4185,52 @@ "semver": "^5.0.3" } }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + } + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + } + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -4151,6 +4260,11 @@ } } }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -4432,6 +4546,11 @@ "streamsearch": "~0.1.2" } }, + "stack": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/stack/-/stack-0.1.0.tgz", + "integrity": "sha1-6SNZipvlHmF2gsshzxsoGKRJraI=" + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -4453,6 +4572,11 @@ } } }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + }, "stream-combiner2": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", @@ -4771,7 +4895,7 @@ }, "underscore": { "version": "1.4.4", - "resolved": "http://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=" }, "union-value": { diff --git a/package.json b/package.json index b630451..35199bf 100644 --- a/package.json +++ b/package.json @@ -38,9 +38,12 @@ "htpasswd-js": "^1.0.2", "micro-cors": "^0.1.1", "minimisted": "^2.0.0", - "tree-kill": "^1.2.0", + "on-finished": "^2.3.0", + "serve-static": "^1.13.2", "ssh-keygen": "^0.4.2", - "ssh2": "^0.6.1" + "ssh2": "^0.6.1", + "stack": "^0.1.0", + "tree-kill": "^1.2.0" }, "devDependencies": { "semantic-release": "15.1.7", From 8b80d50a6a956624e3424577151d7e9f568fd20d Mon Sep 17 00:00:00 2001 From: William Hilton Date: Fri, 11 Jan 2019 23:01:53 -0500 Subject: [PATCH 2/2] feat: add mock server --- http-server.js | 3 +++ mock-response.js | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 mock-response.js diff --git a/http-server.js b/http-server.js index cef31ef..b8239f2 100755 --- a/http-server.js +++ b/http-server.js @@ -8,6 +8,7 @@ var static = require('serve-static') var cors = require('./cors') var logger = require('./logger') +var mock = require('./mock-response') var factory = require('./middleware') var config = { @@ -20,6 +21,8 @@ var server = http.createServer( cors( stack( logger.log(), + logger.handler('x-mock-response'), + mock(), logger.handler('git-http-server'), factory(config), logger.handler('serve-static'), diff --git a/mock-response.js b/mock-response.js new file mode 100644 index 0000000..266ee5a --- /dev/null +++ b/mock-response.js @@ -0,0 +1,16 @@ +module.exports = function () { + return function (req, res, next) { + for (let header in req.headers) { + if (header.startsWith('x-mock-header-')) { + res.setHeader(header.replace('x-mock-header-', ''), req.headers[header]) + next = null + } + } + if (next) { + return next() + } else { + res.statusCode = req.headers['x-mock-status-code'] + res.end(req.headers['x-mock-body']) + } + } +} \ No newline at end of file