blackbird-server
Version:
HTTP for JavaScript
624 lines (623 loc) • 18.4 kB
HTML
<html lang="en">
<head>
<title>Code coverage report for blackbird/modules/middleware/router.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../../prettify.css" />
<link rel="stylesheet" href="../../../base.css" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1>
<a href="../../../index.html">all files</a> / <a href="index.html">blackbird/modules/middleware/</a> router.js
</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">85.48% </span>
<span class="quiet">Statements</span>
<span class='fraction'>53/62</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">78.13% </span>
<span class="quiet">Branches</span>
<span class='fraction'>25/32</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">80% </span>
<span class="quiet">Functions</span>
<span class='fraction'>4/5</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">85.48% </span>
<span class="quiet">Lines</span>
<span class='fraction'>53/62</span>
</div>
</div>
</div>
<div class='status-line high'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet">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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187</td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2×</span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-yes">16×</span>
<span class="cline-any cline-yes">16×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">16×</span>
<span class="cline-any cline-yes">16×</span>
<span class="cline-any cline-yes">34×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">34×</span>
<span class="cline-any cline-yes">34×</span>
<span class="cline-any cline-yes">13×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">13×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">13×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">13×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">3×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">8×</span>
<span class="cline-any cline-yes">4×</span>
<span class="cline-any cline-yes">4×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">8×</span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">8×</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-yes">7×</span>
<span class="cline-any cline-yes">4×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">8×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">8×</span>
<span class="cline-any cline-yes">7×</span>
<span class="cline-any cline-yes">7×</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">7×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">8×</span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">8×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">8×</span>
<span class="cline-any cline-yes">3×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">8×</span>
<span class="cline-any cline-yes">11×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">11×</span>
<span class="cline-any cline-yes">5×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">6×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2×</span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2×</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">1×</span>
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">/* */
const d = require("describe-property");
const objectAssign = require("object-assign");
const compileRoute = require("../utils/compileRoute");
const isRegExp = require("../utils/isRegExp");
const makeParams = require("../utils/makeParams");
const RoutingProperties = require("../utils/RoutingProperties");
const LEADING_HTTP_METHOD_MATCHER = /^(DELETE|GET|HEAD|OPTIONS|POST|PUT|TRACE)\s+(.+)$/;
const {is, not, isEmpty, compose} = require("ramda"),
isnt = compose(not, is);
/**
* A middleware that provides pattern-based routing for URLs, with optional
* support for restricting matches to a specific request method. Named segments
* of the URL are added to conn.params and take precedence over all others.
*
* app.use(mach.router, {
*
* 'GET /login': function (conn) {
* // conn.method == 'GET'
* // conn.pathname == '/login'
* },
*
* 'POST /login': function (conn) {
* // conn.method == 'POST'
* // conn.pathname == '/login'
* },
*
* 'DELETE /users/:id': function (conn) {
* // conn.method == 'DELETE'
* // conn.pathname == '/users/5'
* // conn.params == { id: 5 }
* }
*
* });
*
* This function may also be used outside the context of a middleware stack
* to create a standalone app. Routes may be given one at a time:
*
* let app = mach.router();
*
* app.get('/login', function (conn) {
* // ...
* });
*
* app.delete('/users/:id', function (conn) {
* // ...
* });
*
* Or all at once:
*
* let app = mach.router({
*
* 'GET /login': function (conn) {
* // ...
* },
*
* 'DELETE /users/:id': function (conn) {
* // ...
* }
*
* });
*
* Note: Routes are always tried in the order they were defined.
*/
function createRouter(app, map) {
// Allow mach.router(map)
<span class="missing-if-branch" title="if path not taken" >I</span>if (typeof app === "object") {
<span class="cstat-no" title="statement not covered" > map = app;</span>
<span class="cstat-no" title="statement not covered" > app = null;</span>
}
const routes = {};
function router(conn) {
const method = conn.method;
const routesToTry = (routes[method] || []).concat(routes.ANY || []);
let route, match;
for (let i = 0, len = routesToTry.length; i < len; ++i) {
route = routesToTry[i];
// Try to match the route.
match = route.pattern.exec(conn.pathname);
if (match) {
const params = makeParams(route.keys, Reflect.apply(Array.prototype.slice, match, [1]));
<span class="missing-if-branch" title="if path not taken" >I</span>if (conn.params) {
// Route params take precedence above all others.
<span class="cstat-no" title="statement not covered" > objectAssign(conn.params, params);</span>
} else {
conn.params = params;
}
return conn.run(route.app);
}
}
return conn.run(app);
}
Object.defineProperties(router, {
/**
* Adds a new route that runs the given app when the pattern matches the
* path used in the request. If the pattern is a string, it is automatically
* compiled. The following signatures are supported:
*
* route('/users/:id', app)
* route('/users/:id', 'PUT', app)
* route('/users/:id', [ 'GET', 'PUT' ], app)
* route('GET /users/:id', app)
*/
route: d(function (pattern, methods, app) {
if (is(Function, methods)) {
app = methods;
methods = null;
}
<span class="missing-if-branch" title="if path not taken" >I</span>if (isnt(Function, app)) {
<span class="cstat-no" title="statement not covered" > throw new Error("Route needs an app");</span>
}
if (is(String, methods)) {
methods = [methods];
} else if (!Array.isArray(methods)) {
methods = [];
}
const keys = [];
if (is(String, pattern)) {
const match = pattern.match(LEADING_HTTP_METHOD_MATCHER);
if (match) {
methods.push(match[1]);
pattern = match[2];
}
pattern = compileRoute(pattern, keys);
}
<span class="missing-if-branch" title="if path not taken" >I</span>if (!isRegExp(pattern)) {
<span class="cstat-no" title="statement not covered" > throw new Error("Route pattern must be a RegExp");</span>
}
const route = {pattern, keys, app};
if (isEmpty(methods)) {
methods.push("ANY");
}
methods.forEach(function (method) {
const upperMethod = method.toUpperCase();
if (routes[upperMethod]) {
routes[upperMethod].push(route);
} else {
routes[upperMethod] = [route];
}
});
}),
/**
* Sets the given app as the default for this router.
*/
run: d(<span class="fstat-no" title="function not covered" >function (downstreamApp) {</span>
<span class="cstat-no" title="statement not covered" > app = downstreamApp;</span>
})
});
// Allow app.use(mach.router, map)
<span class="missing-if-branch" title="if path not taken" >I</span>if (is(Object, map)) {
<span class="cstat-no" title="statement not covered" > for (const route in map) {</span>
<span class="cstat-no" title="statement not covered" > if (map.hasOwnProperty(route)) {</span>
<span class="cstat-no" title="statement not covered" > router.route(route, map[route]);</span>
}
}
}
Object.defineProperties(router, RoutingProperties);
return router;
}
module.exports = createRouter;
</pre></td></tr>
</table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage
generated by <a href="http://istanbul-js.org/" target="_blank">istanbul</a> at Sun Jul 10 2016 13:30:36 GMT-0500 (CDT)
</div>
</div>
<script src="../../../prettify.js"></script>
<script>
window.onload = function () {
if (typeof prettyPrint === 'function') {
prettyPrint();
}
};
</script>
<script src="../../../sorter.js"></script>
</body>
</html>