@@ -47,8 +47,8 @@ module.exports = Class.extend(
47
47
} ,
48
48
49
49
autoRoute : function ( app ) {
50
- var middleware = [ ]
51
- , routes = this . route . split ( '|' )
50
+ var middleware = [ ]
51
+ , routes = this . route instanceof Array ? this . route : this . route . split ( '|' ) ;
52
52
53
53
debug ( 'Autorouting for route ' + routes . join ( ', ' ) ) ;
54
54
@@ -66,33 +66,39 @@ module.exports = Class.extend(
66
66
67
67
// Bind the actual routes
68
68
routes . forEach ( function ( route ) {
69
- var actionIdRoute = [ route , ':action' , ':id?' ] . join ( '/' )
70
- , actionRoute = [ route , ':action?' ] . join ( '/' ) ;
69
+ var methods = [ 'GET' , 'POST' , 'PUT' , 'DELETE' ] ;
71
70
72
- debug ( 'Attaching route ' + actionIdRoute ) ;
73
- app . all . apply ( app , [ actionIdRoute ] . concat ( middleware ) ) ; // /example/:action/:id?
74
-
75
- debug ( 'Attaching route ' + actionRoute ) ;
76
- app . all . apply ( app , [ actionRoute ] . concat ( middleware ) ) ; // /example/?:action?
71
+ debug ( 'Attaching route ' + route ) ;
72
+ if ( / ( ^ [ ^ \/ ] + ) \ ? ( \/ .* ) / ig. test ( route ) ) {
73
+ methods = RegExp . $1 ;
74
+ route = RegExp . $2 ;
75
+ methods = methods . match ( / \[ ( [ ^ \[ \] ] + ) \] / ig ) ;
76
+
77
+ if ( methods . length ) {
78
+ methods = methods [ 0 ] . replace ( / ( \[ | \] ) / ig, '' ) ;
79
+ methods = methods . split ( ',' ) ;
80
+ }
81
+ }
82
+
83
+ methods . forEach ( function ( method ) {
84
+ app [ method . toLowerCase ( ) ] . apply ( app , [ route ] . concat ( middleware ) ) ;
85
+ } ) ;
77
86
} ) ;
78
87
} ,
79
88
80
89
extend : function ( ) {
81
90
var extendingArgs = [ ] . slice . call ( arguments )
82
- , autoRouting = ( extendingArgs . length === 2 )
83
- ? extendingArgs [ 0 ] . autoRouting !== false
84
- : this . autoRouting
85
- , definedRoute = ( extendingArgs . length === 2 )
86
- ? extendingArgs [ 0 ] . route !== undefined
87
- : this . route ;
91
+ , autoRouting = ( extendingArgs . length === 2 ) ? extendingArgs [ 0 ] . autoRouting !== false : this . autoRouting
92
+ , definedRoute = ( extendingArgs . length === 2 ) ? extendingArgs [ 0 ] . route !== undefined : this . route ;
88
93
89
94
// Figure out if we are autoRouting and do not have a defined route already
90
95
if ( autoRouting && ! definedRoute ) {
91
96
var stack = new Error ( ) . stack . split ( '\n' )
92
- , stack = stack . splice ( 1 , stack . length - 1 )
93
97
, extendingFilePath = false
94
98
, extendingFileName = false
95
99
, route = null ;
100
+
101
+ stack = stack . splice ( 1 , stack . length - 1 ) ;
96
102
97
103
// Walk backwards over the stack to find the filename where this is defined
98
104
while ( stack . length > 0 && extendingFilePath === false ) {
@@ -110,7 +116,13 @@ module.exports = Class.extend(
110
116
var singular = i . singularize ( extendingFileName . replace ( / ( c o n t r o l l e r ) ? .j s / ig, '' ) . toLowerCase ( ) )
111
117
, plural = i . pluralize ( singular ) ;
112
118
113
- route = [ '/' , singular , '|' , '/' , plural ] . join ( '' ) ;
119
+ route = [ ] ;
120
+ route . push ( '/' + singular + '/:id/?' ) ;
121
+ route . push ( '/' + singular + '/:id/:action/?' ) ;
122
+ route . push ( '/' + plural + '/?' ) ;
123
+ route . push ( '/' + plural + '/:action/?' ) ;
124
+
125
+ route = route . join ( '|' ) ;
114
126
115
127
if ( extendingArgs . length === 2 ) {
116
128
extendingArgs [ 0 ] . route = route ;
@@ -132,7 +144,11 @@ module.exports = Class.extend(
132
144
resFunc : 'json' ,
133
145
action : null ,
134
146
135
- setup : function ( req , res , next ) {
147
+ setup : function ( req , res , next ) {
148
+ this . next = next ;
149
+ this . req = req ;
150
+ this . res = res ;
151
+
136
152
try {
137
153
return this . performanceSafeSetup ( req , res , next ) ;
138
154
} catch ( e ) {
@@ -141,80 +157,48 @@ module.exports = Class.extend(
141
157
} ,
142
158
143
159
performanceSafeSetup : function ( req , res , next ) {
144
- var method = null
145
- , funcName = null
146
- , parts = null ;
147
-
148
- this . next = next ;
149
- this . req = req ;
150
- this . res = res ;
151
-
152
- // Override routes where you attach specifically to a single route
153
- if ( this . Class . actionRouting && / \/ / . test ( this . req . url ) ) {
154
- parts = this . req . url . split ( '/' ) ;
155
- funcName = parts [ parts . length - 1 ] ;
156
-
157
- if ( / \# | \? / . test ( funcName ) ) {
158
- funcName = funcName . split ( / \# | \? / ) [ 0 ] ;
159
- }
160
-
161
- if ( isNaN ( funcName ) ) {
162
- funcName = funcName + 'Action' ;
163
- if ( typeof this [ funcName ] == 'function' ) {
164
- debug ( 'actionRouting mapped to ' + funcName ) ;
165
-
166
- return [ null , funcName , next ] ;
167
- }
168
- }
160
+ var methodAction = req . method . toLowerCase ( ) + 'Action'
161
+ , actionRouting = this . Class . actionRouting
162
+ , actionMethod = / \/ ( [ a - z A - z ] + ) ( \/ ? | \? .* | \# .* ) ? $ / ig. test ( req . url ) ? RegExp . $1 + 'Action' : ( req . params . action !== undefined ? req . params . action : false )
163
+ , restfulRouting = this . Class . restfulRouting
164
+ , idRegex = / ( ^ [ 0 - 9 ] + $ | ^ [ 0 - 9 a - f A - F ] { 24 } $ ) /
165
+ , hasIdParam = req . params && req . params . id !== undefined ? true : false
166
+ , id = ! ! hasIdParam && idRegex . test ( req . params . id ) ? req . params . id : false
167
+ , hasActionParam = req . params && req . params . action !== undefined ? true : false
168
+ , action = ! ! hasActionParam && ! idRegex . test ( req . params . action ) ? req . params . action + 'Action' : false ;
169
+
170
+ // console.log( 'methodAction:' + methodAction );
171
+ // console.log( 'actionMethod:' + actionMethod );
172
+ // console.log( 'actionRouting:' + actionRouting );
173
+ // console.log( 'actionMethod:' + actionMethod );
174
+ // console.log( 'restfulRouting:' + restfulRouting );
175
+ // console.log( 'hasIdParam:' + hasIdParam );
176
+ // console.log( 'id:' + id );
177
+ // console.log( 'hasActionParam:' + hasActionParam );
178
+ // console.log( 'action:' + action );
179
+
180
+ if ( ! ! actionRouting && ! ! hasActionParam && action !== false && typeof this [ action ] === 'function' ) {
181
+ debug ( 'actionRouting: mapped by url to ' + action ) ;
182
+ return [ null , action , next ] ;
169
183
}
170
184
171
- // Route based on an action first if we can
172
- if ( this . Class . actionRouting && typeof this . req . params !== 'undefined' && typeof this . req . params . action !== 'undefined' ) {
173
- // Action Defined Routing
174
- // Updated to consider ObjectId's as numbers for Mongo ids
175
- if ( ! / ^ [ 0 - 9 a - f A - F ] { 24 } $ / . test ( this . req . params . action ) && isNaN ( this . req . params . action ) ) {
176
- funcName = this . req . params . action + 'Action' ;
177
-
178
- if ( typeof this [ funcName ] == 'function' ) {
179
- debug ( 'actionRouting mapped to ' + funcName ) ;
180
- return [ null , funcName , next ] ;
181
- } else {
182
- throw new NoActionException ( ) ;
183
- }
184
- } else {
185
- // HTTP Method Based Routing
186
- method = this . req . method . toLowerCase ( ) + 'Action' ;
187
- if ( typeof this [ method ] == 'function' ) {
188
- debug ( 'http method route mapped to ' + method ) ;
189
-
190
- this . req . params . id = this . req . params . action ;
191
- delete this . req . params . action ;
192
-
193
- return [ null , method , next ] ;
194
- } else {
195
- throw new NoActionException ( ) ;
196
- }
197
- }
185
+ if ( actionMethod !== false && typeof this [ actionMethod ] === 'function' ) {
186
+ debug ( 'actionRouting: mapped by param to ' + actionMethod ) ;
187
+ return [ null , actionMethod , next ] ;
198
188
}
199
189
200
- // Route based on the HTTP Method, otherwise throw an exception
201
- if ( this . Class . restfulRouting ) {
202
- if ( this . isGet ( ) && ( this . req . params === undefined || this . req . params . id === undefined ) && typeof this . listAction === 'function' ) {
203
- method = 'listAction' ;
204
-
205
- debug ( 'restfulRouting mapped to ' + method ) ;
206
- } else {
207
- method = this . req . method . toLowerCase ( ) + 'Action' ;
208
- if ( typeof this [ method ] != 'function' ) {
209
- throw new NoActionException ( ) ;
210
- }
190
+ if ( ! ! restfulRouting ) {
191
+ if ( methodAction === 'getAction' && ! id && typeof this . listAction === 'function' ) {
192
+ methodAction = 'listAction' ;
193
+ }
211
194
212
- debug ( 'restfulRouting mapped to ' + method ) ;
195
+ if ( typeof this [ methodAction ] === 'function' ) {
196
+ debug ( 'restfulRouting mapped to ' + methodAction ) ;
197
+ return [ null , methodAction , next ] ;
213
198
}
214
199
}
215
200
216
- // If we got this far without an action but with a method, then route based on that
217
- return [ null , method , next ] ;
201
+ return [ new NoActionException ( ) , null , next ] ;
218
202
} ,
219
203
220
204
init : function ( error , method , next ) {
0 commit comments