Skip to content

Commit

Permalink
only POST requests are examined by default
Browse files Browse the repository at this point in the history
closes #3
  • Loading branch information
dougwilson committed Jun 1, 2014
1 parent ba3f24e commit 4fe3770
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 9 deletions.
1 change: 1 addition & 0 deletions History.md
Expand Up @@ -4,6 +4,7 @@ unreleased
* New interface, less magic
- Can specify what header to look for override in, if wanted
- Can specify custom function to get method from request
* Only `POST` requests are examined by default

1.0.2 / 2014-05-22
==================
Expand Down
11 changes: 10 additions & 1 deletion README.md
Expand Up @@ -18,12 +18,13 @@ $ npm install method-override
needs to know the method of the request (for example, it _must_ be used prior to
the `csurf` module).

### methodOverride(getter)
### methodOverride(getter, options)

Create a new middleware function to override the `req.method` property with a new
value. This value will be pulled from the provided `getter`.

- `getter` - The getter to use to look up the overridden request method for the request. (default: `_method`)
- `options.methods` - The allowed methods the original request must be in to check for a method override value. (default: `['POST']`)

If the found method is supported by node.js core, then `req.method` will be set to
this value, as if it has originally been that value. The previous `req.method`
Expand All @@ -41,6 +42,14 @@ string is provided, the string is used to look up the method with the following
- All other strings are treated as a property in `req.body`. If the property exists in `req.body`,
it is read and the entry is deleted from `req.body` for seamless method overrides in the body.

#### options.methods

This allows the specification of what methods(s) the request *MUST* be in in order to check for
the method override value. This defaults to only `POST` methods, which is the only method the
override should arrive in. More methods may be specified here, but it may introduce security
issues and cause weird behavior when requests travel through caches. This value is an array
of methods in upper-case. `null` can be specified to allow all methods.

## Examples

### override in POST bodies
Expand Down
17 changes: 16 additions & 1 deletion index.js
Expand Up @@ -28,19 +28,34 @@ var methods = require('methods');
* The original method is available via `req.originalMethod`.
*
* @param {string|function} [getter=_method]
* @param {object} [options]
* @return {function}
* @api public
*/

module.exports = function methodOverride(getter){
module.exports = function methodOverride(getter, options){
options = options || {}

// get the getter fn
var get = typeof getter === 'function'
? getter
: createGetter(getter || '_method')

// get allowed request methods to examine
var methods = options.methods === undefined
? ['POST']
: options.methods

return function methodOverride(req, res, next) {
var method

req.originalMethod = req.originalMethod || req.method

// validate request is on allowed method
if (methods && methods.indexOf(req.originalMethod) === -1) {
return next()
}

method = get(req)

// replace
Expand Down
54 changes: 47 additions & 7 deletions test/test.js
Expand Up @@ -22,7 +22,7 @@ describe('methodOverride(getter)', function(){
})

it('should be case in-sensitive', function(done){
var server = createServer('_method', {
var server = createServer('_method', null, {
_method: 'DELete'
})

Expand All @@ -33,7 +33,7 @@ describe('methodOverride(getter)', function(){
})

it('should ignore invalid methods', function(done){
var server = createServer('_method', {
var server = createServer('_method', null, {
_method: 'BOGUS'
})

Expand All @@ -44,7 +44,7 @@ describe('methodOverride(getter)', function(){
})

it('should remove key from req.body', function(done){
var server = createServer('_method', {
var server = createServer('_method', null, {
foo: 'bar',
_method: 'DELETE'
})
Expand All @@ -57,7 +57,7 @@ describe('methodOverride(getter)', function(){
})

it('should handle key referencing array', function(done){
var server = createServer('_method', {
var server = createServer('_method', null, {
foo: 'bar',
_method: ['DELETE', 'PUT']
})
Expand All @@ -70,7 +70,7 @@ describe('methodOverride(getter)', function(){
})

it('should handle key referencing object', function(done){
var server = createServer('_method', {
var server = createServer('_method', null, {
foo: 'bar',
_method: {}
})
Expand All @@ -81,6 +81,18 @@ describe('methodOverride(getter)', function(){
.expect('X-Got-Method', 'POST')
.expect(200, '{"foo":"bar"}', done)
})

it('should only work with POST', function(done){
var server = createServer('_method', null, {
_method: 'PATCH'
})

request(server)
.delete('/')
.set('Content-Type', 'application/json')
.expect('X-Got-Method', 'DELETE')
.expect(200, done)
})
})

describe('with header', function(){
Expand Down Expand Up @@ -152,10 +164,38 @@ describe('methodOverride(getter)', function(){
.expect('X-Got-Method', 'POST', done)
})
})

describe('given "options.methods"', function(){
it('should allow other methods', function(done){
var server = createServer('X-HTTP-Method-Override', { methods: ['POST', 'PATCH'] })
request(server)
.patch('/')
.set('Content-Type', 'application/json')
.set('X-HTTP-Method-Override', 'DELETE')
.expect('X-Got-Method', 'DELETE', done)
})

it('should allow all methods', function(done){
var server = createServer('X-HTTP-Method-Override', { methods: null })
request(server)
.patch('/')
.set('Content-Type', 'application/json')
.set('X-HTTP-Method-Override', 'DELETE')
.expect('X-Got-Method', 'DELETE', done)
})

it('should not call getter when method not allowed', function(done){
var server = createServer(function(req){ return 'DELETE' })
request(server)
.patch('/')
.set('Content-Type', 'application/json')
.expect('X-Got-Method', 'PATCH', done)
})
})
})

function createServer(key, _body) {
var _override = methodOverride(key)
function createServer(getter, opts, _body) {
var _override = methodOverride(getter, opts)
return http.createServer(function (req, res) {
req.body = _body
_override(req, res, function (err) {
Expand Down

0 comments on commit 4fe3770

Please sign in to comment.