@@ -47,8 +47,8 @@ module.exports = Class.extend(
4747 } ,
4848
4949 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 ( '|' ) ;
5252
5353 debug ( 'Autorouting for route ' + routes . join ( ', ' ) ) ;
5454
@@ -66,33 +66,39 @@ module.exports = Class.extend(
6666
6767 // Bind the actual routes
6868 routes . forEach ( function ( route ) {
69- var actionIdRoute = [ route , ':action' , ':id?' ] . join ( '/' )
70- , actionRoute = [ route , ':action?' ] . join ( '/' ) ;
69+ var methods = [ 'GET' , 'POST' , 'PUT' , 'DELETE' ] ;
7170
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+ } ) ;
7786 } ) ;
7887 } ,
7988
8089 extend : function ( ) {
8190 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 ;
8893
8994 // Figure out if we are autoRouting and do not have a defined route already
9095 if ( autoRouting && ! definedRoute ) {
9196 var stack = new Error ( ) . stack . split ( '\n' )
92- , stack = stack . splice ( 1 , stack . length - 1 )
9397 , extendingFilePath = false
9498 , extendingFileName = false
9599 , route = null ;
100+
101+ stack = stack . splice ( 1 , stack . length - 1 ) ;
96102
97103 // Walk backwards over the stack to find the filename where this is defined
98104 while ( stack . length > 0 && extendingFilePath === false ) {
@@ -110,7 +116,13 @@ module.exports = Class.extend(
110116 var singular = i . singularize ( extendingFileName . replace ( / ( c o n t r o l l e r ) ? .j s / ig, '' ) . toLowerCase ( ) )
111117 , plural = i . pluralize ( singular ) ;
112118
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 ( '|' ) ;
114126
115127 if ( extendingArgs . length === 2 ) {
116128 extendingArgs [ 0 ] . route = route ;
@@ -132,7 +144,11 @@ module.exports = Class.extend(
132144 resFunc : 'json' ,
133145 action : null ,
134146
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+
136152 try {
137153 return this . performanceSafeSetup ( req , res , next ) ;
138154 } catch ( e ) {
@@ -141,80 +157,48 @@ module.exports = Class.extend(
141157 } ,
142158
143159 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 ] ;
169183 }
170184
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 ] ;
198188 }
199189
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+ }
211194
212- debug ( 'restfulRouting mapped to ' + method ) ;
195+ if ( typeof this [ methodAction ] === 'function' ) {
196+ debug ( 'restfulRouting mapped to ' + methodAction ) ;
197+ return [ null , methodAction , next ] ;
213198 }
214199 }
215200
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 ] ;
218202 } ,
219203
220204 init : function ( error , method , next ) {
0 commit comments