@@ -10,6 +10,26 @@ import express from 'express';
10
10
import url from 'url' ;
11
11
import log from './logger' ;
12
12
import { inspect } from 'util' ;
13
+ import {
14
+ logRequest ,
15
+ logResponse
16
+ } from './SensitiveLogger' ;
17
+
18
+ const Layer = require ( 'express/lib/router/layer' ) ;
19
+
20
+ function validateParameter ( key , value ) {
21
+ if ( key == 'className' ) {
22
+ if ( value . match ( / _ ? [ A - Z a - z ] [ A - Z a - z _ 0 - 9 ] * / ) ) {
23
+ return value ;
24
+ }
25
+ } else if ( key == 'objectId' ) {
26
+ if ( value . match ( / [ A - Z a - z 0 - 9 ] + / ) ) {
27
+ return value ;
28
+ }
29
+ } else {
30
+ return value ;
31
+ }
32
+ }
13
33
14
34
export default class PromiseRouter {
15
35
// Each entry should be an object with:
@@ -65,7 +85,8 @@ export default class PromiseRouter {
65
85
this . routes . push ( {
66
86
path : path ,
67
87
method : method ,
68
- handler : handler
88
+ handler : handler ,
89
+ layer : new Layer ( path , null , handler )
69
90
} ) ;
70
91
} ;
71
92
@@ -78,30 +99,16 @@ export default class PromiseRouter {
78
99
if ( route . method != method ) {
79
100
continue ;
80
101
}
81
- // NOTE: we can only route the specific wildcards :className and
82
- // :objectId, and in that order.
83
- // This is pretty hacky but I don't want to rebuild the entire
84
- // express route matcher. Maybe there's a way to reuse its logic.
85
- var pattern = '^' + route . path + '$' ;
86
-
87
- pattern = pattern . replace ( ':className' ,
88
- '(_?[A-Za-z][A-Za-z_0-9]*)' ) ;
89
- pattern = pattern . replace ( ':objectId' ,
90
- '([A-Za-z0-9]+)' ) ;
91
- var re = new RegExp ( pattern ) ;
92
- var m = path . match ( re ) ;
93
- if ( ! m ) {
94
- continue ;
95
- }
96
- var params = { } ;
97
- if ( m [ 1 ] ) {
98
- params . className = m [ 1 ] ;
99
- }
100
- if ( m [ 2 ] ) {
101
- params . objectId = m [ 2 ] ;
102
- }
103
102
104
- return { params : params , handler : route . handler } ;
103
+ let layer = route . layer || new Layer ( route . path , null , route . handler ) ;
104
+ let match = layer . match ( path ) ;
105
+ if ( match ) {
106
+ let params = layer . params ;
107
+ Object . keys ( params ) . forEach ( ( key ) => {
108
+ params [ key ] = validateParameter ( key , params [ key ] ) ;
109
+ } ) ;
110
+ return { params : params , handler : route . handler } ;
111
+ }
105
112
}
106
113
} ;
107
114
@@ -129,24 +136,7 @@ export default class PromiseRouter {
129
136
130
137
expressApp ( ) {
131
138
var expressApp = express ( ) ;
132
- for ( var route of this . routes ) {
133
- switch ( route . method ) {
134
- case 'POST' :
135
- expressApp . post ( route . path , makeExpressHandler ( this . appId , route . handler ) ) ;
136
- break ;
137
- case 'GET' :
138
- expressApp . get ( route . path , makeExpressHandler ( this . appId , route . handler ) ) ;
139
- break ;
140
- case 'PUT' :
141
- expressApp . put ( route . path , makeExpressHandler ( this . appId , route . handler ) ) ;
142
- break ;
143
- case 'DELETE' :
144
- expressApp . delete ( route . path , makeExpressHandler ( this . appId , route . handler ) ) ;
145
- break ;
146
- default :
147
- throw 'unexpected code branch' ;
148
- }
149
- }
139
+ this . mountOnto ( expressApp ) ;
150
140
return expressApp ;
151
141
}
152
142
}
@@ -159,26 +149,15 @@ function makeExpressHandler(appId, promiseHandler) {
159
149
let config = AppCache . get ( appId ) ;
160
150
return function ( req , res , next ) {
161
151
try {
162
- let url = maskSensitiveUrl ( req ) ;
163
- let body = maskSensitiveBody ( req ) ;
164
- let stringifiedBody = JSON . stringify ( body , null , 2 ) ;
165
- log . verbose ( `REQUEST for [${ req . method } ] ${ url } : ${ stringifiedBody } ` , {
166
- method : req . method ,
167
- url : url ,
168
- headers : req . headers ,
169
- body : body
170
- } ) ;
152
+ logRequest ( req . originalUrl , req . method , req . body , req . headers ) ;
153
+
171
154
promiseHandler ( req ) . then ( ( result ) => {
172
155
if ( ! result . response && ! result . location && ! result . text ) {
173
156
log . error ( 'the handler did not include a "response" or a "location" field' ) ;
174
157
throw 'control should not get here' ;
175
158
}
176
159
177
- let stringifiedResponse = JSON . stringify ( result , null , 2 ) ;
178
- log . verbose (
179
- `RESPONSE from [${ req . method } ] ${ url } : ${ stringifiedResponse } ` ,
180
- { result : result }
181
- ) ;
160
+ logResponse ( req . originalUrl , req . method , result ) ;
182
161
183
162
var status = result . status || 200 ;
184
163
res . status ( status ) ;
@@ -214,34 +193,3 @@ function makeExpressHandler(appId, promiseHandler) {
214
193
}
215
194
}
216
195
}
217
-
218
- function maskSensitiveBody ( req ) {
219
- let maskBody = Object . assign ( { } , req . body ) ;
220
- let shouldMaskBody = ( req . method === 'POST' && req . originalUrl . endsWith ( '/users' )
221
- && ! req . originalUrl . includes ( 'classes' ) ) ||
222
- ( req . method === 'PUT' && / u s e r s \/ \w + $ / . test ( req . originalUrl )
223
- && ! req . originalUrl . includes ( 'classes' ) ) ||
224
- ( req . originalUrl . includes ( 'classes/_User' ) ) ;
225
- if ( shouldMaskBody ) {
226
- for ( let key of Object . keys ( maskBody ) ) {
227
- if ( key == 'password' ) {
228
- maskBody [ key ] = '********' ;
229
- break ;
230
- }
231
- }
232
- }
233
- return maskBody ;
234
- }
235
-
236
- function maskSensitiveUrl ( req ) {
237
- let maskUrl = req . originalUrl . toString ( ) ;
238
- let shouldMaskUrl = req . method === 'GET' && req . originalUrl . includes ( '/login' )
239
- && ! req . originalUrl . includes ( 'classes' ) ;
240
- if ( shouldMaskUrl ) {
241
- let password = url . parse ( req . originalUrl , true ) . query . password ;
242
- if ( password ) {
243
- maskUrl = maskUrl . replace ( 'password=' + password , 'password=********' )
244
- }
245
- }
246
- return maskUrl ;
247
- }
0 commit comments