forked from APIDevTools/swagger-express-middleware
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpath-parser.js
146 lines (123 loc) · 4.36 KB
/
path-parser.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
145
146
"use strict";
module.exports = pathParser;
const _ = require("lodash");
const util = require("./helpers/util");
const paramParser = require("./param-parser");
/**
* Parses Swagger path parameters in the HTTP request.
* This middleware populates {@link Request#params} and {@link Request#pathParams}.
*
* NOTE: Express uses a special type of middleware for parsing path parameters.
* This middleware must be registered using {@link Router#param} rather than {@link Router#use}, {@link Router#get}, etc.
* In addition, path-parsing middleware must be registered for EACH path parameter in the Swagger API.
* See http://expressjs.com/4x/api.html#router.param for more info.
*
* @param {MiddlewareContext} context
* @param {express#Router} [router]
* @returns {function[]}
*/
function pathParser (context, router) {
router = util.isExpressRouter(router) ? router : context.router;
if (util.isExpressRouter(router)) {
// This is special path-param middleware, which sets `req.params`
registerPathParamMiddleware();
// If the API changes, register any new path-params
context.on("change", registerPathParamMiddleware);
}
else {
util.debug(
"WARNING! An Express Router/Application was not passed to the requestParser middleware. " +
"req.params will not be parsed. Use req.pathParams instead."
);
}
// This is normal middleware, which sets `req.pathParams`
return [parsePathParams];
/**
* Registers middleware to parse path parameters.
*/
function registerPathParamMiddleware () {
let pathParams = getAllPathParamNames();
pathParams.forEach((param) => {
if (!alreadyRegistered(param)) {
router.param(param, pathParamMiddleware);
}
});
}
/**
* Returns the unique names of all path params in the Swagger API.
*
* @returns {string[]}
*/
function getAllPathParamNames () {
let params = [];
function addParam (param) {
if (param.in === "path") {
params.push(param.name);
}
}
if (context.api) {
_.each(context.api.paths, (path) => {
// Add each path parameter
_.each(path.parameters, addParam);
// Add each operation parameter
_.each(path, (operation) => {
_.each(operation.parameters, addParam);
});
});
}
return _.uniq(params);
}
/**
* Determines whether we've already registered path-param middleware for the given parameter.
*
* @param {string} paramName
* @returns {boolean}
*/
function alreadyRegistered (paramName) {
let params = router.params;
if (!params && router._router) {
params = router._router.params;
}
return params && params[paramName] &&
(params[paramName].indexOf(pathParamMiddleware) >= 0);
}
/**
* This is a special type of Express middleware that specifically parses path parameters and sets `req.params`.
* See http://expressjs.com/4x/api.html#router.param
*/
function pathParamMiddleware (req, res, next, value, name) {
if (req.pathParams) {
// Path parameters have already been parsed by
req.params[name] = req.pathParams[name] || req.params[name];
}
next();
}
/**
* Parses all Swagger path parameters and sets `req.pathParams`.
* NOTE: This middleware cannot set `req.params`. That requires special path-param middleware (see above)
*/
function parsePathParams (req, res, next) {
if (util.isSwaggerRequest(req)) {
req.pathParams = {};
if (req.swagger.pathName.indexOf("{") >= 0) {
// Convert the Swagger path to a RegExp
let paramNames = [];
let pathPattern = req.swagger.pathName.replace(util.swaggerParamRegExp, (match, paramName) => {
paramNames.push(paramName);
return "([^\/]+)";
});
// Exec the RegExp to get the path param values from the URL
let values = new RegExp(pathPattern + "\/?$", "i").exec(req.path);
// Parse each path param
for (let i = 1; i < values.length; i++) {
let paramName = paramNames[i - 1];
let paramValue = decodeURIComponent(values[i]);
let param = _.find(req.swagger.params, { in: "path", name: paramName });
util.debug(' Parsing the "%s" path parameter', paramName);
req.pathParams[paramName] = paramParser.parseParameter(param, paramValue, param);
}
}
}
next();
}
}