@@ -4,35 +4,43 @@ const { parse } = require('regexparam')
4
4
const { LRUCache : Cache } = require ( 'lru-cache' )
5
5
const queryparams = require ( '../utils/queryparams' )
6
6
7
+ // Default handlers as constants to avoid creating functions on each router instance
8
+ const DEFAULT_ROUTE = ( req , res ) => {
9
+ res . statusCode = 404
10
+ res . end ( )
11
+ }
12
+
13
+ const DEFAULT_ERROR_HANDLER = ( err , req , res ) => {
14
+ res . statusCode = 500
15
+ res . end ( err . message )
16
+ }
17
+
18
+ // Simple ID generator
19
+ const generateId = ( ) => Math . random ( ) . toString ( 36 ) . substring ( 2 , 10 ) . toUpperCase ( )
20
+
7
21
module . exports = ( config = { } ) => {
8
- if ( config . defaultRoute === undefined ) {
9
- config . defaultRoute = ( req , res ) => {
10
- res . statusCode = 404
11
- res . end ( )
12
- }
13
- }
14
- if ( config . errorHandler === undefined ) {
15
- config . errorHandler = ( err , req , res ) => {
16
- res . statusCode = 500
17
- res . end ( err . message )
18
- }
19
- }
20
- if ( config . cacheSize === undefined ) {
21
- config . cacheSize = - 1
22
- }
23
- if ( config . id === undefined ) {
24
- config . id = ( Date . now ( ) . toString ( 36 ) + Math . random ( ) . toString ( 36 ) . substr ( 2 , 5 ) ) . toUpperCase ( )
25
- }
22
+ // Use object destructuring with defaults for cleaner config initialization
23
+ const {
24
+ defaultRoute = DEFAULT_ROUTE ,
25
+ errorHandler = DEFAULT_ERROR_HANDLER ,
26
+ cacheSize = - 1 ,
27
+ id = generateId ( )
28
+ } = config
26
29
27
30
const routers = { }
31
+
32
+ // Initialize cache only once
28
33
let cache = null
29
- if ( config . cacheSize > 0 ) {
30
- cache = new Cache ( { max : config . cacheSize } )
31
- } else if ( config . cacheSize < 0 ) {
32
- cache = new Map ( )
34
+ if ( cacheSize > 0 ) {
35
+ cache = new Cache ( { max : cacheSize } )
36
+ } else if ( cacheSize < 0 ) {
37
+ // For unlimited cache, still use LRUCache but with a very high max
38
+ // This provides better memory management than an unbounded Map
39
+ cache = new Cache ( { max : 100000 } )
33
40
}
41
+
34
42
const router = new Trouter ( )
35
- router . id = config . id
43
+ router . id = id
36
44
37
45
const _use = router . use
38
46
@@ -43,60 +51,73 @@ module.exports = (config = {}) => {
43
51
}
44
52
_use . call ( router , prefix , middlewares )
45
53
46
- if ( middlewares [ 0 ] . id ) {
54
+ if ( middlewares [ 0 ] ? .id ) {
47
55
// caching router -> pattern relation for urls pattern replacement
48
56
const { pattern } = parse ( prefix , true )
49
57
routers [ middlewares [ 0 ] . id ] = pattern
50
58
}
51
59
52
- return this
60
+ return router // Fix: return router instead of this
61
+ }
62
+
63
+ // Create the cleanup middleware once
64
+ const createCleanupMiddleware = ( step ) => ( req , res , next ) => {
65
+ req . url = req . preRouterUrl
66
+ req . path = req . preRouterPath
67
+
68
+ req . preRouterUrl = undefined
69
+ req . preRouterPath = undefined
70
+
71
+ return step ( )
53
72
}
54
73
55
74
router . lookup = ( req , res , step ) => {
56
- if ( ! req . url ) {
57
- req . url = '/'
58
- }
59
- if ( ! req . originalUrl ) {
60
- req . originalUrl = req . url
61
- }
75
+ // Initialize URL and originalUrl if needed
76
+ req . url = req . url || '/'
77
+ req . originalUrl = req . originalUrl || req . url
62
78
79
+ // Parse query parameters
63
80
queryparams ( req , req . url )
64
81
65
- let match
66
- if ( cache ) {
67
- const reqCacheKey = req . method + req . path
68
- match = cache . get ( reqCacheKey )
69
- if ( ! match ) {
70
- match = router . find ( req . method , req . path )
82
+ // Fast path for cache lookup
83
+ const reqCacheKey = cache && ( req . method + req . path )
84
+ let match = cache && cache . get ( reqCacheKey )
85
+
86
+ if ( ! match ) {
87
+ match = router . find ( req . method , req . path )
88
+ if ( cache && reqCacheKey ) {
71
89
cache . set ( reqCacheKey , match )
72
90
}
73
- } else {
74
- match = router . find ( req . method , req . path )
75
91
}
76
92
77
- if ( match . handlers . length > 0 ) {
78
- const middlewares = [ ...match . handlers ]
79
- if ( step !== undefined ) {
80
- // router is being used as a nested router
81
- middlewares . push ( ( req , res , next ) => {
82
- req . url = req . preRouterUrl
83
- req . path = req . preRouterPath
93
+ const { handlers, params } = match
84
94
85
- req . preRouterUrl = undefined
86
- req . preRouterPath = undefined
95
+ if ( handlers . length > 0 ) {
96
+ // Avoid creating a new array with spread operator
97
+ // Use the handlers array directly
98
+ let middlewares
87
99
88
- return step ( )
89
- } )
100
+ if ( step !== undefined ) {
101
+ // Only create a new array if we need to add the cleanup middleware
102
+ middlewares = handlers . slice ( )
103
+ middlewares . push ( createCleanupMiddleware ( step ) )
104
+ } else {
105
+ middlewares = handlers
90
106
}
91
107
108
+ // Initialize params object if needed
92
109
if ( ! req . params ) {
93
- req . params = { }
110
+ req . params = params
111
+ } else if ( params ) {
112
+ // Faster than Object.assign for small objects
113
+ for ( const key in params ) {
114
+ req . params [ key ] = params [ key ]
115
+ }
94
116
}
95
- Object . assign ( req . params , match . params )
96
117
97
- return next ( middlewares , req , res , 0 , routers , config . defaultRoute , config . errorHandler )
118
+ return next ( middlewares , req , res , 0 , routers , defaultRoute , errorHandler )
98
119
} else {
99
- config . defaultRoute ( req , res )
120
+ defaultRoute ( req , res )
100
121
}
101
122
}
102
123
0 commit comments