rc@73
|
1 /*!
|
rc@73
|
2 * method-override
|
rc@73
|
3 * Copyright(c) 2010 Sencha Inc.
|
rc@73
|
4 * Copyright(c) 2011 TJ Holowaychuk
|
rc@73
|
5 * Copyright(c) 2014 Jonathan Ong
|
rc@73
|
6 * Copyright(c) 2014 Douglas Christopher Wilson
|
rc@73
|
7 * MIT Licensed
|
rc@73
|
8 */
|
rc@73
|
9
|
rc@73
|
10 /**
|
rc@73
|
11 * Module dependencies.
|
rc@73
|
12 */
|
rc@73
|
13
|
rc@73
|
14 var methods = require('methods');
|
rc@73
|
15 var parseurl = require('parseurl');
|
rc@73
|
16 var querystring = require('querystring');
|
rc@73
|
17 var vary = require('vary');
|
rc@73
|
18
|
rc@73
|
19 /**
|
rc@73
|
20 * Method Override:
|
rc@73
|
21 *
|
rc@73
|
22 * Provides faux HTTP method support.
|
rc@73
|
23 *
|
rc@73
|
24 * Pass an optional `getter` to use when checking for
|
rc@73
|
25 * a method override.
|
rc@73
|
26 *
|
rc@73
|
27 * A string is converted to a getter that will look for
|
rc@73
|
28 * the method in `req.body[getter]` and a function will be
|
rc@73
|
29 * called with `req` and expects the method to be returned.
|
rc@73
|
30 * If the string starts with `X-` then it will look in
|
rc@73
|
31 * `req.headers[getter]` instead.
|
rc@73
|
32 *
|
rc@73
|
33 * The original method is available via `req.originalMethod`.
|
rc@73
|
34 *
|
rc@73
|
35 * @param {string|function} [getter=X-HTTP-Method-Override]
|
rc@73
|
36 * @param {object} [options]
|
rc@73
|
37 * @return {function}
|
rc@73
|
38 * @api public
|
rc@73
|
39 */
|
rc@73
|
40
|
rc@73
|
41 module.exports = function methodOverride(getter, options){
|
rc@73
|
42 options = options || {}
|
rc@73
|
43
|
rc@73
|
44 // get the getter fn
|
rc@73
|
45 var get = typeof getter === 'function'
|
rc@73
|
46 ? getter
|
rc@73
|
47 : createGetter(getter || 'X-HTTP-Method-Override')
|
rc@73
|
48
|
rc@73
|
49 // get allowed request methods to examine
|
rc@73
|
50 var methods = options.methods === undefined
|
rc@73
|
51 ? ['POST']
|
rc@73
|
52 : options.methods
|
rc@73
|
53
|
rc@73
|
54 return function methodOverride(req, res, next) {
|
rc@73
|
55 var method
|
rc@73
|
56 var val
|
rc@73
|
57
|
rc@73
|
58 req.originalMethod = req.originalMethod || req.method
|
rc@73
|
59
|
rc@73
|
60 // validate request is on allowed method
|
rc@73
|
61 if (methods && methods.indexOf(req.originalMethod) === -1) {
|
rc@73
|
62 return next()
|
rc@73
|
63 }
|
rc@73
|
64
|
rc@73
|
65 val = get(req, res)
|
rc@73
|
66 method = Array.isArray(val)
|
rc@73
|
67 ? val[0]
|
rc@73
|
68 : val
|
rc@73
|
69
|
rc@73
|
70 // replace
|
rc@73
|
71 if (method !== undefined && supports(method)) {
|
rc@73
|
72 req.method = method.toUpperCase()
|
rc@73
|
73 }
|
rc@73
|
74
|
rc@73
|
75 next()
|
rc@73
|
76 }
|
rc@73
|
77 }
|
rc@73
|
78
|
rc@73
|
79 /**
|
rc@73
|
80 * Create a getter for the given string.
|
rc@73
|
81 */
|
rc@73
|
82
|
rc@73
|
83 function createGetter(str) {
|
rc@73
|
84 if (str.substr(0, 2).toUpperCase() === 'X-') {
|
rc@73
|
85 // header getter
|
rc@73
|
86 return createHeaderGetter(str)
|
rc@73
|
87 }
|
rc@73
|
88
|
rc@73
|
89 return createQueryGetter(str)
|
rc@73
|
90 }
|
rc@73
|
91
|
rc@73
|
92 /**
|
rc@73
|
93 * Create a getter for the given query key name.
|
rc@73
|
94 */
|
rc@73
|
95
|
rc@73
|
96 function createQueryGetter(key) {
|
rc@73
|
97 return function(req, res) {
|
rc@73
|
98 var url = parseurl(req)
|
rc@73
|
99 var query = querystring.parse(url.query || '')
|
rc@73
|
100 return query[key]
|
rc@73
|
101 }
|
rc@73
|
102 }
|
rc@73
|
103
|
rc@73
|
104 /**
|
rc@73
|
105 * Create a getter for the given header name.
|
rc@73
|
106 */
|
rc@73
|
107
|
rc@73
|
108 function createHeaderGetter(str) {
|
rc@73
|
109 var header = str.toLowerCase()
|
rc@73
|
110
|
rc@73
|
111 return function(req, res) {
|
rc@73
|
112 // set appropriate Vary header
|
rc@73
|
113 vary(res, str)
|
rc@73
|
114
|
rc@73
|
115 // multiple headers get joined with comma by node.js core
|
rc@73
|
116 return (req.headers[header] || '').split(/ *, */)
|
rc@73
|
117 }
|
rc@73
|
118 }
|
rc@73
|
119
|
rc@73
|
120 /**
|
rc@73
|
121 * Check if node supports `method`.
|
rc@73
|
122 */
|
rc@73
|
123
|
rc@73
|
124 function supports(method) {
|
rc@73
|
125 return method
|
rc@73
|
126 && typeof method === 'string'
|
rc@73
|
127 && methods.indexOf(method.toLowerCase()) !== -1
|
rc@73
|
128 }
|