Comparing version 0.1.4 to 0.1.5
@@ -9,3 +9,5 @@ /* | ||
var parse = require('url').parse; | ||
var path = require('path'); | ||
var path = require('path'); | ||
var fs = require('fs'); | ||
var qs = require('querystring'); | ||
@@ -80,6 +82,27 @@ /* | ||
serve: function (req, res) { | ||
var base = this.validate(req); | ||
var self = this, | ||
base = this.validate(req), | ||
filepath, | ||
parsed, | ||
query, | ||
data; | ||
if (base && base !== true) { | ||
if (this.scheme[base]) { | ||
this.scheme[base](req, res); | ||
query = parse(req.url).query, | ||
parsed = qs.parse(query); | ||
if (parsed.response) { | ||
this.scheme[base](req, res, parsed.response); | ||
} else if (parsed.file) { | ||
filepath = path.join(__dirname, parsed.file); | ||
fs.readFile(filepath, function (err, data) { | ||
if (err) { | ||
self.scheme.status(404, res); | ||
} | ||
self.scheme[base](req, res, data); | ||
}); | ||
} else { | ||
this.scheme[base](req, res, data); | ||
} | ||
} else { | ||
@@ -86,0 +109,0 @@ this.scheme.status(base, res); |
@@ -16,2 +16,4 @@ /* | ||
var RE_DELAY_RANGE = /(\d+)-(\d+)/; | ||
function mix(reciever, sender) { | ||
@@ -27,2 +29,6 @@ Object.keys(sender).forEach(function (key) { | ||
var rand = exports.rand = function (min, max) { | ||
return Math.random() * (max - min) + min; | ||
}; | ||
exports.headers = headers; | ||
@@ -42,19 +48,17 @@ | ||
exports.get = function (req, res) { | ||
var p = parse(req.url), | ||
code = ((req.method === 'GET' || req.method === 'HEAD' || req.method === 'OPTIONS') ? 200 : 403); | ||
exports.get = function (req, res, body) { | ||
var code = ((req.method === 'GET' || req.method === 'HEAD' || req.method === 'OPTIONS') ? 200 : 403); | ||
res.writeHead(code, headers); | ||
res.end(p.query || ''); | ||
res.end(body || parse(req.url).query || ''); | ||
}; | ||
exports['delete'] = function (req, res) { | ||
var p = parse(req.url), | ||
code = ((req.method === 'DELETE') ? 200 : 403); | ||
exports['delete'] = function (req, res, body) { | ||
var code = ((req.method === 'DELETE') ? 200 : 403); | ||
res.writeHead(code, headers); | ||
res.end(p.query || ''); | ||
res.end(body || parse(req.url).query || ''); | ||
}; | ||
var post = function (method, req, res) { | ||
var post = function (method, req, res, body) { | ||
var data = '', | ||
@@ -67,5 +71,8 @@ gotData = false, | ||
var body = Object.keys(qs.parse(data)).length > 0 ? data : '', | ||
code; | ||
var code; | ||
if (!body) { | ||
body = Object.keys(qs.parse(data)).length > 0 ? data : ''; | ||
} | ||
if (req.method === method) { | ||
@@ -84,3 +91,5 @@ code = body ? 200 : 204; | ||
// Check if we have data, and aid Express' `req` object. | ||
if (req.body && Object.keys(req.body).length) { | ||
if (body) { | ||
end(); | ||
} else if (req.body && Object.keys(req.body).length) { | ||
data = qs.stringify(req.body); | ||
@@ -109,28 +118,50 @@ gotData = true; | ||
exports.post = function (req, res) { | ||
post('POST', req, res); | ||
exports.post = function (req, res, body) { | ||
post('POST', req, res, body); | ||
}; | ||
exports.put = function (req, res) { | ||
post('PUT', req, res); | ||
exports.put = function (req, res, body) { | ||
post('PUT', req, res, body); | ||
}; | ||
exports.delay = function (req, res) { | ||
exports.delay = function (req, res, body) { | ||
var path = parse(req.url).pathname, | ||
parts = path.split('/delay/')[1].split('/'), | ||
delay = parts[0], | ||
scheme = parts[1], | ||
range = delay.match(RE_DELAY_RANGE), | ||
seconds; | ||
var delay = parseInt(req.url.split('/').pop(), 10), | ||
seconds = (delay * 1000); | ||
if (range) { | ||
seconds = rand(parseInt(range[1], 10), parseInt(range[2], 10)); | ||
} else { | ||
seconds = parseInt(delay, 10) || 0; | ||
} | ||
setTimeout(function () { | ||
res.writeHead(200, headers); | ||
res.end('waited for ' + delay + ' seconds'); | ||
}, seconds); | ||
if (scheme && exports[scheme]) { | ||
exports[scheme](req, res, body); | ||
} else { | ||
res.writeHead(200, headers); | ||
res.end('waited for ' + seconds + ' seconds'); | ||
} | ||
}, seconds * 1000); | ||
}; | ||
exports.json = function (req, res) { | ||
var p = parse(req.url), | ||
json = (p.query ? JSON.stringify(qs.parse(p.query)) : '{ "echo": true }'); | ||
exports.json = function (req, res, body) { | ||
var json = body; | ||
if (req.body) { | ||
if (json) { | ||
// Validate. | ||
try { | ||
JSON.parse(json); | ||
} catch (ex) { | ||
return exports.status(400, res); | ||
} | ||
} else if (req.body && Object.keys(req.body).length) { | ||
json = JSON.stringify(req.body); | ||
} else if (parse(req.url).query) { | ||
json = JSON.stringify(qs.parse(parse(req.url).query)); | ||
} else { | ||
json = '{ "echo": true }'; | ||
} | ||
@@ -137,0 +168,0 @@ |
@@ -5,3 +5,3 @@ { | ||
"author": "Dav Glass <davglass@gmail.com>", | ||
"version": "0.1.4", | ||
"version": "0.1.5", | ||
"devDependencies": { | ||
@@ -8,0 +8,0 @@ "vows": "*", |
@@ -35,2 +35,25 @@ EchoEcho | ||
Delayed Responses | ||
----------------- | ||
You can delay an `echoecho` request with the `delay` route followed by a value | ||
in seconds (e.g., `/delay/3`) or a range in seconds (e.g., `/delay/1-3`). Given | ||
a range, the response will be delayed by a random period of time within the | ||
range. | ||
You can also delay any route by prepending the delay route (e.g., | ||
`/delay/2/get`, `/delay/1-2/json?response={"hello":"world"}`, etc). | ||
Customized Responses | ||
-------------------- | ||
You can customize the response content for any route (except for `status`) | ||
by specifying either a `response` or `file` query parameter. | ||
The `response` query parameter lets you specify the custom response in the URL, | ||
whereas the `file` query parameter will attempt to read a file on the server. | ||
The above ways of specifying custom responses will also work with any delayed | ||
route. | ||
Using in Your Server | ||
@@ -37,0 +60,0 @@ -------------------- |
@@ -5,3 +5,4 @@ var vows = require('vows'), | ||
parse = require('url').parse, | ||
qs = require('querystring'); | ||
qs = require('querystring'), | ||
fs = require('fs'), | ||
echoecho = require('../lib/echo'); | ||
@@ -448,2 +449,12 @@ | ||
}, | ||
'and handle invalid custom json': { | ||
topic: function() { | ||
fetch({ | ||
path: '/foo/bar/baz/echo/json?response=invalidJSON' | ||
}, this.callback); | ||
}, | ||
'with query body': function(res) { | ||
assert.equal(res.body, 'Bad Request'); | ||
} | ||
}, | ||
"and post custom json, express style": { | ||
@@ -609,2 +620,29 @@ topic: function() { | ||
}, | ||
'and delay by a range of seconds': { | ||
topic: function() { | ||
fetch({ | ||
method: 'GET', | ||
path: '/foo/bar/baz/echo/delay/1-3' | ||
}, this.callback); | ||
}, | ||
'with query body': function(res) { | ||
var delay = res.body.match(/[\d.]+/); | ||
delay = delay && parseFloat(delay); | ||
assert(delay <= 3, 'delay should be less than 3 seconds'); | ||
assert(delay >= 1, 'delay should be more than 1 second'); | ||
assert.equal(res.code, 200); | ||
} | ||
}, | ||
'and default to 0 for bad delay values': { | ||
topic: function() { | ||
fetch({ | ||
method: 'GET', | ||
path: '/foo/bar/baz/echo/delay/delay' | ||
}, this.callback); | ||
}, | ||
'with query body': function(res) { | ||
assert.equal(res.code, 200); | ||
assert.equal(res.body, 'waited for 0 seconds'); | ||
} | ||
}, | ||
'should be instantitable': { | ||
@@ -733,3 +771,126 @@ 'should be different objects': { | ||
// -- Setup for general testing of routes ------------------------------------- | ||
var testRoutes = [{ | ||
name: 'get', | ||
method: 'GET' | ||
}, { | ||
name: 'post', | ||
method: 'POST' | ||
}, { | ||
name: 'json', | ||
method: 'GET' | ||
}, { | ||
name: 'json', | ||
method: 'POST' | ||
}, { | ||
name: 'put', | ||
method: 'PUT' | ||
}, { | ||
name: 'delete', | ||
method: 'DELETE' | ||
} | ||
]; | ||
// -- `response` query parameter tests ---------------------------------------- | ||
function assertResponseParam(route, method) { | ||
var json = '{"diaper":"huggies"}'; | ||
path = '/foo/bar/baz/echo/' + route + '?response=' + json | ||
context = { | ||
topic: function() { | ||
fetch({ | ||
method: method, | ||
path: path | ||
}, this.callback); | ||
} | ||
}; | ||
context[route + ' route should use custom response'] = function (res) { | ||
assert.equal(res.body, json); | ||
} | ||
return context; | ||
} | ||
tests['should be loaded'] | ||
['and should load paths'] | ||
['and should use custom response (query)'] = {}; | ||
testRoutes.forEach(function (route) { | ||
tests['should be loaded'] | ||
['and should load paths'] | ||
['and should use custom response (query)'] | ||
['for route ' + route.name + ' with method ' + route.method] | ||
= assertResponseParam(route.name, route.method); | ||
}); | ||
// -- `file` query parameter tests -------------------------------------------- | ||
var file = fs.readFileSync(__dirname + '/fixtures/file.json', 'utf8'); | ||
function assertFileParam(route, method) { | ||
var path = '/foo/bar/baz/echo/' + route + '?file=../tests/fixtures/file.json' | ||
context = { | ||
topic: function() { | ||
fetch({ | ||
method: method, | ||
path: path | ||
}, this.callback); | ||
} | ||
}; | ||
context[route + ' route should use custom response'] = function (res) { | ||
assert.equal(res.body, file); | ||
} | ||
return context; | ||
} | ||
tests['should be loaded'] | ||
['and should load paths'] | ||
['and should use custom response (file)'] = {}; | ||
testRoutes.forEach(function (route) { | ||
tests['should be loaded'] | ||
['and should load paths'] | ||
['and should use custom response (file)'] | ||
['for route ' + route.name + ' with method ' + route.method] | ||
= assertFileParam(route.name, route.method); | ||
}); | ||
// -- delayable routes -------------------------------------------------------- | ||
function assertDelayedRoute(route, method) { | ||
var json = '{"megatron":"decepticon","optimus":"autobot"}', | ||
path = '/foo/bar/baz/echo/delay/1/' + route + '?response=' + json, | ||
context = { | ||
topic: function() { | ||
fetch({ | ||
method: method, | ||
path: path | ||
}, this.callback); | ||
} | ||
}; | ||
context[route + ' route should be delayed'] = function (res) { | ||
assert.equal(res.body, json); | ||
} | ||
return context; | ||
} | ||
tests['should be loaded'] | ||
['and should load paths'] | ||
['and routes should be delayable'] = {}; | ||
testRoutes.forEach(function (route) { | ||
tests['should be loaded'] | ||
['and should load paths'] | ||
['and routes should be delayable'] | ||
['for route ' + route.name + ' with method ' + route.method] | ||
= assertDelayedRoute(route.name, route.method); | ||
}); | ||
vows.describe('echoecho').addBatch(tests).export(module); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
47199
10
1127
143
2
41