diff --git a/app.json b/app.json index b025f3df..5c3a60be 100644 --- a/app.json +++ b/app.json @@ -1,21 +1,19 @@ { - "name": "mockbin", - "description": "Test, mock, and track HTTP requests & responses between libraries, sockets and APIs", - "repository": "https://github.com/Kong/mockbin", - "website": "http://mockbin.org/", - "success_url": "/", - "addons": [ - "openredis" - ], - "keywords": [ - "api", - "bin", - "har", - "http", - "json", - "mock", - "mocking", - "test", - "testing" - ] + "name": "mockbin", + "description": "Test, mock, and track HTTP requests & responses between libraries, sockets and APIs", + "repository": "https://github.com/Kong/mockbin", + "website": "http://mockbin.org/", + "success_url": "/", + "addons": ["openredis"], + "keywords": [ + "api", + "bin", + "har", + "http", + "json", + "mock", + "mocking", + "test", + "testing" + ] } diff --git a/lib/index.js b/lib/index.js index 2e1aa81f..b3dc8835 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,52 +1,62 @@ -'use strict' - -var debug = require('debug')('mockbin') -var express = require('express') -var mw = require('./middleware') -var routes = require('./routes') - -module.exports = function router (options) { - var router = express.Router() - - var defaults = [mw.forwarded, mw.errorHandler, mw.bodyParser, null, mw.cors, mw.poweredBy, mw.negotiateContent] - - var endpoints = [ - { action: 'get', path: '/', route: routes.hello }, - { action: 'all', path: '/ip', route: routes.ips.one }, - { action: 'all', path: '/ips', route: routes.ips.all }, - { action: 'all', path: '/agent', route: routes.headers.agent }, - { action: 'all', path: '/status/:code/:reason?', route: routes.status }, - { action: 'all', path: '/headers', route: routes.headers.all }, - { action: 'all', path: '/header/:name', route: routes.headers.one }, - { action: 'all', path: '/header/:name/:value', route: routes.headers.set }, - { action: 'all', path: '/cookies', route: routes.cookies.all }, - { action: 'all', path: '/forwarded', route: routes.forwarded }, - { action: 'all', path: '/cookie/:name', route: routes.cookies.one }, - { action: 'all', path: '/cookie/:name/:value', route: routes.cookies.set }, - { action: 'all', path: '/redirect/:status_code/:count?', route: routes.redirect }, - { action: 'all', path: '/delay/:ms?', route: routes.delay }, - { action: 'all', path: '/stream/:chunks?', route: routes.stream }, - { action: 'all', path: '/har*', route: routes.har }, - { action: 'all', path: '/echo*', route: routes.echo }, - { action: 'all', path: '/request*', route: routes.request } - ] - - endpoints.forEach(function (endpoint) { - // add route to middleware - defaults.splice(3, 1, endpoint.route) - - // assign router to action at path - router[endpoint.action].apply(router, [endpoint.path].concat(defaults)) - }) - - if (options && options.redis) { - router.use('/bin', routes.bins(options.redis)) - } else { - debug('no redis dsn provided, will not load bin routes') - } - - // duplicate routes with gzip forced - router.use('/gzip', routes.gzip, mw.compression, Object.assign(router)) - - return router -} +const debug = require("debug")("mockbin"); +const express = require("express"); +const mw = require("./middleware"); +const routes = require("./routes"); + +module.exports = function router(options) { + const router = express.Router(); + + const defaults = [ + mw.forwarded, + mw.errorHandler, + mw.bodyParser, + null, + mw.cors, + mw.poweredBy, + mw.negotiateContent, + ]; + + const endpoints = [ + { action: "get", path: "/", route: routes.hello }, + { action: "all", path: "/ip", route: routes.ips.one }, + { action: "all", path: "/ips", route: routes.ips.all }, + { action: "all", path: "/agent", route: routes.headers.agent }, + { action: "all", path: "/status/:code/:reason?", route: routes.status }, + { action: "all", path: "/headers", route: routes.headers.all }, + { action: "all", path: "/header/:name", route: routes.headers.one }, + { action: "all", path: "/header/:name/:value", route: routes.headers.set }, + { action: "all", path: "/cookies", route: routes.cookies.all }, + { action: "all", path: "/forwarded", route: routes.forwarded }, + { action: "all", path: "/cookie/:name", route: routes.cookies.one }, + { action: "all", path: "/cookie/:name/:value", route: routes.cookies.set }, + { + action: "all", + path: "/redirect/:status_code/:count?", + route: routes.redirect, + }, + { action: "all", path: "/delay/:ms?", route: routes.delay }, + { action: "all", path: "/stream/:chunks?", route: routes.stream }, + { action: "all", path: "/har*", route: routes.har }, + { action: "all", path: "/echo*", route: routes.echo }, + { action: "all", path: "/request*", route: routes.request }, + ]; + + endpoints.forEach((endpoint) => { + // add route to middleware + defaults.splice(3, 1, endpoint.route); + + // assign router to action at path + router[endpoint.action].apply(router, [endpoint.path].concat(defaults)); + }); + + if (options?.redis) { + router.use("/bin", routes.bins(options.redis)); + } else { + debug("no redis dsn provided, will not load bin routes"); + } + + // duplicate routes with gzip forced + router.use("/gzip", routes.gzip, mw.compression, Object.assign(router)); + + return router; +}; diff --git a/lib/middleware/body-parser.js b/lib/middleware/body-parser.js index 29a7d818..8bbd0864 100644 --- a/lib/middleware/body-parser.js +++ b/lib/middleware/body-parser.js @@ -1,159 +1,160 @@ -var Dicer = require("dicer"); -var querystring = require("querystring"); -var contentTypeParser = require("content-type"); -var util = require("../utils"); +const Dicer = require("dicer"); +const querystring = require("querystring"); +const contentTypeParser = require("content-type"); +const util = require("../utils"); const parseContentType = (contentTypeHeader) => { - if (!contentTypeHeader) { - return { contentType: null }; - } - var { type, parameters } = contentTypeParser.parse(contentTypeHeader); - return { - contentType: type.replace(/\+$/, ""), - parameters, - }; + if (!contentTypeHeader) { + return { contentType: null }; + } + const { type, parameters } = contentTypeParser.parse(contentTypeHeader); + return { + contentType: type.replace(/\+$/, ""), + parameters, + }; }; module.exports = (req, res, next) => { - req.bodyChunks = []; - - req.on("data", (chunk) => { - req.bodyChunks.push(chunk); - }); - - req.on("end", () => { - req.rawBody = Buffer.concat(req.bodyChunks); - req.body = req.rawBody.toString("utf8"); - req.bodySize = req.rawBody.length; - req.jsonBody = null; - req.formBody = null; - req.contentType = null; - req.multiPartSimple = {}; - - // parse Content-Type - var contentTypeHeader = req.headers["content-type"]; - var { contentType, parameters } = parseContentType(contentTypeHeader); - - if (contentType) { - req.contentType = contentType; - } - - // create HAR Object - req.har = util.createHar(req); - req.simple = util.createSimpleHar(req); - - switch (req.contentType) { - case "application/json": - try { - req.jsonBody = JSON.parse(req.body); - } catch (exception) { } - - next(); - break; - - case "application/x-www-form-urlencoded": - req.formBody = querystring.parse(req.body); - - // update HAR objects - req.simple.postData.params = req.formBody; - req.har.log.entries[0].request.postData.params = util.objectToArray( - req.formBody, - ); - - next(); - break; - - case "multipart/mixed": - case "multipart/related": - case "multipart/form-data": - case "multipart/alternate": - req.multiPartData = []; - req.multiPartParams = []; - - // parse a file upload - var dice = new Dicer({ - boundary: parameters.boundary, - }); - - dice.on("part", (part) => { - part.on("data", (data) => { - req.multiPartData.push(data.toString("utf8")); - }); - - part.on("header", (headers) => { - var param = {}; - - if (headers["content-disposition"]) { - var disposition = contentTypeParser.parse( - headers["content-disposition"][0].replace( - "form-data", - "form-data/text", - ) || "form-data/text", - ); - - param.name = disposition.parameters.name; - - if (disposition.parameters.filename) { - param.fileName = disposition.parameters.filename; - } - } - - if (headers["content-type"]) { - var { contentType: partContentType } = parseContentType( - headers["content-type"][0] || "application/octet-stream", - ); - - param.contentType = partContentType; - } - - req.multiPartParams.push(param); - }); - }); - - dice.on("finish", () => { - // createa a new simple object param - req.multiPart = req.multiPartParams.map((param, index) => { - // append value to pair - param.value = req.multiPartData[index]; - - switch (typeof req.multiPartSimple[param.name]) { - case "undefined": - req.multiPartSimple[param.name] = param.value; - break; - - // array - case "object": - req.multiPartSimple[param.name].push(param.value); - break; - - case "string": - // this exists? must be an array, make it so - req.multiPartSimple[param.name] = [ - req.multiPartSimple[param.name], - ]; - req.multiPartSimple[param.name].push(param.value); - break; - } - - return param; - }); - - // update HAR objects - req.simple.postData.params = req.multiPartSimple - ? req.multiPartSimple - : []; - req.har.log.entries[0].request.postData.params = req.multiPart - ? req.multiPart - : []; - - next(); - }); - - dice.write(req.body); - break; - - default: - next(); - } - }); + req.bodyChunks = []; + + req.on("data", (chunk) => { + req.bodyChunks.push(chunk); + }); + + req.on("end", () => { + req.rawBody = Buffer.concat(req.bodyChunks); + req.body = req.rawBody.toString("utf8"); + req.bodySize = req.rawBody.length; + req.jsonBody = null; + req.formBody = null; + req.contentType = null; + req.multiPartSimple = {}; + + // parse Content-Type + const contentTypeHeader = req.headers["content-type"]; + const { contentType, parameters } = parseContentType(contentTypeHeader); + + if (contentType) { + req.contentType = contentType; + } + + // create HAR Object + req.har = util.createHar(req); + req.simple = util.createSimpleHar(req); + + switch (req.contentType) { + case "application/json": + try { + req.jsonBody = JSON.parse(req.body); + } catch (exception) {} + + next(); + break; + + case "application/x-www-form-urlencoded": + req.formBody = querystring.parse(req.body); + + // update HAR objects + req.simple.postData.params = req.formBody; + req.har.log.entries[0].request.postData.params = util.objectToArray( + req.formBody, + ); + + next(); + break; + + case "multipart/mixed": + case "multipart/related": + case "multipart/form-data": + case "multipart/alternate": { + req.multiPartData = []; + req.multiPartParams = []; + + // parse a file upload + const dice = new Dicer({ + boundary: parameters.boundary, + }); + + dice.on("part", (part) => { + part.on("data", (data) => { + req.multiPartData.push(data.toString("utf8")); + }); + + part.on("header", (headers) => { + const param = {}; + + if (headers["content-disposition"]) { + const disposition = contentTypeParser.parse( + headers["content-disposition"][0].replace( + "form-data", + "form-data/text", + ) || "form-data/text", + ); + + param.name = disposition.parameters.name; + + if (disposition.parameters.filename) { + param.fileName = disposition.parameters.filename; + } + } + + if (headers["content-type"]) { + const { contentType: partContentType } = parseContentType( + headers["content-type"][0] || "application/octet-stream", + ); + + param.contentType = partContentType; + } + + req.multiPartParams.push(param); + }); + }); + + dice.on("finish", () => { + // createa a new simple object param + req.multiPart = req.multiPartParams.map((param, index) => { + // append value to pair + param.value = req.multiPartData[index]; + + switch (typeof req.multiPartSimple[param.name]) { + case "undefined": + req.multiPartSimple[param.name] = param.value; + break; + + // array + case "object": + req.multiPartSimple[param.name].push(param.value); + break; + + case "string": + // this exists? must be an array, make it so + req.multiPartSimple[param.name] = [ + req.multiPartSimple[param.name], + ]; + req.multiPartSimple[param.name].push(param.value); + break; + } + + return param; + }); + + // update HAR objects + req.simple.postData.params = req.multiPartSimple + ? req.multiPartSimple + : []; + req.har.log.entries[0].request.postData.params = req.multiPart + ? req.multiPart + : []; + + next(); + }); + + dice.write(req.body); + break; + } + + default: + next(); + } + }); }; diff --git a/lib/middleware/compression.js b/lib/middleware/compression.js index d9b86117..005495f4 100644 --- a/lib/middleware/compression.js +++ b/lib/middleware/compression.js @@ -1,10 +1,6 @@ -'use strict' - -var compression = require('compression') +const compression = require("compression"); module.exports = compression({ - threshold: 1, - filter: function () { - return true - } -}) + threshold: 1, + filter: () => true, +}); diff --git a/lib/middleware/cors.js b/lib/middleware/cors.js index 282257f8..ef35278c 100644 --- a/lib/middleware/cors.js +++ b/lib/middleware/cors.js @@ -1,31 +1,29 @@ -'use strict' +module.exports = (req, res, next) => { + // default values + const cors = { + origin: "*", + headers: Object.keys(req.headers).join(), + methods: req.method, + }; -module.exports = function (req, res, next) { - // default values - var cors = { - origin: '*', - headers: Object.keys(req.headers).join(), - methods: req.method - } + if (req.headers.origin) { + cors.origin = req.headers.origin; + } - if (req.headers.origin) { - cors.origin = req.headers.origin - } + if (req.headers["access-control-request-headers"]) { + cors.headers = req.headers["access-control-request-headers"]; + } - if (req.headers['access-control-request-headers']) { - cors.headers = req.headers['access-control-request-headers'] - } + if (req.headers["access-control-request-method"]) { + cors.methods = req.headers["access-control-request-method"]; + } - if (req.headers['access-control-request-method']) { - cors.methods = req.headers['access-control-request-method'] - } + res.set({ + "Access-Control-Allow-Origin": cors.origin, + "Access-Control-Allow-Methods": cors.methods, + "Access-Control-Allow-Headers": cors.headers, + "Access-Control-Allow-Credentials": "true", + }); - res.set({ - 'Access-Control-Allow-Origin': cors.origin, - 'Access-Control-Allow-Methods': cors.methods, - 'Access-Control-Allow-Headers': cors.headers, - 'Access-Control-Allow-Credentials': 'true' - }) - - next() -} + next(); +}; diff --git a/lib/middleware/error-handler.js b/lib/middleware/error-handler.js index 22df697c..ffa13b0f 100644 --- a/lib/middleware/error-handler.js +++ b/lib/middleware/error-handler.js @@ -1,11 +1,9 @@ -'use strict' +const debug = require("debug")("mockbin"); -var debug = require('debug')('mockbin') +module.exports = (err, req, res, next) => { + debug(err); -module.exports = function (err, req, res, next) { - debug(err) + res.status(err.status || 500).view = "error"; - res.status(err.status || 500).view = 'error' - - next() -} + next(); +}; diff --git a/lib/middleware/forwarded.js b/lib/middleware/forwarded.js index 84024354..27301d12 100644 --- a/lib/middleware/forwarded.js +++ b/lib/middleware/forwarded.js @@ -1,5 +1,3 @@ -'use strict' +const forwarded = require("forwarded-http/lib/middleware"); -var forwarded = require('forwarded-http/lib/middleware') - -module.exports = forwarded({ allowPrivate: true }) +module.exports = forwarded({ allowPrivate: true }); diff --git a/lib/middleware/index.js b/lib/middleware/index.js index d4afe496..e0a6c6e1 100644 --- a/lib/middleware/index.js +++ b/lib/middleware/index.js @@ -1,9 +1,5 @@ -'use strict' +const changeCase = require("change-case"); -var changeCase = require('change-case') - -module.exports = require('require-directory')(module, { - rename: function (name) { - return changeCase.camelCase(name) - } -}) +module.exports = require("require-directory")(module, { + rename: (name) => changeCase.camelCase(name), +}); diff --git a/lib/middleware/negotiate-content.js b/lib/middleware/negotiate-content.js index 849b2344..d5adc08d 100644 --- a/lib/middleware/negotiate-content.js +++ b/lib/middleware/negotiate-content.js @@ -1,84 +1,90 @@ -'use strict' - -var moment = require('moment') -var XML = require('xmlbuilder') -var YAML = require('yamljs') - -module.exports = function (req, res, next) { - res.bodyXmlObj = { - response: res.body - } - - // am I pretty? - var spaces = req.headers['x-pretty-print'] ? parseInt(req.headers['x-pretty-print'], 10) : 2 - - var xmlOpts = { - pretty: (spaces > 0), - indent: new Array(spaces).join(' '), - newline: '\n' - } - - function YAMLResponse () { - if (typeof res.body === 'string') { - return res.send(res.body) - } - - res.send(YAML.stringify(res.body, 6, spaces)) - } - - function JSONResponse () { - req.app.set('json spaces', spaces) - - res.jsonp(res.body) - } - - function XMLResponse () { - res.send(XML.create(res.bodyXmlObj || res.body, { allowSurrogateChars: true }).end(xmlOpts)) - } - - function HTMLResponse () { - req.app.locals.moment = moment - XML.create(res.bodyXmlObj, { allowSurrogateChars: true }) - res.render(res.view || 'default', { - req: req, - res: res, - data: { - raw: res.body, - yaml: YAML.stringify(res.body, res.yamlInline || 3, 2), - - json: JSON.stringify(res.body, null, 2), - - xml: XML.create(res.bodyXmlObj || res.body, { allowSurrogateChars: true }).end(xmlOpts) - } - }) - } - - res.format({ - 'application/json': JSONResponse, - 'text/json': JSONResponse, - 'text/x-json': JSONResponse, - 'application/x-json': JSONResponse, - - 'text/javascript': JSONResponse, - 'application/javascript': JSONResponse, - 'application/x-javascript': JSONResponse, - - 'text/xml': XMLResponse, - 'application/xml': XMLResponse, - 'application/x-xml': XMLResponse, - - 'text/html': HTMLResponse, - 'application/xhtml+xml': HTMLResponse, - - 'text/yaml': YAMLResponse, - 'text/x-yaml': YAMLResponse, - 'application/yaml': YAMLResponse, - 'application/x-yaml': YAMLResponse, - - 'text/plain': YAMLResponse, - - default: JSONResponse - }) - - next() -} +const moment = require("moment"); +const XML = require("xmlbuilder"); +const YAML = require("yamljs"); + +module.exports = (req, res, next) => { + res.bodyXmlObj = { + response: res.body, + }; + + // am I pretty? + const spaces = req.headers["x-pretty-print"] + ? parseInt(req.headers["x-pretty-print"], 10) + : 2; + + const xmlOpts = { + pretty: spaces > 0, + indent: new Array(spaces).join(" "), + newline: "\n", + }; + + function YAMLResponse() { + if (typeof res.body === "string") { + return res.send(res.body); + } + + res.send(YAML.stringify(res.body, 6, spaces)); + } + + function JSONResponse() { + req.app.set("json spaces", spaces); + + res.jsonp(res.body); + } + + function XMLResponse() { + res.send( + XML.create(res.bodyXmlObj || res.body, { allowSurrogateChars: true }).end( + xmlOpts, + ), + ); + } + + function HTMLResponse() { + req.app.locals.moment = moment; + XML.create(res.bodyXmlObj, { allowSurrogateChars: true }); + res.render(res.view || "default", { + req: req, + res: res, + data: { + raw: res.body, + yaml: YAML.stringify(res.body, res.yamlInline || 3, 2), + + json: JSON.stringify(res.body, null, 2), + + xml: XML.create(res.bodyXmlObj || res.body, { + allowSurrogateChars: true, + }).end(xmlOpts), + }, + }); + } + + res.format({ + "application/json": JSONResponse, + "text/json": JSONResponse, + "text/x-json": JSONResponse, + "application/x-json": JSONResponse, + + "text/javascript": JSONResponse, + "application/javascript": JSONResponse, + "application/x-javascript": JSONResponse, + + "text/xml": XMLResponse, + "application/xml": XMLResponse, + "application/x-xml": XMLResponse, + + "text/html": HTMLResponse, + "application/xhtml+xml": HTMLResponse, + + "text/yaml": YAMLResponse, + "text/x-yaml": YAMLResponse, + "application/yaml": YAMLResponse, + "application/x-yaml": YAMLResponse, + + "text/plain": YAMLResponse, + + default: JSONResponse, + }); + + next(); +}; diff --git a/lib/middleware/not-found-handler.js b/lib/middleware/not-found-handler.js index 522aa36d..cf23b41f 100644 --- a/lib/middleware/not-found-handler.js +++ b/lib/middleware/not-found-handler.js @@ -1,14 +1,12 @@ -'use strict' +module.exports = (req, res, next) => { + res.view = 404; -module.exports = function (req, res, next) { - res.view = 404 + res.status(404).body = { + error: { + code: "404", + message: "Not Found", + }, + }; - res.status(404).body = { - error: { - code: '404', - message: 'Not Found' - } - } - - next() -} + next(); +}; diff --git a/lib/middleware/powered-by.js b/lib/middleware/powered-by.js index 57849dec..0c4b54ba 100644 --- a/lib/middleware/powered-by.js +++ b/lib/middleware/powered-by.js @@ -1,9 +1,7 @@ -'use strict' +module.exports = (req, res, next) => { + req.app.disable("x-powered-by"); -module.exports = function (req, res, next) { - req.app.disable('x-powered-by') + res.set("X-Powered-By", "mockbin"); - res.set('X-Powered-By', 'mockbin') - - next() -} + next(); +}; diff --git a/lib/routes/bins.js b/lib/routes/bins.js index dd1f2b71..3c359460 100644 --- a/lib/routes/bins.js +++ b/lib/routes/bins.js @@ -1,65 +1,64 @@ -var debug = require('debug')('mockbin') -var express = require('express') -var mw = require('../middleware') -var redis = require('redis') -var routes = require('./bins/') -var URL = require('url').URL +const debug = require("debug")("mockbin"); +const express = require("express"); +const mw = require("../middleware"); +const redis = require("redis"); +const routes = require("./bins/"); +const URL = require("url").URL; -module.exports = function bins (dsnStr) { - // parse redis dsn - var dsn = new URL(dsnStr) +module.exports = function bins(dsnStr) { + // parse redis dsn + const dsn = new URL(dsnStr); - this.dsn = dsn + this.dsn = dsn; - // connect to redis - this.client = redis.createClient( - { - host: dsn.hostname, - port: dsn.port, - no_ready_check: true - }) + // connect to redis + this.client = redis.createClient({ + host: dsn.hostname, + port: dsn.port, + no_ready_check: true, + }); - // Disable client's AUTH command. - this.client.auth = null - this.client.send_command('AUTH', [dsn.username, dsn.password]) + // Disable client's AUTH command. + this.client.auth = null; + this.client.send_command("AUTH", [dsn.username, dsn.password]); - this.client.on('error', (err) => { - debug('redis error:', err) - }) + this.client.on("error", (err) => { + debug("redis error:", err); + }); - var router = express.Router() + const router = express.Router(); - var defaults = [ - mw.forwarded, - mw.errorHandler, - mw.bodyParser, - null, - mw.cors, - mw.negotiateContent - ] + const defaults = [ + mw.forwarded, + mw.errorHandler, + mw.bodyParser, + null, + mw.cors, + mw.negotiateContent, + ]; - var endpoints = [ - { action: 'get', path: '/create', route: routes.form.bind(this) }, - { action: 'post', path: '/create', route: routes.create.bind(this) }, - { action: 'get', path: '/:uuid/view', route: routes.view.bind(this) }, - { action: 'get', path: '/:uuid/sample', route: routes.sample.bind(this) }, - { action: 'get', path: '/:uuid/log', route: routes.log.bind(this) }, - { - action: 'delete', - path: '/:uuid/delete', - route: routes.delete.bind(this) - }, - { action: 'put', path: '/:uuid', route: routes.update.bind(this) }, - { action: 'all', path: '/:uuid*', route: routes.run.bind(this) } - ] + const endpoints = [ + { action: "get", path: "/create", route: routes.form.bind(this) }, + { action: "post", path: "/create", route: routes.create.bind(this) }, + { action: "get", path: "/:uuid/view", route: routes.view.bind(this) }, + { action: "get", path: "/:uuid/sample", route: routes.sample.bind(this) }, + { action: "get", path: "/:uuid/log", route: routes.log.bind(this) }, + { + action: "delete", + path: "/:uuid/delete", + route: routes.delete.bind(this), + }, + { action: "put", path: "/:uuid", route: routes.update.bind(this) }, + { action: "all", path: "/:uuid*", route: routes.run.bind(this) }, + ]; - endpoints.forEach((endpoint) => { - // add route to middleware - defaults.splice(3, 1, endpoint.route) + endpoints.forEach((endpoint) => { + // add route to middleware + defaults.splice(3, 1, endpoint.route); - // assign router to action at path - router[endpoint.action].apply(router, [endpoint.path].concat(defaults)) - }) + // assign router to action at path + router[endpoint.action].apply(router, [endpoint.path].concat(defaults)); + }); - return router -} + return router; +}; diff --git a/lib/routes/bins/create.js b/lib/routes/bins/create.js index 34d7c5c7..44cee6b8 100644 --- a/lib/routes/bins/create.js +++ b/lib/routes/bins/create.js @@ -1,63 +1,64 @@ -'use strict' - -var debug = require('debug')('mockbin') -var util = require('util') -var uuid = require('uuid') -var validate = require('har-validator') +const debug = require("debug")("mockbin"); +const util = require("util"); +const uuid = require("uuid"); +const validate = require("har-validator"); module.exports = async function (req, res, next) { - var mock = req.jsonBody - - // check for full HAR - if (req.jsonBody && req.jsonBody.response) { - mock = req.jsonBody.response - } - - // exception for the web Form - // TODO eliminate this and rely on req.simple.postData.text - if (req.simple.postData.params && req.simple.postData.params.response) { - try { - mock = JSON.parse(req.simple.postData.params.response) - } catch (e) { - debug(e) - } - } - - // overritten by application/x-www-form-urlencoded or multipart/form-data - if (req.simple.postData.text) { - try { - mock = JSON.parse(req.simple.postData.text) - } catch (e) { - debug(e) - } - } - - // provide optional values before validation - mock.redirectURL = '' - mock.bodySize = 0 - mock.headersSize = 0 - - if (!mock.content) { - mock.content = {} - } - - mock.content.size = 0 - - await validate.response(mock) - .then(function () { - var id = uuid.v4() - - this.client.set('bin:' + id, JSON.stringify(mock)) - - res.view = 'redirect' - res.status(201).location(util.format('/bin/%s', id)).body = id - }.bind(this)) - - .catch(function (err) { - res.body = { - errors: err.errors - } - }) - - .then(next) -} + let mock = req.jsonBody; + + // check for full HAR + if (req.jsonBody?.response) { + mock = req.jsonBody.response; + } + + // exception for the web Form + // TODO eliminate this and rely on req.simple.postData.text + if (req.simple.postData.params?.response) { + try { + mock = JSON.parse(req.simple.postData.params.response); + } catch (e) { + debug(e); + } + } + + // overritten by application/x-www-form-urlencoded or multipart/form-data + if (req.simple.postData.text) { + try { + mock = JSON.parse(req.simple.postData.text); + } catch (e) { + debug(e); + } + } + + // provide optional values before validation + mock.redirectURL = ""; + mock.bodySize = 0; + mock.headersSize = 0; + + if (!mock.content) { + mock.content = {}; + } + + mock.content.size = 0; + + await validate + .response(mock) + .then( + function () { + const id = uuid.v4(); + + this.client.set(`bin:${id}`, JSON.stringify(mock)); + + res.view = "redirect"; + res.status(201).location(util.format("/bin/%s", id)).body = id; + }.bind(this), + ) + + .catch((err) => { + res.body = { + errors: err.errors, + }; + }) + + .then(next); +}; diff --git a/lib/routes/bins/delete.js b/lib/routes/bins/delete.js index 552078f7..8638612f 100644 --- a/lib/routes/bins/delete.js +++ b/lib/routes/bins/delete.js @@ -1,21 +1,21 @@ -var debug = require('debug')('mockbin') +const debug = require("debug")("mockbin"); module.exports = function (req, res, next) { - this.client.del('bin:' + req.params.uuid, (err) => { - if (err) { - debug(err) + this.client.del(`bin:${req.params.uuid}`, (err) => { + if (err) { + debug(err); - throw err - } - next() - }) + throw err; + } + next(); + }); - this.client.del('log:' + req.params.uuid, (err) => { - if (err) { - debug(err) + this.client.del(`log:${req.params.uuid}`, (err) => { + if (err) { + debug(err); - throw err - } - next() - }) -} + throw err; + } + next(); + }); +}; diff --git a/lib/routes/bins/form.js b/lib/routes/bins/form.js index 0ab7d7cd..5f0a258f 100644 --- a/lib/routes/bins/form.js +++ b/lib/routes/bins/form.js @@ -1,7 +1,5 @@ -'use strict' +module.exports = (req, res, next) => { + res.view = "bin/create"; -module.exports = function (req, res, next) { - res.view = 'bin/create' - - next() -} + next(); +}; diff --git a/lib/routes/bins/index.js b/lib/routes/bins/index.js index 9dc1432d..b2a403e8 100644 --- a/lib/routes/bins/index.js +++ b/lib/routes/bins/index.js @@ -1,3 +1 @@ -'use strict' - -module.exports = require('require-directory')(module) +module.exports = require("require-directory")(module); diff --git a/lib/routes/bins/log.js b/lib/routes/bins/log.js index 7682d94e..6f1b27bb 100644 --- a/lib/routes/bins/log.js +++ b/lib/routes/bins/log.js @@ -1,35 +1,31 @@ -'use strict' - -var debug = require('debug')('mockbin') -var pkg = require('../../../package.json') +const debug = require("debug")("mockbin"); +const pkg = require("../../../package.json"); module.exports = function (req, res, next) { - res.view = 'bin/log' + res.view = "bin/log"; - this.client.lrange('log:' + req.params.uuid, 0, -1, function (err, history) { - if (err) { - debug(err) + this.client.lrange(`log:${req.params.uuid}`, 0, -1, (err, history) => { + if (err) { + debug(err); - throw err - } + throw err; + } - res.body = { - log: { - version: '1.2', - creator: { - name: 'mockbin.com', - version: pkg.version - }, - entries: [] - } - } + res.body = { + log: { + version: "1.2", + creator: { + name: "mockbin.com", + version: pkg.version, + }, + entries: [], + }, + }; - if (history.length) { - res.body.log.entries = history.map(function (request) { - return JSON.parse(request) - }) - } + if (history.length) { + res.body.log.entries = history.map((request) => JSON.parse(request)); + } - next() - }) -} + next(); + }); +}; diff --git a/lib/routes/bins/run.js b/lib/routes/bins/run.js index 7144ee53..b193efa2 100644 --- a/lib/routes/bins/run.js +++ b/lib/routes/bins/run.js @@ -1,45 +1,49 @@ -'use strict' - -var debug = require('debug')('mockbin') +const debug = require("debug")("mockbin"); module.exports = function (req, res, next) { - this.client.get('bin:' + req.params.uuid, function (err, value) { - if (err) { - debug(err) - - throw err - } - - if (value) { - var har = JSON.parse(value) - - // log interaction & send the appropriate response based on HAR - this.client.rpush('log:' + req.params.uuid, JSON.stringify(req.har.log.entries[0])) - this.client.ltrim('log:' + req.params.uuid, 0, 100) - - // headers - har.headers.map(function (header) { - res.set(header.name, header.value) - }) - - // cookies - har.cookies.map(function (cookie) { - res.cookie(cookie.name, cookie.value) - }) - - // status - res.httpVersion = har.httpVersion.split('/')[1] - res.statusCode = har.status || 200 - res.statusMessage = har.statusText || 'OK' - - // special condition - if (har.redirectURL !== '') { - res.location(har.redirectURL) - } - - return res.send(har.content.text ? har.content.text : null) - } - - next() - }.bind(this)) -} + this.client.get( + `bin:${req.params.uuid}`, + function (err, value) { + if (err) { + debug(err); + + throw err; + } + + if (value) { + const har = JSON.parse(value); + + // log interaction & send the appropriate response based on HAR + this.client.rpush( + `log:${req.params.uuid}`, + JSON.stringify(req.har.log.entries[0]), + ); + this.client.ltrim(`log:${req.params.uuid}`, 0, 100); + + // headers + har.headers.map((header) => { + res.set(header.name, header.value); + }); + + // cookies + har.cookies.map((cookie) => { + res.cookie(cookie.name, cookie.value); + }); + + // status + res.httpVersion = har.httpVersion.split("/")[1]; + res.statusCode = har.status || 200; + res.statusMessage = har.statusText || "OK"; + + // special condition + if (har.redirectURL !== "") { + res.location(har.redirectURL); + } + + return res.send(har.content.text ? har.content.text : null); + } + + next(); + }.bind(this), + ); +}; diff --git a/lib/routes/bins/sample.js b/lib/routes/bins/sample.js index 50a42912..40d7ddfe 100644 --- a/lib/routes/bins/sample.js +++ b/lib/routes/bins/sample.js @@ -1,63 +1,68 @@ -'use strict' - -var debug = require('debug')('mockbin') -var util = require('util') +const debug = require("debug")("mockbin"); +const util = require("util"); module.exports = function (req, res, next) { - this.client.get('bin:' + req.params.uuid, function (err, value) { - if (err) { - debug(err) + this.client.get(`bin:${req.params.uuid}`, (err, value) => { + if (err) { + debug(err); - throw err - } + throw err; + } - if (value) { - res.json({ - method: 'POST', - url: util.format('%s://%s/bin/%s', req.protocol, req.hostname, req.params.uuid), - httpVersion: 'HTTP/1.1', - queryString: [ - { - name: 'foo', - value: 'bar' - }, - { - name: 'foo', - value: 'baz' - } - ], - headers: [ - { - name: 'Accept', - value: 'application/json' - }, - { - name: 'Content-Type', - value: 'application/x-www-form-urlencoded' - } - ], - cookies: [ - { - name: 'foo', - value: 'bar' - }, - { - name: 'bar', - value: 'baz' - } - ], - postData: { - mimeType: 'application/x-www-form-urlencoded', - params: [{ - name: 'foo', - value: 'bar' - }, - { - name: 'bar', - value: 'baz' - }] - } - }) - } - }) -} + if (value) { + res.json({ + method: "POST", + url: util.format( + "%s://%s/bin/%s", + req.protocol, + req.hostname, + req.params.uuid, + ), + httpVersion: "HTTP/1.1", + queryString: [ + { + name: "foo", + value: "bar", + }, + { + name: "foo", + value: "baz", + }, + ], + headers: [ + { + name: "Accept", + value: "application/json", + }, + { + name: "Content-Type", + value: "application/x-www-form-urlencoded", + }, + ], + cookies: [ + { + name: "foo", + value: "bar", + }, + { + name: "bar", + value: "baz", + }, + ], + postData: { + mimeType: "application/x-www-form-urlencoded", + params: [ + { + name: "foo", + value: "bar", + }, + { + name: "bar", + value: "baz", + }, + ], + }, + }); + } + }); +}; diff --git a/lib/routes/bins/update.js b/lib/routes/bins/update.js index 6af0ad4e..ffd900c5 100644 --- a/lib/routes/bins/update.js +++ b/lib/routes/bins/update.js @@ -1,62 +1,62 @@ -var debug = require('debug')('mockbin') -var util = require('util') -var validate = require('har-validator') +const debug = require("debug")("mockbin"); +const util = require("util"); +const validate = require("har-validator"); module.exports = function (req, res, next) { - var id = req.params.uuid - var mock = req.jsonBody - - // check for full HAR - if (req.jsonBody && req.jsonBody.response) { - mock = req.jsonBody.response - } - - // exception for the web Form - // TODO eliminate this and rely on req.simple.postData.text - if (req.simple.postData.params && req.simple.postData.params.response) { - try { - mock = JSON.parse(req.simple.postData.params.response) - } catch (e) { - debug(e) - } - } - - // overritten by application/x-www-form-urlencoded or multipart/form-data - if (req.simple.postData.text) { - try { - mock = JSON.parse(req.simple.postData.text) - } catch (e) { - debug(e) - } - } - - // provide optional values before validation - mock.redirectURL = '' - mock.bodySize = 0 - mock.headersSize = 0 - - if (!mock.content) { - mock.content = {} - } - - mock.content.size = 0 - - validate - .response(mock) - .then( - function () { - this.client.set('bin:' + id, JSON.stringify(mock)) - - res.view = 'redirect' - res.status(200).location(util.format('/bin/%s', id)).body = id - }.bind(this) - ) - - .catch((err) => { - res.body = { - errors: err.errors - } - }) - - .then(next) -} + const id = req.params.uuid; + let mock = req.jsonBody; + + // check for full HAR + if (req.jsonBody?.response) { + mock = req.jsonBody.response; + } + + // exception for the web Form + // TODO eliminate this and rely on req.simple.postData.text + if (req.simple.postData.params?.response) { + try { + mock = JSON.parse(req.simple.postData.params.response); + } catch (e) { + debug(e); + } + } + + // overritten by application/x-www-form-urlencoded or multipart/form-data + if (req.simple.postData.text) { + try { + mock = JSON.parse(req.simple.postData.text); + } catch (e) { + debug(e); + } + } + + // provide optional values before validation + mock.redirectURL = ""; + mock.bodySize = 0; + mock.headersSize = 0; + + if (!mock.content) { + mock.content = {}; + } + + mock.content.size = 0; + + validate + .response(mock) + .then( + function () { + this.client.set(`bin:${id}`, JSON.stringify(mock)); + + res.view = "redirect"; + res.status(200).location(util.format("/bin/%s", id)).body = id; + }.bind(this), + ) + + .catch((err) => { + res.body = { + errors: err.errors, + }; + }) + + .then(next); +}; diff --git a/lib/routes/bins/view.js b/lib/routes/bins/view.js index 84922ba3..338d907a 100644 --- a/lib/routes/bins/view.js +++ b/lib/routes/bins/view.js @@ -1,22 +1,20 @@ -'use strict' - -var debug = require('debug')('mockbin') +const debug = require("debug")("mockbin"); module.exports = function (req, res, next) { - this.client.get('bin:' + req.params.uuid, function (err, value) { - if (err) { - debug(err) + this.client.get(`bin:${req.params.uuid}`, (err, value) => { + if (err) { + debug(err); - throw err - } + throw err; + } - if (value) { - var har = JSON.parse(value) + if (value) { + const har = JSON.parse(value); - res.view = 'bin/view' - res.body = har - } + res.view = "bin/view"; + res.body = har; + } - next() - }) -} + next(); + }); +}; diff --git a/lib/routes/cookies.js b/lib/routes/cookies.js index e804c003..c8df4bf4 100644 --- a/lib/routes/cookies.js +++ b/lib/routes/cookies.js @@ -1,25 +1,27 @@ -'use strict' - module.exports = { - one: function oneCookie (req, res, next) { - var name = req.params.name.toLowerCase() + one: function oneCookie(req, res, next) { + const name = req.params.name.toLowerCase(); - res.body = req.cookies ? (req.cookies[name] ? req.cookies[name] : false) : false + res.body = req.cookies + ? req.cookies[name] + ? req.cookies[name] + : false + : false; - next() - }, + next(); + }, - set: function setCookie (req, res, next) { - res.cookie(req.params.name, req.params.value) + set: function setCookie(req, res, next) { + res.cookie(req.params.name, req.params.value); - res.body = req.params.value + res.body = req.params.value; - next() - }, + next(); + }, - all: function allCookies (req, res, next) { - res.body = req.har.log.entries[0].request.cookies + all: function allCookies(req, res, next) { + res.body = req.har.log.entries[0].request.cookies; - next() - } -} + next(); + }, +}; diff --git a/lib/routes/delay.js b/lib/routes/delay.js index efc1fc90..992725b3 100644 --- a/lib/routes/delay.js +++ b/lib/routes/delay.js @@ -1,17 +1,15 @@ -'use strict' +module.exports = function delay(req, res, next) { + let delay = req.params.ms ? parseInt(req.params.ms, 10) : 200; -module.exports = function delay (req, res, next) { - var delay = req.params.ms ? parseInt(req.params.ms, 10) : 200 + if (delay > 60000) { + delay = 60000; + } - if (delay > 60000) { - delay = 60000 - } + setTimeout(() => { + res.body = { + delay: delay, + }; - setTimeout(function () { - res.body = { - delay: delay - } - - next() - }, delay) -} + next(); + }, delay); +}; diff --git a/lib/routes/echo.js b/lib/routes/echo.js index 6cb05073..cdf10c9b 100644 --- a/lib/routes/echo.js +++ b/lib/routes/echo.js @@ -1,6 +1,4 @@ -'use strict' - -module.exports = function echo (req, res) { - res.type(req.headers['content-type'] || 'text/plain') - res.send(req.body || '') -} +module.exports = function echo(req, res) { + res.type(req.headers["content-type"] || "text/plain"); + res.send(req.body || ""); +}; diff --git a/lib/routes/forwarded.js b/lib/routes/forwarded.js index 93d6bdcf..c620d4fc 100644 --- a/lib/routes/forwarded.js +++ b/lib/routes/forwarded.js @@ -1,7 +1,5 @@ -'use strict' +module.exports = function forwarded(req, res, next) { + res.body = req.forwarded; -module.exports = function forwarded (req, res, next) { - res.body = req.forwarded - - next() -} + next(); +}; diff --git a/lib/routes/gzip.js b/lib/routes/gzip.js index 693acea4..56b58038 100644 --- a/lib/routes/gzip.js +++ b/lib/routes/gzip.js @@ -1,8 +1,6 @@ -'use strict' +module.exports = function gzip(req, res, next) { + // force compression + req.headers["accept-encoding"] = "gzip"; -module.exports = function gzip (req, res, next) { - // force compression - req.headers['accept-encoding'] = 'gzip' - - next() -} + next(); +}; diff --git a/lib/routes/har.js b/lib/routes/har.js index 376c8b1b..bc703e2d 100644 --- a/lib/routes/har.js +++ b/lib/routes/har.js @@ -1,10 +1,8 @@ -'use strict' +module.exports = function har(req, res, next) { + res.view = "default"; + res.yamlInline = 6; -module.exports = function har (req, res, next) { - res.view = 'default' - res.yamlInline = 6 + res.body = req.har; - res.body = req.har - - next() -} + next(); +}; diff --git a/lib/routes/headers.js b/lib/routes/headers.js index cd3511a3..54daafb0 100644 --- a/lib/routes/headers.js +++ b/lib/routes/headers.js @@ -1,36 +1,38 @@ -'use strict' - module.exports = { - one: function oneHeader (req, res, next) { - var name = req.params.name.toLowerCase() + one: function oneHeader(req, res, next) { + const name = req.params.name.toLowerCase(); - res.body = req.headers ? (req.headers[name] ? req.headers[name] : false) : false + res.body = req.headers + ? req.headers[name] + ? req.headers[name] + : false + : false; - next() - }, + next(); + }, - agent: function agent (req, res, next) { - req.params.name = 'user-agent' + agent: function agent(req, res, next) { + req.params.name = "user-agent"; - module.exports.one(req, res, next) - }, + module.exports.one(req, res, next); + }, - set: function setHeader (req, res, next) { - res.set(req.params.name, req.params.value) + set: function setHeader(req, res, next) { + res.set(req.params.name, req.params.value); - res.body = req.params.value + res.body = req.params.value; - next() - }, + next(); + }, - all: function allHeaders (req, res, next) { - res.yamlInline = 2 + all: function allHeaders(req, res, next) { + res.yamlInline = 2; - res.body = { - headers: req.har.log.entries[0].request.headers, - headersSize: req.har.log.entries[0].request.headersSize - } + res.body = { + headers: req.har.log.entries[0].request.headers, + headersSize: req.har.log.entries[0].request.headersSize, + }; - next() - } -} + next(); + }, +}; diff --git a/lib/routes/hello.js b/lib/routes/hello.js index 11f63fd6..6083c79f 100644 --- a/lib/routes/hello.js +++ b/lib/routes/hello.js @@ -1,9 +1,7 @@ -'use strict' +module.exports = function hello(req, res, next) { + res.view = "index"; -module.exports = function hello (req, res, next) { - res.view = 'index' + res.body = "Hello World!"; - res.body = 'Hello World!' - - next() -} + next(); +}; diff --git a/lib/routes/index.js b/lib/routes/index.js index 9dc1432d..b2a403e8 100644 --- a/lib/routes/index.js +++ b/lib/routes/index.js @@ -1,3 +1 @@ -'use strict' - -module.exports = require('require-directory')(module) +module.exports = require("require-directory")(module); diff --git a/lib/routes/ips.js b/lib/routes/ips.js index 7f579ca2..41214bda 100644 --- a/lib/routes/ips.js +++ b/lib/routes/ips.js @@ -1,15 +1,13 @@ -'use strict' - module.exports = { - one: function oneIP (req, res, next) { - res.body = req.ip + one: function oneIP(req, res, next) { + res.body = req.ip; - next() - }, + next(); + }, - all: function allIPs (req, res, next) { - res.body = req.forwarded.for + all: function allIPs(req, res, next) { + res.body = req.forwarded.for; - next() - } -} + next(); + }, +}; diff --git a/lib/routes/redirect.js b/lib/routes/redirect.js index 8d0b35db..936b7e54 100644 --- a/lib/routes/redirect.js +++ b/lib/routes/redirect.js @@ -1,33 +1,39 @@ -'use strict' - -var util = require('util') - -module.exports = function redirect (req, res, next) { - var count = req.params.count ? parseInt(req.params.count, 10) : 1 - var status = parseInt(req.params.status_code, 10) || 302 - var valid = [300, 301, 302, 303, 307, 308] - - if (count > 100) { - count = 100 - } - - if (!~valid.indexOf(status)) { - res.body = { - error: 'invalid status code, must be one of ' + valid.join() - } - - return next() - } - - if (count > 0) { - if (count === 1 && req.query.to) { - return res.redirect(status, req.query.to) - } - - return res.redirect(status, util.format('/redirect/%d/%d%s', status, count - 1, req.query.to ? '?to=' + req.query.to : '')) - } - - res.body = 'redirect finished' - - next() -} +const util = require("util"); + +module.exports = function redirect(req, res, next) { + let count = req.params.count ? parseInt(req.params.count, 10) : 1; + const status = parseInt(req.params.status_code, 10) || 302; + const valid = [300, 301, 302, 303, 307, 308]; + + if (count > 100) { + count = 100; + } + + if (!~valid.indexOf(status)) { + res.body = { + error: `invalid status code, must be one of ${valid.join()}`, + }; + + return next(); + } + + if (count > 0) { + if (count === 1 && req.query.to) { + return res.redirect(status, req.query.to); + } + + return res.redirect( + status, + util.format( + "/redirect/%d/%d%s", + status, + count - 1, + req.query.to ? `?to=${req.query.to}` : "", + ), + ); + } + + res.body = "redirect finished"; + + next(); +}; diff --git a/lib/routes/request.js b/lib/routes/request.js index 5e43f6c9..e99f0073 100644 --- a/lib/routes/request.js +++ b/lib/routes/request.js @@ -1,9 +1,7 @@ -'use strict' +module.exports = function rquest(req, res, next) { + res.yamlInline = 6; -module.exports = function rquest (req, res, next) { - res.yamlInline = 6 + res.body = req.simple; - res.body = req.simple - - next() -} + next(); +}; diff --git a/lib/routes/status.js b/lib/routes/status.js index 6743d4c0..ca0f2e48 100644 --- a/lib/routes/status.js +++ b/lib/routes/status.js @@ -1,13 +1,11 @@ -'use strict' +module.exports = function status(req, res, next) { + res.statusCode = req.params.code || 200; + res.statusMessage = (req.params.reason || "OK").replace(/\+/g, " "); -module.exports = function status (req, res, next) { - res.statusCode = req.params.code || 200 - res.statusMessage = (req.params.reason || 'OK').replace(/\+/g, ' ') + res.body = { + code: res.statusCode, + message: res.statusMessage, + }; - res.body = { - code: res.statusCode, - message: res.statusMessage - } - - next() -} + next(); +}; diff --git a/lib/routes/stream.js b/lib/routes/stream.js index 831d50ac..c1d21208 100644 --- a/lib/routes/stream.js +++ b/lib/routes/stream.js @@ -1,27 +1,27 @@ -'use strict' +module.exports = function stream(req, res, next) { + res.set({ + "Content-Type": "text/plain; charset=utf-8", + "Transfer-Encoding": "chunked", + }); -module.exports = function stream (req, res, next) { - res.set({ - 'Content-Type': 'text/plain; charset=utf-8', - 'Transfer-Encoding': 'chunked' - }) + // set default chunks to 10 + let chunks = req.params.chunks ? parseInt(req.params.chunks, 10) : 10; - // set default chunks to 10 - var chunks = req.params.chunks ? parseInt(req.params.chunks, 10) : 10 + // max out chunks at 100 + if (chunks > 100) { + chunks = 100; + } - // max out chunks at 100 - if (chunks > 100) { - chunks = 100 - } + let count = 1; - var count = 1 + while (count <= chunks) { + res.write( + `${JSON.stringify({ + type: "stream", + chunk: count++, + })}\n`, + ); + } - while (count <= chunks) { - res.write(JSON.stringify({ - type: 'stream', - chunk: count++ - }) + '\n') - } - - res.end() -} + res.end(); +}; diff --git a/lib/utils.js b/lib/utils.js index 8d66c1f9..97d09d37 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,94 +1,96 @@ -'use strict' +const pkg = require("../package.json"); -var pkg = require('../package.json') +const utils = { + objectToArray: (obj) => { + if (!obj || typeof obj !== "object") { + return []; + } -var utils = { - objectToArray: function (obj) { - if (!obj || typeof obj !== 'object') { - return [] - } + const results = Object.keys(obj).reduce((results, name) => { + results.push({ + name: name, + value: obj[name], + }); - var results = Object.keys(obj).reduce(function (results, name) { - results.push({ - name: name, - value: obj[name] - }) + return results; + }, []); - return results - }, []) + return results; + }, - return results - }, + getReqHeaderSize: (req) => { + const keys = Object.keys(req.headers); - getReqHeaderSize: function (req) { - var keys = Object.keys(req.headers) + const values = keys.map((key) => req.headers[key]); - var values = keys.map(function (key) { - return req.headers[key] - }) + const headers = + req.method + + req.url + + req.versionMajor + + req.versionMinor + + keys.join() + + values.join(); - var headers = req.method + req.url + req.versionMajor + req.versionMinor + keys.join() + values.join() + // startline: [method] [url] HTTP/1.1\r\n = 12 + // endline: \r\n = 2 + // every header + \r\n = * 2 + return Buffer.from(headers).length + keys.length * 2 + 12 + 2; + }, - // startline: [method] [url] HTTP/1.1\r\n = 12 - // endline: \r\n = 2 - // every header + \r\n = * 2 - return Buffer.from(headers).length + (keys.length * 2) + 12 + 2 - }, + createHar: (req) => ({ + log: { + version: "1.2", + creator: { + name: "mockbin.com", + version: pkg.version, + }, + entries: [ + { + startedDateTime: new Date().toISOString(), + clientIPAddress: req.ip, + request: { + method: req.method, + url: `${req.forwarded.proto}://${req.hostname}${req.originalUrl}`, + httpVersion: "HTTP/1.1", + // TODO, add cookie details + cookies: utils.objectToArray(req.cookies), + headers: utils.objectToArray(req.headers), + queryString: utils.objectToArray(req.query), + // TODO + postData: { + mimeType: req.contentType + ? req.contentType + : "application/octet-stream", + text: req.body, + params: [], + }, + headersSize: utils.getReqHeaderSize(req), + bodySize: req.rawBody.length, + }, + }, + ], + }, + }), - createHar: function (req) { - return { - log: { - version: '1.2', - creator: { - name: 'mockbin.com', - version: pkg.version - }, - entries: [{ - startedDateTime: new Date().toISOString(), - clientIPAddress: req.ip, - request: { - method: req.method, - url: req.forwarded.proto + '://' + req.hostname + req.originalUrl, - httpVersion: 'HTTP/1.1', - // TODO, add cookie details - cookies: utils.objectToArray(req.cookies), - headers: utils.objectToArray(req.headers), - queryString: utils.objectToArray(req.query), - // TODO - postData: { - mimeType: req.contentType ? req.contentType : 'application/octet-stream', - text: req.body, - params: [] - }, - headersSize: utils.getReqHeaderSize(req), - bodySize: req.rawBody.length - } - }] - } - } - }, + createSimpleHar: (req) => ({ + startedDateTime: new Date().toISOString(), + clientIPAddress: req.ip, + method: req.method, + url: `${req.forwarded.proto}://${req.hostname}${req.originalUrl}`, + httpVersion: "HTTP/1.1", + // TODO, add cookie details + cookies: req.cookies, + headers: req.headers, + queryString: req.query, + // TODO + postData: { + mimeType: req.contentType ? req.contentType : "application/octet-stream", + text: req.body, + params: [], + }, + headersSize: utils.getReqHeaderSize(req), + bodySize: req.rawBody.length, + }), +}; - createSimpleHar: function (req) { - return { - startedDateTime: new Date().toISOString(), - clientIPAddress: req.ip, - method: req.method, - url: req.forwarded.proto + '://' + req.hostname + req.originalUrl, - httpVersion: 'HTTP/1.1', - // TODO, add cookie details - cookies: req.cookies, - headers: req.headers, - queryString: req.query, - // TODO - postData: { - mimeType: req.contentType ? req.contentType : 'application/octet-stream', - text: req.body, - params: [] - }, - headersSize: utils.getReqHeaderSize(req), - bodySize: req.rawBody.length - } - } -} - -module.exports = utils +module.exports = utils; diff --git a/server.js b/server.js index b6455b04..923ec556 100644 --- a/server.js +++ b/server.js @@ -1,17 +1,15 @@ -'use strict' +const app = require("./src"); +const dotenv = require("dotenv"); +const pkg = require("./package"); -var app = require('./src') -var dotenv = require('dotenv') -var pkg = require('./package') +dotenv.config({ silent: true }); -dotenv.config({ silent: true }) +const options = { + port: process.env.MOCKBIN_PORT || pkg.config.port, + quiet: process.env.MOCKBIN_QUIET || pkg.config.quiet, + redis: process.env.MOCKBIN_REDIS || pkg.config.redis, +}; -var options = { - port: process.env.MOCKBIN_PORT || pkg.config.port, - quiet: process.env.MOCKBIN_QUIET || pkg.config.quiet, - redis: process.env.MOCKBIN_REDIS || pkg.config.redis -} - -app(options, function () { - console.info('starting server on port: %d', options.port) -}) +app(options, () => { + console.info("starting server on port: %d", options.port); +}); diff --git a/src/index.js b/src/index.js index f94c4d06..b115a9f3 100644 --- a/src/index.js +++ b/src/index.js @@ -1,47 +1,45 @@ -'use strict' - -var compression = require('compression') -var cookieParser = require('cookie-parser') -var debug = require('debug')('mockbin') -var express = require('express') -var methodOverride = require('method-override') -var morgan = require('morgan') -var path = require('path') -var router = require('../lib') - -module.exports = function (options, done) { - if (!options) { - throw Error('missing options') - } - - debug('system started with options: %j', options) - - // setup ExpressJS - var app = express() - - app.enable('view cache') - app.enable('trust proxy') - app.set('view engine', 'pug') - app.set('views', path.join(__dirname, 'views')) - app.set('jsonp callback name', '__callback') - - // add 3rd party middlewares - app.use(compression()) - app.use(cookieParser()) - app.use(methodOverride('__method')) - app.use(methodOverride('X-HTTP-Method-Override')) - app.use('/static', express.static(path.join(__dirname, 'static'))) - - if (options.quiet !== true) { - app.use(morgan('dev')) - } - - // magic starts here - app.use('/', router(options)) - - app.listen(options.port) - - if (typeof done === 'function') { - done() - } -} +const compression = require("compression"); +const cookieParser = require("cookie-parser"); +const debug = require("debug")("mockbin"); +const express = require("express"); +const methodOverride = require("method-override"); +const morgan = require("morgan"); +const path = require("path"); +const router = require("../lib"); + +module.exports = (options, done) => { + if (!options) { + throw Error("missing options"); + } + + debug("system started with options: %j", options); + + // setup ExpressJS + const app = express(); + + app.enable("view cache"); + app.enable("trust proxy"); + app.set("view engine", "pug"); + app.set("views", path.join(__dirname, "views")); + app.set("jsonp callback name", "__callback"); + + // add 3rd party middlewares + app.use(compression()); + app.use(cookieParser()); + app.use(methodOverride("__method")); + app.use(methodOverride("X-HTTP-Method-Override")); + app.use("/static", express.static(path.join(__dirname, "static"))); + + if (options.quiet !== true) { + app.use(morgan("dev")); + } + + // magic starts here + app.use("/", router(options)); + + app.listen(options.port); + + if (typeof done === "function") { + done(); + } +}; diff --git a/src/static/bin/create.js b/src/static/bin/create.js index 6757028a..9fab511f 100644 --- a/src/static/bin/create.js +++ b/src/static/bin/create.js @@ -1,199 +1,215 @@ /* globals $, hljs, FileReader */ -var sample = { - text: { - status: 200, - statusText: 'OK', - httpVersion: 'HTTP/1.1', - headers: [ - { - name: 'Content-Type', - value: 'text/plain' - } - ], - cookies: [], - content: { - mimeType: 'text/plain', - text: 'Hello World' - } - }, - - json: { - status: 200, - statusText: 'OK', - httpVersion: 'HTTP/1.1', - headers: [ - { - name: 'Content-Type', - value: 'application/json' - } - ], - cookies: [], - content: { - mimeType: 'application/json', - text: '{\n "foo": "Hello World"\n}' - } - }, - - jsonp: { - status: 200, - statusText: 'OK', - httpVersion: 'HTTP/1.1', - headers: [ - { - name: 'Content-Type', - value: 'application/javascript' - } - ], - cookies: [], - content: { - mimeType: 'application/javascript', - text: 'callback({\n "foo": "Hello World"\n})' - } - }, - - xml: { - status: 200, - statusText: 'OK', - httpVersion: 'HTTP/1.1', - headers: [ - { - name: 'Content-Type', - value: 'application/xml' - } - ], - cookies: [], - content: { - mimeType: 'application/xml', - text: '\nHello World' - } - } -} - -$(function () { - $('select[name="example"]').on('change', function (e) { - var data = sample[$(this).val()] - - if (data) { - $('input[name="response"]').val(JSON.stringify(data)) - $('pre code').text(JSON.stringify(data, null, 2)) - hljs.highlightBlock($('pre code')[0]) - } - }) - - $('input[type="file"]').on('change', function (e) { - var file = e.target.files[0] - - if (!file) { - return - } - - var reader = new FileReader() - - reader.onload = function (e) { - try { - var data = JSON.parse(e.target.result) - } catch (e) { - console.log(e) - } - - if (data) { - $('input[name="response"]').val(JSON.stringify(data)) - - $('pre code').text(JSON.stringify(data, null, 2)) - hljs.highlightBlock($('pre code')[0]) - } - } - - reader.readAsText(file) - }) - - var addKeyPair = function (event) { - var self = $(this) - - var group = self.parents('.form-group') - var form = self.parents('form') - - group.clone().appendTo(form) - } - - var processFormData = function (event) { - var response = { - status: '', - statusText: '', - httpVersion: 'HTTP/1.1', - headers: [], - cookies: [], - content: { - mimeType: '', - text: '' - } - } - - $('.has-error').removeClass('has-error') - - $('.form input:not(:valid)').each(function () { - $(this).parents('.form-group').addClass('has-error') - }) - - var forms = [{ form: 'status', parent: response }, { form: 'content', parent: response.content }] - - forms.forEach(function (item) { - $('form[name="' + item.form + '"] div.form-group:not(.pair) .form-control').each(function () { - var self = $(this) - - item.parent[self.attr('name')] = self.val() - }) - }) - - var groups = ['headers', 'cookies'] - - groups.forEach(function (pair) { - var params = [] - - $('form[name="' + pair + '"] .pair input[name="name"]').slice(0, -1).each(function (index, header) { - var value = $(header).val() - - if (value.trim() !== '') { - params.push({ name: value }) - } - }) - - $('form[name="' + pair + '"] .pair input[name="value"]').slice(0, -1).each(function (index, header) { - if (params[index]) { - params[index].value = $(header).val() - } - }) - - response[pair] = params - }) - - // fix type issues - response.status = parseInt(response.status, 10) - - $('input[name="response"]').val(JSON.stringify(response)) - $('pre code').text(JSON.stringify(response, null, 2)) - - hljs.highlightBlock($('pre code')[0]) - } - - $('.toggle-comments').on('click', function (event) { - $('.form').toggleClass('no-comments') - $('.form input[name="comment"]').attr('disabled', $(this).hasClass('active')) - }) - - $('form').on('click', '.form-group.pair:last-of-type .btn-success', addKeyPair) - - $('form').on('focus', '.form-group.pair:last-child input', addKeyPair) - - $('form').on('click', '.form-group.pair .btn-danger', function (event) { - $(this).parents('.form-group').remove() - }) - - $('form').on('keyup keypress change blur', '.form-control', processFormData) - $('form').on('click', '[type!="submit"].btn', processFormData) - - $(document).ready(function () { - processFormData() - }) -}) +const sample = { + text: { + status: 200, + statusText: "OK", + httpVersion: "HTTP/1.1", + headers: [ + { + name: "Content-Type", + value: "text/plain", + }, + ], + cookies: [], + content: { + mimeType: "text/plain", + text: "Hello World", + }, + }, + + json: { + status: 200, + statusText: "OK", + httpVersion: "HTTP/1.1", + headers: [ + { + name: "Content-Type", + value: "application/json", + }, + ], + cookies: [], + content: { + mimeType: "application/json", + text: '{\n "foo": "Hello World"\n}', + }, + }, + + jsonp: { + status: 200, + statusText: "OK", + httpVersion: "HTTP/1.1", + headers: [ + { + name: "Content-Type", + value: "application/javascript", + }, + ], + cookies: [], + content: { + mimeType: "application/javascript", + text: 'callback({\n "foo": "Hello World"\n})', + }, + }, + + xml: { + status: 200, + statusText: "OK", + httpVersion: "HTTP/1.1", + headers: [ + { + name: "Content-Type", + value: "application/xml", + }, + ], + cookies: [], + content: { + mimeType: "application/xml", + text: '\nHello World', + }, + }, +}; + +$(() => { + $('select[name="example"]').on("change", function (e) { + const data = sample[$(this).val()]; + + if (data) { + $('input[name="response"]').val(JSON.stringify(data)); + $("pre code").text(JSON.stringify(data, null, 2)); + hljs.highlightBlock($("pre code")[0]); + } + }); + + $('input[type="file"]').on("change", (e) => { + const file = e.target.files[0]; + + if (!file) { + return; + } + + const reader = new FileReader(); + + reader.onload = (e) => { + try { + const data = JSON.parse(e.target.result); + } catch (e) { + console.log(e); + } + + if (data) { + $('input[name="response"]').val(JSON.stringify(data)); + + $("pre code").text(JSON.stringify(data, null, 2)); + hljs.highlightBlock($("pre code")[0]); + } + }; + + reader.readAsText(file); + }); + + const addKeyPair = function (event) { + const self = $(this); + + const group = self.parents(".form-group"); + const form = self.parents("form"); + + group.clone().appendTo(form); + }; + + const processFormData = (event) => { + const response = { + status: "", + statusText: "", + httpVersion: "HTTP/1.1", + headers: [], + cookies: [], + content: { + mimeType: "", + text: "", + }, + }; + + $(".has-error").removeClass("has-error"); + + $(".form input:not(:valid)").each(function () { + $(this).parents(".form-group").addClass("has-error"); + }); + + const forms = [ + { form: "status", parent: response }, + { form: "content", parent: response.content }, + ]; + + forms.forEach((item) => { + $( + `form[name="${item.form}"] div.form-group:not(.pair) .form-control`, + ).each(function () { + const self = $(this); + + item.parent[self.attr("name")] = self.val(); + }); + }); + + const groups = ["headers", "cookies"]; + + groups.forEach((pair) => { + const params = []; + + $(`form[name="${pair}"] .pair input[name="name"]`) + .slice(0, -1) + .each((index, header) => { + const value = $(header).val(); + + if (value.trim() !== "") { + params.push({ name: value }); + } + }); + + $(`form[name="${pair}"] .pair input[name="value"]`) + .slice(0, -1) + .each((index, header) => { + if (params[index]) { + params[index].value = $(header).val(); + } + }); + + response[pair] = params; + }); + + // fix type issues + response.status = parseInt(response.status, 10); + + $('input[name="response"]').val(JSON.stringify(response)); + $("pre code").text(JSON.stringify(response, null, 2)); + + hljs.highlightBlock($("pre code")[0]); + }; + + $(".toggle-comments").on("click", function (event) { + $(".form").toggleClass("no-comments"); + $('.form input[name="comment"]').attr( + "disabled", + $(this).hasClass("active"), + ); + }); + + $("form").on( + "click", + ".form-group.pair:last-of-type .btn-success", + addKeyPair, + ); + + $("form").on("focus", ".form-group.pair:last-child input", addKeyPair); + + $("form").on("click", ".form-group.pair .btn-danger", function (event) { + $(this).parents(".form-group").remove(); + }); + + $("form").on("keyup keypress change blur", ".form-control", processFormData); + $("form").on("click", '[type!="submit"].btn', processFormData); + + $(document).ready(() => { + processFormData(); + }); +}); diff --git a/src/static/har/echo.json b/src/static/har/echo.json index a8f7cbb2..f0ca36e5 100644 --- a/src/static/har/echo.json +++ b/src/static/har/echo.json @@ -1,12 +1,12 @@ { - "method": "POST", - "url": "http://mockbin.org/request", - "headers": [ - { "name": "Accept", "value": "application/json" }, - { "name": "Content-Type", "value": "application/json" } - ], - "postData": { - "mimeType": "application/json", - "text": "{\"foo\": \"bar\"}" - } + "method": "POST", + "url": "http://mockbin.org/request", + "headers": [ + { "name": "Accept", "value": "application/json" }, + { "name": "Content-Type", "value": "application/json" } + ], + "postData": { + "mimeType": "application/json", + "text": "{\"foo\": \"bar\"}" + } } diff --git a/test/fixtures/response.json b/test/fixtures/response.json index 182d307a..760361a2 100644 --- a/test/fixtures/response.json +++ b/test/fixtures/response.json @@ -1,49 +1,49 @@ { - "status": 200, - "statusText": "OK", - "httpVersion": "HTTP/1.1", - "headers": [ - { - "name": "Date", - "value": "Wed, 21 Jan 2015 23:36:35 GMT" - }, - { - "name": "Server", - "value": "Apache" - }, - { - "name": "Transfer-Encoding", - "value": "chunked" - }, - { - "name": "Content-Type", - "value": "text/html; charset=UTF-8" - }, - { - "name": "Cache-Control", - "value": "max-age=7200" - }, - { - "name": "Connection", - "value": "Keep-Alive" - }, - { - "name": "Keep-Alive", - "value": "timeout=5, max=50" - }, - { - "name": "Expires", - "value": "Thu, 22 Jan 2015 01:36:35 GMT" - } - ], - "cookies": [], - "content": { - "size": 20, - "mimeType": "text/html", - "text": "

Hello World

", - "compression": 0 - }, - "redirectURL": "", - "headersSize": 323, - "bodySize": 70993 + "status": 200, + "statusText": "OK", + "httpVersion": "HTTP/1.1", + "headers": [ + { + "name": "Date", + "value": "Wed, 21 Jan 2015 23:36:35 GMT" + }, + { + "name": "Server", + "value": "Apache" + }, + { + "name": "Transfer-Encoding", + "value": "chunked" + }, + { + "name": "Content-Type", + "value": "text/html; charset=UTF-8" + }, + { + "name": "Cache-Control", + "value": "max-age=7200" + }, + { + "name": "Connection", + "value": "Keep-Alive" + }, + { + "name": "Keep-Alive", + "value": "timeout=5, max=50" + }, + { + "name": "Expires", + "value": "Thu, 22 Jan 2015 01:36:35 GMT" + } + ], + "cookies": [], + "content": { + "size": 20, + "mimeType": "text/html", + "text": "

Hello World

", + "compression": 0 + }, + "redirectURL": "", + "headersSize": 323, + "bodySize": 70993 } diff --git a/test/http/index.js b/test/http/index.js index 809466b4..2e7a9fd8 100644 --- a/test/http/index.js +++ b/test/http/index.js @@ -1,319 +1,319 @@ /* global describe, it, before, after */ -var cookieParser = require('cookie-parser') -var express = require('express') -var mockbin = require('../../lib') -var path = require('path') -var unirest = require('unirest') - -var app = express() -var server = null - -require('should') - -describe('HTTP', () => { - before((done) => { - // express setup - app.enable('trust proxy') - app.set('view engine', 'pug') - app.set('views', path.join(__dirname, '..', '..', 'src', 'views')) - - app.use(cookieParser()) - - app.use('/', mockbin()) - server = app.listen(3000, () => { - done() - }) - }) - - after(() => { - server.close() - }) - - it('home page responds with html content', (done) => { - var req = unirest.get('http://localhost:3000/') - - req.headers('Accept', 'text/html') - - req.end((res) => { - res.status.should.equal(200) - res.headers.should.have - .property('content-type') - .and.equal('text/html; charset=utf-8') - done() - }) - }) - - it('should send CORS headers', (done) => { - var req = unirest.options('http://localhost:3000/request') - - req.end((res) => { - res.headers.should.have - .property('access-control-allow-origin') - .and.equal('*') - res.headers.should.have - .property('access-control-allow-methods') - .and.equal('OPTIONS') - res.headers.should.have - .property('access-control-allow-headers') - .and.equal('host,content-length,connection') - done() - }) - }) - - it('GET / responds with hello message', (done) => { - var req = unirest.get('http://localhost:3000/') - - req.headers('Accept', 'text/plain') - - req.end((res) => { - res.headers.should.have - .property('content-type') - .and.equal('text/plain; charset=utf-8') - res.body.should.equal('Hello World!') - done() - }) - }) - - it('GET /ip should return local ip', (done) => { - var req = unirest.get('http://localhost:3000/ip') - - req.headers('Accept', 'text/plain') - - req.end((res) => { - res.body.should.equal('::1') - done() - }) - }) - - it('GET /ips should return proxied IPs', (done) => { - var req = unirest.get('http://localhost:3000/ips') - - req.headers({ - Accept: 'application/json', - 'X-Forwarded-For': '10.10.10.1, 10.10.10.2, 10.10.10.3' - }) - - req.end((res) => { - res.body.should.be.an.Object() - res.body.should.have.properties('10.10.10.1', '10.10.10.2', '10.10.10.3') - - done() - }) - }) - - it('GET /agent should return user-agent string', (done) => { - var req = unirest.get('http://localhost:3000/agent') - - req.headers({ - Accept: 'text/plain', - 'User-Agent': 'mockbin tester' - }) - - req.end((res) => { - res.body.should.equal('mockbin tester') - - done() - }) - }) - - it('GET /status/:code should return custom status code', (done) => { - var req = unirest.get('http://localhost:3000/status/900') - - req.headers('Accept', 'application/json') - - req.end((res) => { - res.status.should.equal(900) - res.body.should.have.property('code').and.equal('900') - res.body.should.have.property('message').and.equal('OK') - done() - }) - }) - - it('GET /status/:code/:reason should return custom status code + reason', (done) => { - var req = unirest.get('http://localhost:3000/status/900/reason') - - req.headers('Accept', 'application/json') - - req.end((res) => { - res.status.should.equal(900) - res.body.should.have.property('code').and.equal('900') - res.body.should.have.property('message').and.equal('reason') - done() - }) - }) - - it('GET /status/:code/:reason should allow spaces in reason text', (done) => { - var req = unirest.get( - 'http://localhost:3000/status/900/because of reasons' - ) - - req.headers('Accept', 'application/json') - - req.end((res) => { - res.status.should.equal(900) - res.body.should.have.property('code').and.equal('900') - res.body.should.have.property('message').and.equal('because of reasons') - done() - }) - }) - - it('GET /status/:code/:reason should replace plus signs in reason text with spaces', (done) => { - var req = unirest.get( - 'http://localhost:3000/status/900/because+of+reasons' - ) - - req.headers('Accept', 'application/json') - - req.end((res) => { - res.status.should.equal(900) - res.body.should.have.property('code').and.equal('900') - res.body.should.have.property('message').and.equal('because of reasons') - done() - }) - }) +const cookieParser = require("cookie-parser"); +const express = require("express"); +const mockbin = require("../../lib"); +const path = require("path"); +const unirest = require("unirest"); + +const app = express(); +let server = null; + +require("should"); + +describe("HTTP", () => { + before((done) => { + // express setup + app.enable("trust proxy"); + app.set("view engine", "pug"); + app.set("views", path.join(__dirname, "..", "..", "src", "views")); + + app.use(cookieParser()); + + app.use("/", mockbin()); + server = app.listen(3000, () => { + done(); + }); + }); + + after(() => { + server.close(); + }); + + it("home page responds with html content", (done) => { + const req = unirest.get("http://localhost:3000/"); + + req.headers("Accept", "text/html"); + + req.end((res) => { + res.status.should.equal(200); + res.headers.should.have + .property("content-type") + .and.equal("text/html; charset=utf-8"); + done(); + }); + }); + + it("should send CORS headers", (done) => { + const req = unirest.options("http://localhost:3000/request"); + + req.end((res) => { + res.headers.should.have + .property("access-control-allow-origin") + .and.equal("*"); + res.headers.should.have + .property("access-control-allow-methods") + .and.equal("OPTIONS"); + res.headers.should.have + .property("access-control-allow-headers") + .and.equal("host,content-length,connection"); + done(); + }); + }); + + it("GET / responds with hello message", (done) => { + const req = unirest.get("http://localhost:3000/"); + + req.headers("Accept", "text/plain"); + + req.end((res) => { + res.headers.should.have + .property("content-type") + .and.equal("text/plain; charset=utf-8"); + res.body.should.equal("Hello World!"); + done(); + }); + }); + + it("GET /ip should return local ip", (done) => { + const req = unirest.get("http://localhost:3000/ip"); + + req.headers("Accept", "text/plain"); + + req.end((res) => { + res.body.should.equal("::1"); + done(); + }); + }); + + it("GET /ips should return proxied IPs", (done) => { + const req = unirest.get("http://localhost:3000/ips"); + + req.headers({ + Accept: "application/json", + "X-Forwarded-For": "10.10.10.1, 10.10.10.2, 10.10.10.3", + }); + + req.end((res) => { + res.body.should.be.an.Object(); + res.body.should.have.properties("10.10.10.1", "10.10.10.2", "10.10.10.3"); + + done(); + }); + }); + + it("GET /agent should return user-agent string", (done) => { + const req = unirest.get("http://localhost:3000/agent"); + + req.headers({ + Accept: "text/plain", + "User-Agent": "mockbin tester", + }); + + req.end((res) => { + res.body.should.equal("mockbin tester"); + + done(); + }); + }); + + it("GET /status/:code should return custom status code", (done) => { + const req = unirest.get("http://localhost:3000/status/900"); + + req.headers("Accept", "application/json"); + + req.end((res) => { + res.status.should.equal(900); + res.body.should.have.property("code").and.equal("900"); + res.body.should.have.property("message").and.equal("OK"); + done(); + }); + }); + + it("GET /status/:code/:reason should return custom status code + reason", (done) => { + const req = unirest.get("http://localhost:3000/status/900/reason"); + + req.headers("Accept", "application/json"); + + req.end((res) => { + res.status.should.equal(900); + res.body.should.have.property("code").and.equal("900"); + res.body.should.have.property("message").and.equal("reason"); + done(); + }); + }); + + it("GET /status/:code/:reason should allow spaces in reason text", (done) => { + const req = unirest.get( + "http://localhost:3000/status/900/because of reasons", + ); + + req.headers("Accept", "application/json"); + + req.end((res) => { + res.status.should.equal(900); + res.body.should.have.property("code").and.equal("900"); + res.body.should.have.property("message").and.equal("because of reasons"); + done(); + }); + }); + + it("GET /status/:code/:reason should replace plus signs in reason text with spaces", (done) => { + const req = unirest.get( + "http://localhost:3000/status/900/because+of+reasons", + ); + + req.headers("Accept", "application/json"); + + req.end((res) => { + res.status.should.equal(900); + res.body.should.have.property("code").and.equal("900"); + res.body.should.have.property("message").and.equal("because of reasons"); + done(); + }); + }); - it('GET /headers should return all headers', (done) => { - var req = unirest.get('http://localhost:3000/headers') + it("GET /headers should return all headers", (done) => { + const req = unirest.get("http://localhost:3000/headers"); - req.headers({ - Accept: 'application/json', - 'X-Custom-Header': 'ALL YOUR BASE ARE BELONG TO US' - }) + req.headers({ + Accept: "application/json", + "X-Custom-Header": "ALL YOUR BASE ARE BELONG TO US", + }); - req.end((res) => { - res.body.headers.should.containEql({ - name: 'x-custom-header', - value: 'ALL YOUR BASE ARE BELONG TO US' - }) + req.end((res) => { + res.body.headers.should.containEql({ + name: "x-custom-header", + value: "ALL YOUR BASE ARE BELONG TO US", + }); - done() - }) - }) + done(); + }); + }); - it('GET /header/:name should return specific headers', (done) => { - var req = unirest.get('http://localhost:3000/header/X-Custom-Header') + it("GET /header/:name should return specific headers", (done) => { + const req = unirest.get("http://localhost:3000/header/X-Custom-Header"); - req.headers({ - Accept: 'application/json', - 'X-Custom-Header': 'ALL YOUR BASE ARE BELONG TO US' - }) + req.headers({ + Accept: "application/json", + "X-Custom-Header": "ALL YOUR BASE ARE BELONG TO US", + }); - req.end((res) => { - res.body.should.equal('ALL YOUR BASE ARE BELONG TO US') + req.end((res) => { + res.body.should.equal("ALL YOUR BASE ARE BELONG TO US"); - done() - }) - }) + done(); + }); + }); - it('GET /cookies should return all cookies', (done) => { - var req = unirest.get('http://localhost:3000/cookies') + it("GET /cookies should return all cookies", (done) => { + const req = unirest.get("http://localhost:3000/cookies"); - req.headers({ - Accept: 'application/json', - Cookie: 'my-cookie=ALL YOUR BASE ARE BELONG TO US' - }) + req.headers({ + Accept: "application/json", + Cookie: "my-cookie=ALL YOUR BASE ARE BELONG TO US", + }); - req.end((res) => { - res.body.should.containEql({ - name: 'my-cookie', - value: 'ALL YOUR BASE ARE BELONG TO US' - }) + req.end((res) => { + res.body.should.containEql({ + name: "my-cookie", + value: "ALL YOUR BASE ARE BELONG TO US", + }); - done() - }) - }) - - it('GET /cookie/:name should return specific cookie', (done) => { - var req = unirest.get('http://localhost:3000/cookie/my-cookie') + done(); + }); + }); + + it("GET /cookie/:name should return specific cookie", (done) => { + const req = unirest.get("http://localhost:3000/cookie/my-cookie"); - req.headers({ - Accept: 'application/json', - Cookie: 'my-cookie=ALL YOUR BASE ARE BELONG TO US' - }) + req.headers({ + Accept: "application/json", + Cookie: "my-cookie=ALL YOUR BASE ARE BELONG TO US", + }); - req.end((res) => { - res.body.should.containEql('ALL YOUR BASE ARE BELONG TO US') + req.end((res) => { + res.body.should.containEql("ALL YOUR BASE ARE BELONG TO US"); - done() - }) - }) + done(); + }); + }); - it('GET /redirect/:status should redirect 1 time using :status', (done) => { - var req = unirest.get('http://localhost:3000/redirect/303') + it("GET /redirect/:status should redirect 1 time using :status", (done) => { + const req = unirest.get("http://localhost:3000/redirect/303"); - req.followRedirect(true) + req.followRedirect(true); - req.maxRedirects(0) + req.maxRedirects(0); - req.end((res) => { - res.error - .toString() - .should.equal( - 'Error: Exceeded maxRedirects. Probably stuck in a redirect loop http://localhost:3000/redirect/303' - ) + req.end((res) => { + res.error + .toString() + .should.equal( + "Error: Exceeded maxRedirects. Probably stuck in a redirect loop http://localhost:3000/redirect/303", + ); - done() - }) - }) + done(); + }); + }); - it('GET /redirect/:status/:n should redirect :n times using :status', (done) => { - var req = unirest.get('http://localhost:3000/redirect/302/3') + it("GET /redirect/:status/:n should redirect :n times using :status", (done) => { + const req = unirest.get("http://localhost:3000/redirect/302/3"); - req.followRedirect(true) + req.followRedirect(true); - req.headers('Accept', 'application/json') + req.headers("Accept", "application/json"); - req.end((res) => { - res.body.should.equal('redirect finished') + req.end((res) => { + res.body.should.equal("redirect finished"); - done() - }) - }) + done(); + }); + }); - it('GET /redirect/:status/:n should redirect :n times using :status (verify count)', (done) => { - var req = unirest.get('http://localhost:3000/redirect/302/3') + it("GET /redirect/:status/:n should redirect :n times using :status (verify count)", (done) => { + const req = unirest.get("http://localhost:3000/redirect/302/3"); - req.followRedirect(true) + req.followRedirect(true); - req.maxRedirects(2) + req.maxRedirects(2); - req.end((res) => { - res.error - .toString() - .should.equal( - 'Error: Exceeded maxRedirects. Probably stuck in a redirect loop http://localhost:3000/redirect/302/1' - ) + req.end((res) => { + res.error + .toString() + .should.equal( + "Error: Exceeded maxRedirects. Probably stuck in a redirect loop http://localhost:3000/redirect/302/1", + ); - done() - }) - }) + done(); + }); + }); - it('GET /redirect/:status?to=URL should redirect to URL', (done) => { - var req = unirest.get( - 'http://localhost:3000/redirect/308?to=http://mockbin.com/' - ) + it("GET /redirect/:status?to=URL should redirect to URL", (done) => { + const req = unirest.get( + "http://localhost:3000/redirect/308?to=http://mockbin.com/", + ); - req.followRedirect(false) + req.followRedirect(false); - req.end((res) => { - res.status.should.equal(308) - res.headers.should.containEql({ location: 'http://mockbin.com/' }) + req.end((res) => { + res.status.should.equal(308); + res.headers.should.containEql({ location: "http://mockbin.com/" }); - done() - }) - }) + done(); + }); + }); - it('POST /request should accept multipart/form-data requests', function (done) { - var number = '123' - var req = unirest.post('http://localhost:3000/request') - req.headers('content-type', 'multipart/form-data; boundary=----boundary') - req.field('number', number) + it("POST /request should accept multipart/form-data requests", (done) => { + const number = "123"; + const req = unirest.post("http://localhost:3000/request"); + req.headers("content-type", "multipart/form-data; boundary=----boundary"); + req.field("number", number); - req.end(function (res) { - res.body.postData.params.number.should.equal(number) + req.end((res) => { + res.body.postData.params.number.should.equal(number); - done() - }) - }) -}) + done(); + }); + }); +}); diff --git a/test/routes/cookies.js b/test/routes/cookies.js index 189e87ac..65d3f4a3 100644 --- a/test/routes/cookies.js +++ b/test/routes/cookies.js @@ -1,83 +1,81 @@ /* global describe, it */ -'use strict' +const cookies = require("../../lib/routes/cookies"); -var cookies = require('../../lib/routes/cookies') +require("should"); -require('should') +describe("/cookie/:name", () => { + it("should response with one cookie", (done) => { + const res = {}; + const req = { + params: { + name: "foo", + }, + cookies: { + foo: "bar", + }, + }; -describe('/cookie/:name', function () { - it('should response with one cookie', function (done) { - var res = {} - var req = { - params: { - name: 'foo' - }, - cookies: { - foo: 'bar' - } - } + cookies.one(req, res, () => { + res.body.should.equal(req.cookies.foo); - cookies.one(req, res, function () { - res.body.should.equal(req.cookies.foo) + done(); + }); + }); - done() - }) - }) + it("should response with false when no cookies are defined", (done) => { + const res = {}; + const req = { + params: { + name: "foo", + }, + cookies: {}, + }; - it('should response with false when no cookies are defined', function (done) { - var res = {} - var req = { - params: { - name: 'foo' - }, - cookies: {} - } + cookies.one(req, res, () => { + res.body.should.be.false(); - cookies.one(req, res, function () { - res.body.should.be.false() + done(); + }); + }); - done() - }) - }) + it("should response with false when no match", (done) => { + const res = {}; + const req = { + params: { + name: "foo", + }, + }; - it('should response with false when no match', function (done) { - var res = {} - var req = { - params: { - name: 'foo' - } - } + cookies.one(req, res, () => { + res.body.should.be.false(); - cookies.one(req, res, function () { - res.body.should.be.false() + done(); + }); + }); +}); - done() - }) - }) -}) +describe("/cookie/:name", () => { + it("should response with all cookies", (done) => { + const res = {}; + const req = { + har: { + log: { + entries: [ + { + request: { + cookies: ["test"], + }, + }, + ], + }, + }, + }; -describe('/cookie/:name', function () { - it('should response with all cookies', function (done) { - var res = {} - var req = { - har: { - log: { - entries: [ - { - request: { - cookies: ['test'] - } - } - ] - } - } - } + cookies.all(req, res, () => { + res.body.should.equal(req.har.log.entries[0].request.cookies); - cookies.all(req, res, function () { - res.body.should.equal(req.har.log.entries[0].request.cookies) - - done() - }) - }) -}) + done(); + }); + }); +}); diff --git a/test/routes/delay.js b/test/routes/delay.js index 5bccc7cb..eb715230 100644 --- a/test/routes/delay.js +++ b/test/routes/delay.js @@ -1,43 +1,41 @@ /* global describe, it */ -'use strict' - -var delay = require('../../lib/routes/delay') - -require('should') - -describe('/delay/:ms', function () { - this.timeout(210) - - it('should not timeout', function (done) { - var res = {} - var req = { - params: { - ms: 10 - } - } - - delay(req, res, function () { - res.body.should.eql({ - delay: req.params.ms - }) - - done() - }) - }) - - it('should default to 200ms', function (done) { - var res = {} - var req = { - params: {} - } - - delay(req, res, function () { - res.body.should.eql({ - delay: 200 - }) - - done() - }) - }) -}) +const delay = require("../../lib/routes/delay"); + +require("should"); + +describe("/delay/:ms", function () { + this.timeout(210); + + it("should not timeout", (done) => { + const res = {}; + const req = { + params: { + ms: 10, + }, + }; + + delay(req, res, () => { + res.body.should.eql({ + delay: req.params.ms, + }); + + done(); + }); + }); + + it("should default to 200ms", (done) => { + const res = {}; + const req = { + params: {}, + }; + + delay(req, res, () => { + res.body.should.eql({ + delay: 200, + }); + + done(); + }); + }); +}); diff --git a/test/routes/echo.js b/test/routes/echo.js index e1c5d1d3..48eda12f 100644 --- a/test/routes/echo.js +++ b/test/routes/echo.js @@ -1,52 +1,50 @@ /* global describe, it */ -'use strict' +const echo = require("../../lib/routes/echo"); -var echo = require('../../lib/routes/echo') +require("should"); -require('should') +const res = { + headers: {}, -var res = { - headers: {}, + type: (type) => { + res.headers["content-type"] = type; + }, - type: function (type) { - res.headers['content-type'] = type - }, + send: (body) => { + res.body = body; + }, +}; - send: function (body) { - res.body = body - } -} +describe("/echo", () => { + it("should respond with request body and content-type header", (done) => { + const req = { + body: "foo", + headers: { + "content-type": "text/plain", + }, + }; -describe('/echo', function () { - it('should respond with request body and content-type header', function (done) { - var req = { - body: 'foo', - headers: { - 'content-type': 'text/plain' - } - } + echo(req, res); - echo(req, res) + res.body.should.equal(req.body); + res.headers.should.have.property("content-type"); + res.headers["content-type"].should.equal(req.headers["content-type"]); - res.body.should.equal(req.body) - res.headers.should.have.property('content-type') - res.headers['content-type'].should.equal(req.headers['content-type']) + done(); + }); - done() - }) + it("should respond with default values", (done) => { + const req = { + headers: {}, + }; - it('should respond with default values', function (done) { - var req = { - headers: {} - } + echo(req, res); - echo(req, res) + res.body.should.equal(""); + res.headers.should.have.property("content-type"); + res.headers["content-type"].should.equal("text/plain"); - res.body.should.equal('') - res.headers.should.have.property('content-type') - res.headers['content-type'].should.equal('text/plain') - - done() - }) -}) + done(); + }); +}); diff --git a/test/routes/gzip.js b/test/routes/gzip.js index 522b0709..97bc7bb9 100644 --- a/test/routes/gzip.js +++ b/test/routes/gzip.js @@ -1,23 +1,21 @@ /* global describe, it */ -'use strict' +const gzip = require("../../lib/routes/gzip"); -var gzip = require('../../lib/routes/gzip') +require("should"); -require('should') +describe("/gzip/*", () => { + // not much to test here, mostly compression middleware's job + it("should force accept-encoding header", (done) => { + const req = { + headers: {}, + }; -describe('/gzip/*', function () { - // not much to test here, mostly compression middleware's job - it('should force accept-encoding header', function (done) { - var req = { - headers: {} - } + gzip(req, {}, () => { + req.headers.should.have.property("accept-encoding"); + req.headers["accept-encoding"].should.equal("gzip"); - gzip(req, {}, function () { - req.headers.should.have.property('accept-encoding') - req.headers['accept-encoding'].should.equal('gzip') - - done() - }) - }) -}) + done(); + }); + }); +}); diff --git a/test/routes/har.js b/test/routes/har.js index bed9a7f0..e531b8d4 100644 --- a/test/routes/har.js +++ b/test/routes/har.js @@ -1,23 +1,21 @@ /* global describe, it */ -'use strict' +const har = require("../../lib/routes/har"); -var har = require('../../lib/routes/har') +require("should"); -require('should') +describe("/har", () => { + // not much to test here, actual endpoint logic is tested elsewhere + it("should return object", (done) => { + const res = {}; + const req = { + har: "foo", + }; -describe('/har', function () { - // not much to test here, actual endpoint logic is tested elsewhere - it('should return object', function (done) { - var res = {} - var req = { - har: 'foo' - } + har(req, res, () => { + res.body.should.equal(req.har); - har(req, res, function () { - res.body.should.equal(req.har) - - done() - }) - }) -}) + done(); + }); + }); +}); diff --git a/test/routes/headers.js b/test/routes/headers.js index 648b3695..1a7c2dfc 100644 --- a/test/routes/headers.js +++ b/test/routes/headers.js @@ -1,102 +1,100 @@ /* global describe, it */ -'use strict' - -var headers = require('../../lib/routes/headers') - -require('should') - -describe('/agent', function () { - it('should response with user-agent header', function (done) { - var res = {} - var req = { - params: {}, - headers: { - 'user-agent': 'foo' - } - } - - headers.agent(req, res, function () { - res.body.should.equal(req.headers['user-agent']) - - done() - }) - }) -}) - -describe('/header/:name', function () { - it('should response with one header', function (done) { - var res = {} - var req = { - params: { - name: 'foo' - }, - headers: { - foo: 'bar' - } - } - - headers.one(req, res, function () { - res.body.should.equal(req.headers.foo) - - done() - }) - }) - - it('should response with false when no headers are defined', function (done) { - var res = {} - var req = { - params: { - name: 'foo' - }, - headers: {} - } - - headers.one(req, res, function () { - res.body.should.be.false() - - done() - }) - }) - - it('should response with false when no match', function (done) { - var res = {} - var req = { - params: { - name: 'foo' - } - } - - headers.one(req, res, function () { - res.body.should.be.false() - - done() - }) - }) -}) - -describe('/header/:name', function () { - it('should response with all headers', function (done) { - var res = {} - var req = { - har: { - log: { - entries: [ - { - request: { - headers: ['test'], - headersSize: 0 - } - } - ] - } - } - } - - headers.all(req, res, function () { - res.body.should.eql(req.har.log.entries[0].request) - - done() - }) - }) -}) +const headers = require("../../lib/routes/headers"); + +require("should"); + +describe("/agent", () => { + it("should response with user-agent header", (done) => { + const res = {}; + const req = { + params: {}, + headers: { + "user-agent": "foo", + }, + }; + + headers.agent(req, res, () => { + res.body.should.equal(req.headers["user-agent"]); + + done(); + }); + }); +}); + +describe("/header/:name", () => { + it("should response with one header", (done) => { + const res = {}; + const req = { + params: { + name: "foo", + }, + headers: { + foo: "bar", + }, + }; + + headers.one(req, res, () => { + res.body.should.equal(req.headers.foo); + + done(); + }); + }); + + it("should response with false when no headers are defined", (done) => { + const res = {}; + const req = { + params: { + name: "foo", + }, + headers: {}, + }; + + headers.one(req, res, () => { + res.body.should.be.false(); + + done(); + }); + }); + + it("should response with false when no match", (done) => { + const res = {}; + const req = { + params: { + name: "foo", + }, + }; + + headers.one(req, res, () => { + res.body.should.be.false(); + + done(); + }); + }); +}); + +describe("/header/:name", () => { + it("should response with all headers", (done) => { + const res = {}; + const req = { + har: { + log: { + entries: [ + { + request: { + headers: ["test"], + headersSize: 0, + }, + }, + ], + }, + }, + }; + + headers.all(req, res, () => { + res.body.should.eql(req.har.log.entries[0].request); + + done(); + }); + }); +}); diff --git a/test/routes/hello.js b/test/routes/hello.js index a95ec238..421b2d35 100644 --- a/test/routes/hello.js +++ b/test/routes/hello.js @@ -1,19 +1,17 @@ /* global describe, it */ -'use strict' +const hello = require("../../lib/routes/hello"); -var hello = require('../../lib/routes/hello') +require("should"); -require('should') +describe("/", () => { + it("should respond with Hello World", (done) => { + const res = {}; -describe('/', function () { - it('should respond with Hello World', function (done) { - var res = {} + hello(null, res, () => { + res.body.should.equal("Hello World!"); - hello(null, res, function () { - res.body.should.equal('Hello World!') - - done() - }) - }) -}) + done(); + }); + }); +}); diff --git a/test/routes/ips.js b/test/routes/ips.js index dd3037db..dbdb8c5b 100644 --- a/test/routes/ips.js +++ b/test/routes/ips.js @@ -1,42 +1,40 @@ /* global describe, it */ -'use strict' - -var ips = require('../../lib/routes/ips') - -require('should') - -describe('/ip', function () { - it('should response with ip address', function (done) { - var res = {} - var req = { - ip: '0.0.0.0' - } - - ips.one(req, res, function () { - res.body.should.equal(req.ip) - - done() - }) - }) -}) - -describe('/ips', function () { - it('should response with all address', function (done) { - var res = {} - var req = { - forwarded: { - for: { - '0.0.0.0': -1, - '1.1.1.1': -1 - } - } - } - - ips.all(req, res, function () { - res.body.should.equal(req.forwarded.for) - - done() - }) - }) -}) +const ips = require("../../lib/routes/ips"); + +require("should"); + +describe("/ip", () => { + it("should response with ip address", (done) => { + const res = {}; + const req = { + ip: "0.0.0.0", + }; + + ips.one(req, res, () => { + res.body.should.equal(req.ip); + + done(); + }); + }); +}); + +describe("/ips", () => { + it("should response with all address", (done) => { + const res = {}; + const req = { + forwarded: { + for: { + "0.0.0.0": -1, + "1.1.1.1": -1, + }, + }, + }; + + ips.all(req, res, () => { + res.body.should.equal(req.forwarded.for); + + done(); + }); + }); +}); diff --git a/test/routes/redirect.js b/test/routes/redirect.js index cd7d12e6..bffbcf5d 100644 --- a/test/routes/redirect.js +++ b/test/routes/redirect.js @@ -1,128 +1,128 @@ /* global describe, it */ -'use strict' - -var redirect = require('../../lib/routes/redirect') - -require('should') - -var res = { - redirect: function (status, target) { - res.status = status - res.target = target - } -} - -describe('/redirect/:status_code/:count', function () { - it('should use default values', function (done) { - var req = { - query: {}, - params: {} - } - - redirect(req, res) - res.status.should.equal(302) - res.target.should.equal('/redirect/302/0') - - done() - }) - - it('should use redirect x times', function (done) { - var req = { - query: {}, - - params: { - count: 3 - } - } - - redirect(req, res) - res.status.should.equal(302) - res.target.should.equal('/redirect/302/2') - - done() - }) - - it('should use redirect with custom status', function (done) { - var req = { - query: {}, - - params: { - count: 3, - status_code: 308 - } - } - - redirect(req, res) - res.status.should.equal(308) - res.target.should.equal('/redirect/308/2') - - done() - }) - - it('should use redirect to custom target eventually', function (done) { - var req = { - query: { - to: 'http://mockbin.org' - }, - - params: { - count: 3, - status_code: 308 - } - } - - redirect(req, res) - res.status.should.equal(308) - res.target.should.equal('/redirect/308/2?to=http://mockbin.org') - - done() - }) - - it('should use redirect to custom target', function (done) { - var req = { - query: { - to: 'http://mockbin.org' - }, - - params: { - count: 1, - status_code: 308 - } - } - - redirect(req, res) - res.status.should.equal(308) - res.target.should.equal('http://mockbin.org') - - done() - }) - - it('should reject invalid redirect status code', function (done) { - var req = { - params: { - status_code: 400 - } - } - - redirect(req, res, function () { - res.body.should.have.property('error') - res.body.error.should.equal('invalid status code, must be one of 300,301,302,303,307,308') - done() - }) - }) - - it('should finish redirecting', function (done) { - var req = { - query: {}, - params: { - count: '0' - } - } - - redirect(req, res, function () { - res.body.should.equal('redirect finished') - done() - }) - }) -}) +const redirect = require("../../lib/routes/redirect"); + +require("should"); + +const res = { + redirect: (status, target) => { + res.status = status; + res.target = target; + }, +}; + +describe("/redirect/:status_code/:count", () => { + it("should use default values", (done) => { + const req = { + query: {}, + params: {}, + }; + + redirect(req, res); + res.status.should.equal(302); + res.target.should.equal("/redirect/302/0"); + + done(); + }); + + it("should use redirect x times", (done) => { + const req = { + query: {}, + + params: { + count: 3, + }, + }; + + redirect(req, res); + res.status.should.equal(302); + res.target.should.equal("/redirect/302/2"); + + done(); + }); + + it("should use redirect with custom status", (done) => { + const req = { + query: {}, + + params: { + count: 3, + status_code: 308, + }, + }; + + redirect(req, res); + res.status.should.equal(308); + res.target.should.equal("/redirect/308/2"); + + done(); + }); + + it("should use redirect to custom target eventually", (done) => { + const req = { + query: { + to: "http://mockbin.org", + }, + + params: { + count: 3, + status_code: 308, + }, + }; + + redirect(req, res); + res.status.should.equal(308); + res.target.should.equal("/redirect/308/2?to=http://mockbin.org"); + + done(); + }); + + it("should use redirect to custom target", (done) => { + const req = { + query: { + to: "http://mockbin.org", + }, + + params: { + count: 1, + status_code: 308, + }, + }; + + redirect(req, res); + res.status.should.equal(308); + res.target.should.equal("http://mockbin.org"); + + done(); + }); + + it("should reject invalid redirect status code", (done) => { + const req = { + params: { + status_code: 400, + }, + }; + + redirect(req, res, () => { + res.body.should.have.property("error"); + res.body.error.should.equal( + "invalid status code, must be one of 300,301,302,303,307,308", + ); + done(); + }); + }); + + it("should finish redirecting", (done) => { + const req = { + query: {}, + params: { + count: "0", + }, + }; + + redirect(req, res, () => { + res.body.should.equal("redirect finished"); + done(); + }); + }); +}); diff --git a/test/routes/request.js b/test/routes/request.js index 82cdfc25..e383c686 100644 --- a/test/routes/request.js +++ b/test/routes/request.js @@ -1,23 +1,21 @@ /* global describe, it */ -'use strict' +const request = require("../../lib/routes/request"); -var request = require('../../lib/routes/request') +require("should"); -require('should') +describe("/request", () => { + // not much to test here, actual endpoint logic is tested elsewhere + it("should return object", (done) => { + const res = {}; + const req = { + simple: "foo", + }; -describe('/request', function () { - // not much to test here, actual endpoint logic is tested elsewhere - it('should return object', function (done) { - var res = {} - var req = { - simple: 'foo' - } + request(req, res, () => { + res.body.should.equal(req.simple); - request(req, res, function () { - res.body.should.equal(req.simple) - - done() - }) - }) -}) + done(); + }); + }); +}); diff --git a/test/routes/status.js b/test/routes/status.js index 27cd1d9f..b556508b 100644 --- a/test/routes/status.js +++ b/test/routes/status.js @@ -1,67 +1,65 @@ /* global describe, it */ -'use strict' - -var status = require('../../lib/routes/status') - -require('should') - -describe('/status/:code/:reason', function () { - it('should use defaults', function (done) { - var req = { - params: {} - } - - var res = {} - - status(req, res, function () { - res.statusCode.should.equal(200) - res.statusMessage.should.equal('OK') - - res.body.code.should.equal(200) - res.body.message.should.equal('OK') - - done() - }) - }) - - it('should use params', function (done) { - var req = { - params: { - code: 300, - reason: 'foo' - } - } - - var res = {} - - status(req, res, function () { - res.statusCode.should.equal(300) - res.statusMessage.should.equal('foo') - - res.body.code.should.equal(300) - res.body.message.should.equal('foo') - done() - }) - }) - - it('should replace + with spaces', function (done) { - var req = { - params: { - code: 300, - reason: 'foo+bar' - } - } - - var res = {} - - status(req, res, function () { - res.statusCode.should.equal(300) - res.statusMessage.should.equal('foo bar') - - res.body.code.should.equal(300) - res.body.message.should.equal('foo bar') - done() - }) - }) -}) +const status = require("../../lib/routes/status"); + +require("should"); + +describe("/status/:code/:reason", () => { + it("should use defaults", (done) => { + const req = { + params: {}, + }; + + const res = {}; + + status(req, res, () => { + res.statusCode.should.equal(200); + res.statusMessage.should.equal("OK"); + + res.body.code.should.equal(200); + res.body.message.should.equal("OK"); + + done(); + }); + }); + + it("should use params", (done) => { + const req = { + params: { + code: 300, + reason: "foo", + }, + }; + + const res = {}; + + status(req, res, () => { + res.statusCode.should.equal(300); + res.statusMessage.should.equal("foo"); + + res.body.code.should.equal(300); + res.body.message.should.equal("foo"); + done(); + }); + }); + + it("should replace + with spaces", (done) => { + const req = { + params: { + code: 300, + reason: "foo+bar", + }, + }; + + const res = {}; + + status(req, res, () => { + res.statusCode.should.equal(300); + res.statusMessage.should.equal("foo bar"); + + res.body.code.should.equal(300); + res.body.message.should.equal("foo bar"); + done(); + }); + }); +}); diff --git a/test/routes/stream.js b/test/routes/stream.js index 2532a387..2b434f0a 100644 --- a/test/routes/stream.js +++ b/test/routes/stream.js @@ -1,84 +1,94 @@ /* global describe, it */ -'use strict' - -var stream = require('../../lib/routes/stream') - -require('should') - -describe('/stream/:chunks', function () { - it('should respond with streamed chunks using default values', function (done) { - var req = { - params: {} - } - - var res = { - body: '', - - set: function (headers) { - res.headers = headers - }, - - write: function (body) { - res.body += body - }, - - end: function () { - res.headers.should.have.property('Content-Type').and.equal('text/plain; charset=utf-8') - res.headers.should.have.property('Transfer-Encoding').and.equal('chunked') - - res.body.should.equal([ - '{"type":"stream","chunk":1}', - '{"type":"stream","chunk":2}', - '{"type":"stream","chunk":3}', - '{"type":"stream","chunk":4}', - '{"type":"stream","chunk":5}', - '{"type":"stream","chunk":6}', - '{"type":"stream","chunk":7}', - '{"type":"stream","chunk":8}', - '{"type":"stream","chunk":9}', - '{"type":"stream","chunk":10}' - ].join('\n') + '\n') - - done() - } - } - - stream(req, res) - }) - - it('should respond with streamed chunks using specified chunks count', function (done) { - var req = { - params: { - chunks: 3 - } - } - - var res = { - body: '', - - set: function (headers) { - res.headers = headers - }, - - write: function (body) { - res.body += body - }, - - end: function () { - res.headers.should.have.property('Content-Type').and.equal('text/plain; charset=utf-8') - res.headers.should.have.property('Transfer-Encoding').and.equal('chunked') - - res.body.should.equal([ - '{"type":"stream","chunk":1}', - '{"type":"stream","chunk":2}', - '{"type":"stream","chunk":3}' - ].join('\n') + '\n') - - done() - } - } - - stream(req, res) - }) -}) +const stream = require("../../lib/routes/stream"); + +require("should"); + +describe("/stream/:chunks", () => { + it("should respond with streamed chunks using default values", (done) => { + const req = { + params: {}, + }; + + const res = { + body: "", + + set: (headers) => { + res.headers = headers; + }, + + write: (body) => { + res.body += body; + }, + + end: () => { + res.headers.should.have + .property("Content-Type") + .and.equal("text/plain; charset=utf-8"); + res.headers.should.have + .property("Transfer-Encoding") + .and.equal("chunked"); + + res.body.should.equal( + `${[ + '{"type":"stream","chunk":1}', + '{"type":"stream","chunk":2}', + '{"type":"stream","chunk":3}', + '{"type":"stream","chunk":4}', + '{"type":"stream","chunk":5}', + '{"type":"stream","chunk":6}', + '{"type":"stream","chunk":7}', + '{"type":"stream","chunk":8}', + '{"type":"stream","chunk":9}', + '{"type":"stream","chunk":10}', + ].join("\n")}\n`, + ); + + done(); + }, + }; + + stream(req, res); + }); + + it("should respond with streamed chunks using specified chunks count", (done) => { + const req = { + params: { + chunks: 3, + }, + }; + + const res = { + body: "", + + set: (headers) => { + res.headers = headers; + }, + + write: (body) => { + res.body += body; + }, + + end: () => { + res.headers.should.have + .property("Content-Type") + .and.equal("text/plain; charset=utf-8"); + res.headers.should.have + .property("Transfer-Encoding") + .and.equal("chunked"); + + res.body.should.equal( + `${[ + '{"type":"stream","chunk":1}', + '{"type":"stream","chunk":2}', + '{"type":"stream","chunk":3}', + ].join("\n")}\n`, + ); + + done(); + }, + }; + + stream(req, res); + }); +}); diff --git a/test/utils.js b/test/utils.js index 9f7e5b02..4f13f998 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,118 +1,118 @@ /* global describe, it */ -'use strict' - -var pkg = require('../package.json') -var utils = require('../lib/utils') - -require('should') - -var fixture = { - method: 'POST', - url: 'http://mockbin.com/', - protocol: 'http', - versionMajor: '1', - versionMinor: '1', - ip: '127.0.0.1', - body: '', - rawBody: '', - hostname: 'mockbin.com', - originalUrl: '/', - forwarded: { - proto: 'http' - }, - headers: { - foo: 'bar' - } -} - -describe('Utils', function () { - describe('ObjectToArray', function () { - it('should return blank array on undefined', function (done) { - var result = utils.objectToArray(undefined) - - result.should.be.an.Array() - result.length.should.be.equal(0) - - done() - }) - - it('should return blank array on invalid type', function (done) { - var result = utils.objectToArray('foo') - - result.should.be.an.Array() - result.length.should.be.equal(0) - - done() - }) - - it('should convert to name/value pair', function (done) { - var result = utils.objectToArray(fixture.headers) - - result.should.be.an.Array() - result.should.be.eql([{ - name: 'foo', - value: 'bar' - }]) - - done() - }) - }) - - describe('getReqHeaderSize', function () { - it('should calculate header size', function (done) { - var result = utils.getReqHeaderSize(fixture) - - result.should.be.a.Number() - result.should.be.equal(47) - - done() - }) - }) - - describe('createHar', function () { - var result = utils.createHar(fixture) - - result.log.entries[0].startedDateTime = 'now' - - result.should.be.an.Object() - result.should.eql({ - log: { - version: '1.2', - creator: { - name: 'mockbin.com', - version: pkg.version - }, - - entries: [{ - startedDateTime: 'now', - clientIPAddress: '127.0.0.1', - request: { - method: 'POST', - url: 'http://mockbin.com/', - httpVersion: 'HTTP/1.1', - cookies: [], - headers: [ - { - name: 'foo', - value: 'bar' - } - ], - queryString: [], - postData: { - mimeType: 'application/octet-stream', - params: [], - text: '' - }, - headersSize: 47, - bodySize: 0 - } - }] - } - }) - }) - - describe('createSimpleHar', function () { - - }) -}) +const pkg = require("../package.json"); +const utils = require("../lib/utils"); + +require("should"); + +const fixture = { + method: "POST", + url: "http://mockbin.com/", + protocol: "http", + versionMajor: "1", + versionMinor: "1", + ip: "127.0.0.1", + body: "", + rawBody: "", + hostname: "mockbin.com", + originalUrl: "/", + forwarded: { + proto: "http", + }, + headers: { + foo: "bar", + }, +}; + +describe("Utils", () => { + describe("ObjectToArray", () => { + it("should return blank array on undefined", (done) => { + const result = utils.objectToArray(undefined); + + result.should.be.an.Array(); + result.length.should.be.equal(0); + + done(); + }); + + it("should return blank array on invalid type", (done) => { + const result = utils.objectToArray("foo"); + + result.should.be.an.Array(); + result.length.should.be.equal(0); + + done(); + }); + + it("should convert to name/value pair", (done) => { + const result = utils.objectToArray(fixture.headers); + + result.should.be.an.Array(); + result.should.be.eql([ + { + name: "foo", + value: "bar", + }, + ]); + + done(); + }); + }); + + describe("getReqHeaderSize", () => { + it("should calculate header size", (done) => { + const result = utils.getReqHeaderSize(fixture); + + result.should.be.a.Number(); + result.should.be.equal(47); + + done(); + }); + }); + + describe("createHar", () => { + const result = utils.createHar(fixture); + + result.log.entries[0].startedDateTime = "now"; + + result.should.be.an.Object(); + result.should.eql({ + log: { + version: "1.2", + creator: { + name: "mockbin.com", + version: pkg.version, + }, + + entries: [ + { + startedDateTime: "now", + clientIPAddress: "127.0.0.1", + request: { + method: "POST", + url: "http://mockbin.com/", + httpVersion: "HTTP/1.1", + cookies: [], + headers: [ + { + name: "foo", + value: "bar", + }, + ], + queryString: [], + postData: { + mimeType: "application/octet-stream", + params: [], + text: "", + }, + headersSize: 47, + bodySize: 0, + }, + }, + ], + }, + }); + }); + + describe("createSimpleHar", () => {}); +});