UNPKG

3.09 kBJavaScriptView Raw
1/*
2Routing Primitives for Kettle Servers
3
4Copyright 2015 Raising the Floor (International)
5
6Licensed under the New BSD license. You may not use this file except in
7compliance with this License.
8
9You may obtain a copy of the License at
10https://github.com/fluid-project/kettle/blob/master/LICENSE.txt
11*/
12
13/* Contains code adapted from express 4.x "layer.js":
14 * Copyright(c) 2009-2013 TJ Holowaychuk
15 * Copyright(c) 2013 Roman Shtylman
16 * Copyright(c) 2014-2015 Douglas Christopher Wilson
17 * MIT Licensed
18 */
19
20"use strict";
21
22var fluid = require("infusion"),
23 urlModule = require("url"),
24 kettle = fluid.registerNamespace("kettle");
25
26// Upstream dependency stolen from express 4.x
27// Note that path-to-regexp 2.0.0 breaks compatibility with our use of /* to encode middleware matches - seems unlikely we will upgrade
28kettle.pathToRegexp = require("path-to-regexp");
29
30fluid.defaults("kettle.router.http", {
31 gradeNames: "fluid.component",
32 members: {
33 handlers: []
34 },
35 invokers: {
36 register: {
37 funcName: "kettle.router.http.register",
38 args: ["{that}", "{arguments}.0"]
39 },
40 match: {
41 funcName: "kettle.router.http.match",
42 args: ["{that}.handlers", "{arguments}.0"]
43 }
44 }
45});
46
47
48kettle.router.http.register = function (that, handler) {
49 var prefix = handler.prefix || "";
50 handler.regexp = kettle.pathToRegexp(prefix + handler.route, handler.keys = []);
51 that.handlers.push(handler);
52};
53
54kettle.router.registerOneHandlerImpl = function (that, handler, extend) {
55 var handlerCopy = fluid.extend({
56 method: "get"
57 }, handler, extend);
58 kettle.router.http.register(that, handlerCopy);
59};
60
61kettle.router.http.decodeParam = function (val) {
62 if (typeof val !== "string" || val.length === 0) {
63 return val;
64 }
65 try {
66 return decodeURIComponent(val);
67 } catch (err) {
68 err.message = "Failed to decode request routing parameter \"" + val + "\"";
69 err.status = err.statusCode = 400;
70 throw err;
71 }
72};
73
74kettle.router.http.matchToParams = function (handler, match) {
75 var params = {};
76 for (var i = 1; i < match.length; i++) {
77 var key = handler.keys[i - 1];
78 var prop = key.name;
79 var val = kettle.router.http.decodeParam(match[i]);
80
81 if (val !== undefined) {
82 params[prop] = val;
83 }
84 }
85 return params;
86};
87
88// cf. Router.prototype.matchRequest
89kettle.router.http.match = function (handlers, req) {
90 var method = req.method.toLowerCase(),
91 parsedUrl = urlModule.parse(req.url),
92 path = parsedUrl.pathname;
93 for (var i = 0; i < handlers.length; ++i) {
94 var handler = handlers[i];
95 if (method === handler.method) {
96 var match = handler.regexp.exec(path);
97 if (match) {
98 return {
99 handler: handler,
100 output: {
101 params: kettle.router.http.matchToParams(handler, match)
102 }
103 };
104 }
105 }
106 }
107};