diff --git a/app/http-mock-server.js b/app/http-mock-server.js index e4d0d00..e31feaa 100644 --- a/app/http-mock-server.js +++ b/app/http-mock-server.js @@ -6,183 +6,240 @@ const sleep = require('sleep'); const pathToRegexp = require('path-to-regexp'); const path = require('path'); const mime = require('mime'); +const {parse} = require('querystring'); class HttpMockServer { - constructor(app) { - this.app = app; - http.createServer((req, res) => { - let foundEndpoint = this.findEndpoint(req); - - if (foundEndpoint !== null) { - if (Array.isArray(foundEndpoint.response)) { - let weightResponseIndexes = []; - foundEndpoint.response.forEach((responseItem, index) => { - weightResponseIndexes = weightResponseIndexes.concat((new Array(responseItem.weight || 1)).fill(index)); - }); - const randIndex = weightResponseIndexes[Math.floor(Math.random() * weightResponseIndexes.length)]; - if (randIndex !== undefined) { - HttpMockServer.writeResponse(req, res, foundEndpoint, foundEndpoint.response[randIndex]); - } - } else { - HttpMockServer.writeResponse(req, res, foundEndpoint, foundEndpoint.response); - } + constructor(app) { + this.app = app; + http.createServer((req, res) => { + let body = null; + req.on('data', (chunk) => { + if (!body) { + body = ''; + } + body += chunk; + }); + req.on('end', () => { + + // build body + if (body) { + if (req.headers['content-type']) { + if (req.headers['content-type'] === + 'application/x-www-form-urlencoded') { + req.body = parse(body); + } else if (req.headers['content-type'] === + 'application/json') { + req.body = JSON.parse(body); } else { - res.writeHead(404, {}); + try { + req.body = JSON.parse(body); + } + catch (error) { + try { + req.body = parse(body); + } + catch (error) { + req.body = body; + } + } } + } else { + req.body = body; + } + } - res.end(); - }).listen(80); - } + let foundEndpoint = this.findEndpoint(req); - static writeResponse(request, response, endpoint, endpointResponse) { - if (endpointResponse.delay) { - if (Array.isArray(endpointResponse.delay)) { - if (endpointResponse.delay.length === 2) { - sleep.msleep(Math.floor(Math.random() * (endpointResponse.delay[1] - endpointResponse.delay[0])) + endpointResponse.delay[0]); - } - } else { - sleep.msleep(endpointResponse.delay); + if (foundEndpoint !== null) { + if (Array.isArray(foundEndpoint.response)) { + let weightResponseIndexes = []; + foundEndpoint.response.forEach((responseItem, index) => { + weightResponseIndexes = weightResponseIndexes.concat((new Array(responseItem.weight || 1)).fill(index)); + }); + const randIndex = weightResponseIndexes[Math.floor(Math.random() * weightResponseIndexes.length)]; + if (randIndex !== undefined) { + HttpMockServer.writeResponse(req, res, foundEndpoint, foundEndpoint.response[randIndex]); } + } else { + HttpMockServer.writeResponse(req, res, foundEndpoint, foundEndpoint.response); + } + } else { + res.writeHead(404, {}); } - response.writeHead(endpointResponse.status || 200, endpointResponse.headers); + res.end(); + }); + }).listen(80); + } - if (endpointResponse.velocity && endpointResponse.velocity.enabled) { - response.write(Velocity.render(HttpMockServer.getEndpointBody(endpoint, endpointResponse), { - math: Math, - req: request, - endpoint: endpoint, - context: endpointResponse.velocity.context, - params: endpoint.params - })); - } else { - response.write(HttpMockServer.getEndpointBody(endpoint, endpointResponse)); + static writeResponse(request, response, endpoint, endpointResponse) { + if (endpointResponse.delay) { + if (Array.isArray(endpointResponse.delay)) { + if (endpointResponse.delay.length === 2) { + sleep.msleep(Math.floor(Math.random() * (endpointResponse.delay[1] - endpointResponse.delay[0])) + endpointResponse.delay[0]); } + } else { + sleep.msleep(endpointResponse.delay); + } } - static getEndpointPath(endpoint, endpointRequest) { - let basePath = endpoint.basePath || ''; + response.writeHead(endpointResponse.status || 200, endpointResponse.headers); + + if (endpointResponse.velocity && endpointResponse.velocity.enabled) { + response.write(Velocity.render(HttpMockServer.getEndpointBody(endpoint, endpointResponse), { + math: Math, + req: request, + endpoint: endpoint, + context: endpointResponse.velocity.context, + params: endpoint.params + })); + } else { + response.write(HttpMockServer.getEndpointBody(endpoint, endpointResponse)); + } + } - if (basePath !== '') { - basePath = '/' + basePath.replace(/^\//, ""); - } + static getEndpointPath(endpoint, endpointRequest) { + let basePath = endpoint.basePath || ''; - return basePath.replace(/\/$/, "") + '/' + endpointRequest.path.replace(/^\//, ""); + if (basePath !== '') { + basePath = '/' + basePath.replace(/^\//, ""); } - isRequestMatch(endpoint, endpointRequest, request, endpointParams) { - endpoint.callCount = endpoint.callCount || 0; + return basePath.replace(/\/$/, "") + '/' + endpointRequest.path.replace(/^\//, ""); + } - if (endpoint.maxCalls && endpoint.callCount >= endpoint.maxCalls) { - return false; - } + isRequestMatch(endpoint, endpointRequest, request, endpointParams) { + endpoint.callCount = endpoint.callCount || 0; - if (endpointRequest.method && request.method !== endpointRequest.method) { - return false; - } + if (endpoint.maxCalls && endpoint.callCount >= endpoint.maxCalls) { + return false; + } - let keys = []; - const re = pathToRegexp(HttpMockServer.getEndpointPath(endpoint, endpointRequest), keys); - const params = re.exec(request.path); + if (endpointRequest.method && request.method !== endpointRequest.method) { + return false; + } - if (params === null) { - return false; - } + let keys = []; + const re = pathToRegexp(HttpMockServer.getEndpointPath(endpoint, endpointRequest), keys); + const params = re.exec(request.path); - let matchQuery = true; + if (params === null) { + return false; + } - if (endpointRequest.query) { - Object.keys(endpointRequest.query).forEach((key) => { - if (!request.query[key]) { - matchQuery = false; - return; - } + let matchQuery = true; - if (!(new RegExp(endpointRequest.query[key])).test(request.query[key])) { - matchQuery = false; - } - }); + if (endpointRequest.query) { + Object.keys(endpointRequest.query).forEach((key) => { + if (!request.query[key]) { + matchQuery = false; + return; } - if (!matchQuery) { - return false; + if (!(new RegExp(endpointRequest.query[key])).test(request.query[key])) { + matchQuery = false; } + }); + } - let matchHeader = true; + if (!matchQuery) { + return false; + } - if (endpointRequest.headers) { - Object.keys(endpointRequest.headers).forEach((key) => { - if (!request.headers[key]) { - matchHeader = false; - return; - } + let matchHeader = true; - if (!(new RegExp(endpointRequest.headers[key])).test(request.headers[key])) { - matchHeader = false; - } - }); + if (endpointRequest.headers) { + Object.keys(endpointRequest.headers).forEach((key) => { + if (!request.headers[key]) { + matchHeader = false; + return; } - if (!matchHeader) { - return false; + if (!(new RegExp(endpointRequest.headers[key])).test(request.headers[key])) { + matchHeader = false; } + }); + } - keys.forEach((key, index) => { - endpointParams[key.name] = params[index + 1]; - }); - - return true; + if (!matchHeader) { + return false; } - findEndpoint(request) { - let params = {}; - const urlParse = url.parse(request.url, true); - request.path = urlParse.pathname; - request.query = urlParse.query; - - let foundEndpoint = this.app.endpoints.find((endpoint) => { - if (Array.isArray(endpoint.request)) { - if (endpoint.request.find((endpointRequest) => { - return this.isRequestMatch(endpoint, endpointRequest, request, params); - })) { - return true; - } - } else { - if (this.isRequestMatch(endpoint, endpoint.request, request, params)) { - return true; - } - } - }); + let matchBody = true; - if (!foundEndpoint) { - return null; + if (endpointRequest.body) { + Object.keys(endpointRequest.body).forEach((key) => { + if (!request.body[key]) { + matchBody = false; + return; } - foundEndpoint.callCount++; - foundEndpoint = JSON.parse(JSON.stringify(foundEndpoint)); - foundEndpoint.params = params; + if (!(new RegExp(endpointRequest.body[key])).test(request.body[key])) { + matchBody = false; + } + }); + } - return foundEndpoint; + if (!matchBody) { + return false; } - static getEndpointBody(endpoint, endpointResponse) { - if (endpointResponse.body !== undefined) { - return endpointResponse.body; + keys.forEach((key, index) => { + endpointParams[key.name] = params[index + 1]; + }); + + return true; + } + + findEndpoint(request) { + let params = {}; + const urlParse = url.parse(request.url, true); + request.path = urlParse.pathname; + request.query = urlParse.query; + + let foundEndpoint = this.app.endpoints.find((endpoint) => { + if (Array.isArray(endpoint.request)) { + if (endpoint.request.find((endpointRequest) => { + return this.isRequestMatch(endpoint, endpointRequest, request, params); + })) { + return true; + } + } else { + if (this.isRequestMatch(endpoint, endpoint.request, request, params)) { + return true; } + } + }); - const imageMimeTypes = [ - 'image/gif', - 'image/jpeg', - 'image/pjpeg', - 'image/x-png', - 'image/png', - 'image/svg+xml' - ]; + if (!foundEndpoint) { + return null; + } + + foundEndpoint.callCount++; + foundEndpoint = JSON.parse(JSON.stringify(foundEndpoint)); + foundEndpoint.params = params; - const bodyFilePath = path.resolve(endpoint.currentDirectory, endpointResponse.bodyFile); + return foundEndpoint; + } - return fs.readFileSync(bodyFilePath, imageMimeTypes.indexOf(mime.getType(bodyFilePath)) === -1 ? 'utf8' : null); + static getEndpointBody(endpoint, endpointResponse) { + if (endpointResponse.body !== undefined) { + return endpointResponse.body; } + + const imageMimeTypes = [ + 'image/gif', + 'image/jpeg', + 'image/pjpeg', + 'image/x-png', + 'image/png', + 'image/svg+xml' + ]; + + const bodyFilePath = path.resolve(endpoint.currentDirectory, endpointResponse.bodyFile); + + return fs.readFileSync(bodyFilePath, imageMimeTypes.indexOf(mime.getType(bodyFilePath)) === -1 ? 'utf8' : null); + } } module.exports = HttpMockServer; diff --git a/app/package-lock.json b/app/package-lock.json index a3a4fc3..4d3242a 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -332,7 +332,7 @@ "dot-prop": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", - "integrity": "sha1-HxngwuGqDjJ5fEl5nyg3rGr2nFc=", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", "dev": true, "requires": { "is-obj": "1.0.1" @@ -480,7 +480,7 @@ "setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY=" + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" }, "statuses": { "version": "1.3.1", @@ -1049,7 +1049,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8"