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