@@ -14,21 +14,28 @@ import {
14
14
import * as domain from 'domain' ;
15
15
import * as http from 'http' ;
16
16
import * as os from 'os' ;
17
- import * as url from 'url' ;
18
17
19
18
import { NodeClient } from './client' ;
20
19
import { flush } from './sdk' ;
21
20
22
21
const DEFAULT_SHUTDOWN_TIMEOUT = 2000 ;
23
22
24
- interface ExpressRequest {
23
+ interface ExpressRequest extends http . IncomingMessage {
24
+ [ key : string ] : any ;
25
+ baseUrl ?: string ;
26
+ ip ?: string ;
27
+ originalUrl ?: string ;
25
28
route ?: {
26
29
path : string ;
30
+ stack : [
31
+ {
32
+ name : string ;
33
+ } ,
34
+ ] ;
35
+ } ;
36
+ user ?: {
37
+ [ key : string ] : any ;
27
38
} ;
28
- method : string ;
29
- originalUrl : string ;
30
- baseUrl : string ;
31
- query : string ;
32
39
}
33
40
34
41
/**
@@ -45,19 +52,14 @@ export function tracingHandler(): (
45
52
res : http . ServerResponse ,
46
53
next : ( error ?: any ) => void ,
47
54
) : void {
48
- // TODO: At this point `req.route.path` (which we use in `extractTransaction`) is not available
49
- // but `req.path` or `req.url` should do the job as well. We could unify this here.
50
- const reqMethod = ( req . method || '' ) . toUpperCase ( ) ;
51
- const reqUrl = req . url && stripUrlQueryAndFragment ( req . url ) ;
52
-
53
55
// If there is a trace header set, we extract the data from it (parentSpanId, traceId, and sampling decision)
54
56
let traceparentData ;
55
57
if ( req . headers && isString ( req . headers [ 'sentry-trace' ] ) ) {
56
58
traceparentData = extractTraceparentData ( req . headers [ 'sentry-trace' ] as string ) ;
57
59
}
58
60
59
61
const transaction = startTransaction ( {
60
- name : ` ${ reqMethod } ${ reqUrl } ` ,
62
+ name : extractRouteInfo ( req , { path : true , method : true } ) ,
61
63
op : 'http.server' ,
62
64
...traceparentData ,
63
65
} ) ;
@@ -75,7 +77,7 @@ export function tracingHandler(): (
75
77
res . once ( 'finish' , ( ) => {
76
78
// We schedule the immediate execution of the `finish` to let all the spans being closed first.
77
79
setImmediate ( ( ) => {
78
- addExpressReqToTransaction ( transaction , ( req as unknown ) as ExpressRequest ) ;
80
+ addExpressReqToTransaction ( transaction , req ) ;
79
81
transaction . setHttpStatus ( res . statusCode ) ;
80
82
transaction . finish ( ) ;
81
83
} ) ;
@@ -91,56 +93,56 @@ export function tracingHandler(): (
91
93
*/
92
94
function addExpressReqToTransaction ( transaction : Transaction | undefined , req : ExpressRequest ) : void {
93
95
if ( ! transaction ) return ;
94
- if ( req . route ) {
95
- transaction . name = `${ req . method } ${ req . baseUrl } ${ req . route . path } ` ;
96
- }
96
+ transaction . name = extractRouteInfo ( req , { path : true , method : true } ) ;
97
97
transaction . setData ( 'url' , req . originalUrl ) ;
98
98
transaction . setData ( 'baseUrl' , req . baseUrl ) ;
99
99
transaction . setData ( 'query' , req . query ) ;
100
100
}
101
101
102
+ /**
103
+ * Extracts complete generalized path from the request object.
104
+ * eg. /mountpoint/user/:id
105
+ */
106
+ function extractRouteInfo ( req : ExpressRequest , options : { path ?: boolean ; method ?: boolean } = { } ) : string {
107
+ const method = req . method ?. toUpperCase ( ) ;
108
+ let path ;
109
+ if ( req . baseUrl && req . route ) {
110
+ path = `${ req . baseUrl } ${ req . route . path } ` ;
111
+ } else if ( req . originalUrl || req . url ) {
112
+ path = stripUrlQueryAndFragment ( req . originalUrl || req . url || '' ) ;
113
+ } else {
114
+ path = req . route ?. path || '' ;
115
+ }
116
+
117
+ let info = '' ;
118
+ if ( options . method && method ) {
119
+ info += method ;
120
+ }
121
+ if ( options . method && options . path ) {
122
+ info += ` ` ;
123
+ }
124
+ if ( options . path && path ) {
125
+ info += path ;
126
+ }
127
+
128
+ return info ;
129
+ }
130
+
102
131
type TransactionTypes = 'path' | 'methodPath' | 'handler' ;
103
132
104
133
/** JSDoc */
105
- function extractTransaction ( req : { [ key : string ] : any } , type : boolean | TransactionTypes ) : string | undefined {
106
- try {
107
- // Express.js shape
108
- const request = req as {
109
- url : string ;
110
- originalUrl : string ;
111
- method : string ;
112
- route : {
113
- path : string ;
114
- stack : [
115
- {
116
- name : string ;
117
- } ,
118
- ] ;
119
- } ;
120
- } ;
121
-
122
- let routePath ;
123
- try {
124
- routePath = url . parse ( request . originalUrl || request . url ) . pathname ;
125
- } catch ( _oO ) {
126
- routePath = request . route . path ;
134
+ function extractTransaction ( req : ExpressRequest , type : boolean | TransactionTypes ) : string {
135
+ switch ( type ) {
136
+ case 'path' : {
137
+ return extractRouteInfo ( req , { path : true } ) ;
127
138
}
128
-
129
- switch ( type ) {
130
- case 'path' : {
131
- return routePath ;
132
- }
133
- case 'handler' : {
134
- return request . route . stack [ 0 ] . name ;
135
- }
136
- case 'methodPath' :
137
- default : {
138
- const method = request . method . toUpperCase ( ) ;
139
- return `${ method } ${ routePath } ` ;
140
- }
139
+ case 'handler' : {
140
+ return req . route ?. stack [ 0 ] . name || '<anonymous>' ;
141
+ }
142
+ case 'methodPath' :
143
+ default : {
144
+ return extractRouteInfo ( req , { path : true , method : true } ) ;
141
145
}
142
- } catch ( _oO ) {
143
- return undefined ;
144
146
}
145
147
}
146
148
@@ -186,20 +188,7 @@ export interface ParseRequestOptions {
186
188
* @param options object containing flags to enable functionality
187
189
* @hidden
188
190
*/
189
- export function parseRequest (
190
- event : Event ,
191
- req : {
192
- [ key : string ] : any ;
193
- user ?: {
194
- [ key : string ] : any ;
195
- } ;
196
- ip ?: string ;
197
- connection ?: {
198
- remoteAddress ?: string ;
199
- } ;
200
- } ,
201
- options ?: ParseRequestOptions ,
202
- ) : Event {
191
+ export function parseRequest ( event : Event , req : ExpressRequest , options ?: ParseRequestOptions ) : Event {
203
192
// eslint-disable-next-line no-param-reassign
204
193
options = {
205
194
ip : false ,
@@ -261,10 +250,7 @@ export function parseRequest(
261
250
}
262
251
263
252
if ( options . transaction && ! event . transaction ) {
264
- const transaction = extractTransaction ( req , options . transaction ) ;
265
- if ( transaction ) {
266
- event . transaction = transaction ;
267
- }
253
+ event . transaction = extractTransaction ( req , options . transaction ) ;
268
254
}
269
255
270
256
return event ;
0 commit comments