@@ -14,21 +14,28 @@ import {
1414import * as domain from 'domain' ;
1515import * as http from 'http' ;
1616import * as os from 'os' ;
17- import * as url from 'url' ;
1817
1918import { NodeClient } from './client' ;
2019import { flush } from './sdk' ;
2120
2221const DEFAULT_SHUTDOWN_TIMEOUT = 2000 ;
2322
24- interface ExpressRequest {
23+ interface ExpressRequest extends http . IncomingMessage {
24+ [ key : string ] : any ;
25+ baseUrl ?: string ;
26+ ip ?: string ;
27+ originalUrl ?: string ;
2528 route ?: {
2629 path : string ;
30+ stack : [
31+ {
32+ name : string ;
33+ } ,
34+ ] ;
35+ } ;
36+ user ?: {
37+ [ key : string ] : any ;
2738 } ;
28- method : string ;
29- originalUrl : string ;
30- baseUrl : string ;
31- query : string ;
3239}
3340
3441/**
@@ -45,19 +52,14 @@ export function tracingHandler(): (
4552 res : http . ServerResponse ,
4653 next : ( error ?: any ) => void ,
4754 ) : 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-
5355 // If there is a trace header set, we extract the data from it (parentSpanId, traceId, and sampling decision)
5456 let traceparentData ;
5557 if ( req . headers && isString ( req . headers [ 'sentry-trace' ] ) ) {
5658 traceparentData = extractTraceparentData ( req . headers [ 'sentry-trace' ] as string ) ;
5759 }
5860
5961 const transaction = startTransaction ( {
60- name : ` ${ reqMethod } ${ reqUrl } ` ,
62+ name : extractRouteInfo ( req , { path : true , method : true } ) ,
6163 op : 'http.server' ,
6264 ...traceparentData ,
6365 } ) ;
@@ -75,7 +77,7 @@ export function tracingHandler(): (
7577 res . once ( 'finish' , ( ) => {
7678 // We schedule the immediate execution of the `finish` to let all the spans being closed first.
7779 setImmediate ( ( ) => {
78- addExpressReqToTransaction ( transaction , ( req as unknown ) as ExpressRequest ) ;
80+ addExpressReqToTransaction ( transaction , req ) ;
7981 transaction . setHttpStatus ( res . statusCode ) ;
8082 transaction . finish ( ) ;
8183 } ) ;
@@ -91,56 +93,56 @@ export function tracingHandler(): (
9193 */
9294function addExpressReqToTransaction ( transaction : Transaction | undefined , req : ExpressRequest ) : void {
9395 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 } ) ;
9797 transaction . setData ( 'url' , req . originalUrl ) ;
9898 transaction . setData ( 'baseUrl' , req . baseUrl ) ;
9999 transaction . setData ( 'query' , req . query ) ;
100100}
101101
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+
102131type TransactionTypes = 'path' | 'methodPath' | 'handler' ;
103132
104133/** 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 } ) ;
127138 }
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 } ) ;
141145 }
142- } catch ( _oO ) {
143- return undefined ;
144146 }
145147}
146148
@@ -186,20 +188,7 @@ export interface ParseRequestOptions {
186188 * @param options object containing flags to enable functionality
187189 * @hidden
188190 */
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 {
203192 // eslint-disable-next-line no-param-reassign
204193 options = {
205194 ip : false ,
@@ -261,10 +250,7 @@ export function parseRequest(
261250 }
262251
263252 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 ) ;
268254 }
269255
270256 return event ;
0 commit comments