UNPKG

5.38 kBJavaScriptView Raw
1/**
2 * MOST Web Framework
3 * A JavaScript Web Framework
4 * http://themost.io
5 *
6 * Copyright (c) 2014, Kyriakos Barbounakis k.barbounakis@gmail.com, Anthi Oikonomou anthioikonomou@gmail.com
7 *
8 * Released under the BSD3-Clause license
9 * Date: 2014-06-10
10 */
11///
12var pluralize = require('pluralize');
13
14/**
15 * HttpRoute class provides routing functionality to HTTP requests
16 * @class
17 * @constructor
18 * @param {string|*=} route - A formatted string or an object which represents an HTTP route response url (e.g. /pages/:name.html, /user/edit.html).
19 * */
20function HttpRoute(route) {
21 if (typeof route === 'string') {
22 this.route = { url:route };
23 }
24 else if (typeof route === 'object') {
25 this.route = route;
26 }
27 this.routeData = { };
28
29 this.patterns = {
30 int:function() {
31 return "^[1-9]([0-9]*)$";
32 },
33 boolean:function() {
34 return "^true|false$"
35 },
36 decimal:function() {
37 return "^[+-]?[0-9]*\\.?[0-9]*$";
38 },
39 float:function() {
40 return "^[+-]?[0-9]*\\.?[0-9]*$";
41 },
42 guid:function() {
43 return "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$";
44 },
45 plural: function() {
46 return "^[a-zA-Z]+$";
47 },
48 string: function() {
49 return "^'(.*)'$"
50 },
51 date:function() {
52 return "^(datetime)?'\\d{4}-([0]\\d|1[0-2])-([0-2]\\d|3[01])(?:[T ](\\d+):(\\d+)(?::(\\d+)(?:\\.(\\d+))?)?)?(?:Z(-?\\d*))?([+-](\\d+):(\\d+))?'$";
53 },
54 };
55
56 this.parsers = {
57 int:function(v) {
58 return parseInt(v);
59 },
60 boolean:function(v) {
61 return (/^true$/ig.test(v));
62 },
63 decimal:function(v) {
64 return parseFloat(v);
65 },
66 float:function(v) {
67 return parseFloat(v);
68 },
69 plural:function(v) {
70 return pluralize.singular(v);
71 },
72 string:function(v) {
73 return v.replace(/^'/,'').replace(/'$/,'');
74 },
75 date:function(v) {
76 return new Date(Date.parse(v.replace(/^(datetime)?'/,'').replace(/'$/,'')));
77 }
78 }
79
80}
81
82/**
83 * @param {string} urlToMatch
84 * @return {boolean}
85 */
86HttpRoute.prototype.isMatch = function (urlToMatch) {
87 var self = this;
88 if (typeof self.route === 'undefined' || self.route==null) {
89 throw new Error("Route may not be null");
90 }
91 self.routeData = self.routeData || { };
92 if (typeof urlToMatch !== 'string')
93 return false;
94 if (urlToMatch.length === 0)
95 return false;
96 var str1 = urlToMatch, patternMatch, parser;
97 var k = urlToMatch.indexOf('?');
98 if (k >= 0)
99 str1 = urlToMatch.substr(0, k);
100 var re = /({([\w[\]]+)(?::\s*((?:[^{}\\]+|\\.|{(?:[^{}\\]+|\\.)*})+))?})|((:)([\w[\]]+))/ig;
101 var match = re.exec(this.route.url);
102 var params = [];
103 while(match) {
104 if (typeof match[2] === 'undefined') {
105 //parameter with colon (e.g. :id)
106 params.push({
107 name: match[6]
108 });
109 }
110 else if (typeof match[3] !== 'undefined') {
111 //common expressions
112 patternMatch = match[3];
113 parser = null;
114 if (typeof self.patterns[match[3]] === 'function') {
115 patternMatch = self.patterns[match[3]]();
116 if (typeof self.parsers[match[3]] === 'function') {
117 parser = self.parsers[match[3]];
118 }
119 }
120 params.push({
121 name: match[2],
122 pattern: new RegExp(patternMatch, "ig"),
123 parser: parser
124 });
125 }
126 else {
127 params.push({
128 name: match[2]
129 });
130 }
131 match = re.exec(this.route.url);
132 }
133 var str, matcher;
134 str = this.route.url.replace(re, "([\\$_\\-.:',+=%0-9\\w-]+)");
135 matcher = new RegExp("^" + str + "$", "ig");
136 match = matcher.exec(str1);
137 if (typeof match === 'undefined' || match === null) {
138 return false;
139 }
140 var decodedMatch;
141 for (var i = 0; i < params.length; i++) {
142 var param = params[i];
143 if (typeof param.pattern !== 'undefined') {
144 if (!param.pattern.test(match[i+1])) {
145 return false;
146 }
147 }
148 decodedMatch = decodeURIComponent(match[i+1]);
149 if (typeof param.parser === 'function') {
150 param.value = param.parser((match[i+1] !== decodedMatch) ? decodedMatch : match[i+1]);
151 }
152 else {
153 param.value = (match[i+1] !== decodedMatch) ? decodedMatch : match[i+1];
154 }
155
156 }
157 params.forEach(function(x) {
158 self.routeData[x.name] = x.value;
159 });
160 if (self.route.hasOwnProperty("controller")) {
161 self.routeData["controller"] = self.route["controller"];
162 }
163 if (self.route.hasOwnProperty("action")) {
164 self.routeData["action"] = self.route["action"];
165 }
166 return true;
167};
168
169
170if (typeof exports !== 'undefined') {
171 module.exports = {
172 HttpRoute:HttpRoute,
173 /**
174 * Creates a new instance of HttpRoute class
175 * @param {string|*=} route
176 * @returns {HttpRoute}
177 */
178 createInstance: function (route) {
179 return new HttpRoute(route);
180 }
181 };
182}
\No newline at end of file