@@ -2,174 +2,15 @@ import * as sentryCore from '@sentry/core';
22import * as sentryHub from '@sentry/hub' ;
33import { Hub } from '@sentry/hub' ;
44import { Transaction } from '@sentry/tracing' ;
5- import { Baggage } from '@sentry/types' ;
5+ import { Baggage , Event } from '@sentry/types' ;
66import { isBaggageEmpty , isBaggageMutable , SentryError } from '@sentry/utils' ;
77import * as http from 'http' ;
8- import * as net from 'net' ;
98
10- import { Event , Request , User } from '../src' ;
119import { NodeClient } from '../src/client' ;
12- import {
13- errorHandler ,
14- ExpressRequest ,
15- extractRequestData ,
16- parseRequest ,
17- requestHandler ,
18- tracingHandler ,
19- } from '../src/handlers' ;
10+ import { errorHandler , requestHandler , tracingHandler } from '../src/handlers' ;
2011import * as SDK from '../src/sdk' ;
2112import { getDefaultNodeClientOptions } from './helper/node-client-options' ;
2213
23- describe ( 'parseRequest' , ( ) => {
24- let mockReq : { [ key : string ] : any } ;
25-
26- beforeEach ( ( ) => {
27- mockReq = {
28- baseUrl : '/routerMountPath' ,
29- body : 'foo' ,
30- cookies : { test : 'test' } ,
31- headers : {
32- host : 'mattrobenolt.com' ,
33- } ,
34- method : 'POST' ,
35- originalUrl : '/routerMountPath/subpath/specificValue?querystringKey=querystringValue' ,
36- path : '/subpath/specificValue' ,
37- query : {
38- querystringKey : 'querystringValue' ,
39- } ,
40- route : {
41- path : '/subpath/:parameterName' ,
42- stack : [
43- {
44- name : 'parameterNameRouteHandler' ,
45- } ,
46- ] ,
47- } ,
48- url : '/subpath/specificValue?querystringKey=querystringValue' ,
49- user : {
50- custom_property : 'foo' ,
51- 52- id : 123 ,
53- username : 'tobias' ,
54- } ,
55- } ;
56- } ) ;
57-
58- describe ( 'parseRequest.user properties' , ( ) => {
59- const DEFAULT_USER_KEYS = [ 'id' , 'username' , 'email' ] ;
60- const CUSTOM_USER_KEYS = [ 'custom_property' ] ;
61-
62- test ( 'parseRequest.user only contains the default properties from the user' , ( ) => {
63- const parsedRequest : Event = parseRequest ( { } , mockReq as ExpressRequest ) ;
64- expect ( Object . keys ( parsedRequest . user as User ) ) . toEqual ( DEFAULT_USER_KEYS ) ;
65- } ) ;
66-
67- test ( 'parseRequest.user only contains the custom properties specified in the options.user array' , ( ) => {
68- const parsedRequest : Event = parseRequest ( { } , mockReq as ExpressRequest , {
69- user : CUSTOM_USER_KEYS ,
70- } ) ;
71- expect ( Object . keys ( parsedRequest . user as User ) ) . toEqual ( CUSTOM_USER_KEYS ) ;
72- } ) ;
73-
74- test ( 'parseRequest.user doesnt blow up when someone passes non-object value' , ( ) => {
75- const parsedRequest : Event = parseRequest (
76- { } ,
77- {
78- ...mockReq ,
79- // @ts -ignore user is not assignable to object
80- user : 'wat' ,
81- } ,
82- ) ;
83- expect ( Object . keys ( parsedRequest . user as User ) ) . toEqual ( [ ] ) ;
84- } ) ;
85- } ) ;
86-
87- describe ( 'parseRequest.ip property' , ( ) => {
88- test ( 'can be extracted from req.ip' , ( ) => {
89- const parsedRequest : Event = parseRequest (
90- { } ,
91- {
92- ...mockReq ,
93- ip : '123' ,
94- } as ExpressRequest ,
95- {
96- ip : true ,
97- } ,
98- ) ;
99- expect ( parsedRequest . user ! . ip_address ) . toEqual ( '123' ) ;
100- } ) ;
101-
102- test ( 'can extract from req.connection.remoteAddress' , ( ) => {
103- const parsedRequest : Event = parseRequest (
104- { } ,
105- {
106- ...mockReq ,
107- connection : {
108- remoteAddress : '321' ,
109- } as net . Socket ,
110- } as ExpressRequest ,
111- {
112- ip : true ,
113- } ,
114- ) ;
115- expect ( parsedRequest . user ! . ip_address ) . toEqual ( '321' ) ;
116- } ) ;
117- } ) ;
118-
119- describe ( 'parseRequest.request properties' , ( ) => {
120- test ( 'parseRequest.request only contains the default set of properties from the request' , ( ) => {
121- const DEFAULT_REQUEST_PROPERTIES = [ 'cookies' , 'data' , 'headers' , 'method' , 'query_string' , 'url' ] ;
122- const parsedRequest : Event = parseRequest ( { } , mockReq as ExpressRequest ) ;
123- expect ( Object . keys ( parsedRequest . request as Request ) ) . toEqual ( DEFAULT_REQUEST_PROPERTIES ) ;
124- } ) ;
125-
126- test ( 'parseRequest.request only contains the specified properties in the options.request array' , ( ) => {
127- const INCLUDED_PROPERTIES = [ 'data' , 'headers' , 'query_string' , 'url' ] ;
128- const parsedRequest : Event = parseRequest ( { } , mockReq as ExpressRequest , {
129- request : INCLUDED_PROPERTIES ,
130- } ) ;
131- expect ( Object . keys ( parsedRequest . request as Request ) ) . toEqual ( INCLUDED_PROPERTIES ) ;
132- } ) ;
133-
134- test ( 'parseRequest.request skips `body` property for GET and HEAD requests' , ( ) => {
135- expect ( parseRequest ( { } , mockReq as ExpressRequest , { } ) . request ) . toHaveProperty ( 'data' ) ;
136- expect ( parseRequest ( { } , { ...mockReq , method : 'GET' } as ExpressRequest , { } ) . request ) . not . toHaveProperty ( 'data' ) ;
137- expect ( parseRequest ( { } , { ...mockReq , method : 'HEAD' } as ExpressRequest , { } ) . request ) . not . toHaveProperty ( 'data' ) ;
138- } ) ;
139- } ) ;
140-
141- describe ( 'parseRequest.transaction property' , ( ) => {
142- test ( 'extracts method and full route path by default`' , ( ) => {
143- const parsedRequest : Event = parseRequest ( { } , mockReq as ExpressRequest ) ;
144- expect ( parsedRequest . transaction ) . toEqual ( 'POST /routerMountPath/subpath/:parameterName' ) ;
145- } ) ;
146-
147- test ( 'extracts method and full path by default when mountpoint is `/`' , ( ) => {
148- mockReq . originalUrl = mockReq . originalUrl . replace ( '/routerMountpath' , '' ) ;
149- mockReq . baseUrl = '' ;
150- const parsedRequest : Event = parseRequest ( { } , mockReq as ExpressRequest ) ;
151- // "sub"path is the full path here, because there's no router mount path
152- expect ( parsedRequest . transaction ) . toEqual ( 'POST /subpath/:parameterName' ) ;
153- } ) ;
154-
155- test ( 'fallback to method and `originalUrl` if route is missing' , ( ) => {
156- delete mockReq . route ;
157- const parsedRequest : Event = parseRequest ( { } , mockReq as ExpressRequest ) ;
158- expect ( parsedRequest . transaction ) . toEqual ( 'POST /routerMountPath/subpath/specificValue' ) ;
159- } ) ;
160-
161- test ( 'can extract path only instead if configured' , ( ) => {
162- const parsedRequest : Event = parseRequest ( { } , mockReq as ExpressRequest , { transaction : 'path' } ) ;
163- expect ( parsedRequest . transaction ) . toEqual ( '/routerMountPath/subpath/:parameterName' ) ;
164- } ) ;
165-
166- test ( 'can extract handler name instead if configured' , ( ) => {
167- const parsedRequest : Event = parseRequest ( { } , mockReq as ExpressRequest , { transaction : 'handler' } ) ;
168- expect ( parsedRequest . transaction ) . toEqual ( 'parameterNameRouteHandler' ) ;
169- } ) ;
170- } ) ;
171- } ) ;
172-
17314describe ( 'requestHandler' , ( ) => {
17415 const headers = { ears : 'furry' , nose : 'wet' , tongue : 'spotted' , cookie : 'favorite=zukes' } ;
17516 const method = 'wagging' ;
@@ -270,7 +111,7 @@ describe('requestHandler', () => {
270111 } ) ;
271112 } ) ;
272113
273- it ( 'patches `res.end` when `flushTimeout` is specified' , ( ) => {
114+ it ( 'patches `res.end` when `flushTimeout` is specified' , done => {
274115 const flush = jest . spyOn ( SDK , 'flush' ) . mockResolvedValue ( true ) ;
275116
276117 const sentryRequestMiddleware = requestHandler ( { flushTimeout : 1337 } ) ;
@@ -280,10 +121,11 @@ describe('requestHandler', () => {
280121 setImmediate ( ( ) => {
281122 expect ( flush ) . toHaveBeenCalledWith ( 1337 ) ;
282123 expect ( res . finished ) . toBe ( true ) ;
124+ done ( ) ;
283125 } ) ;
284126 } ) ;
285127
286- it ( 'prevents errors thrown during `flush` from breaking the response' , async ( ) => {
128+ it ( 'prevents errors thrown during `flush` from breaking the response' , done => {
287129 jest . spyOn ( SDK , 'flush' ) . mockRejectedValue ( new SentryError ( 'HTTP Error (429)' ) ) ;
288130
289131 const sentryRequestMiddleware = requestHandler ( { flushTimeout : 1337 } ) ;
@@ -292,6 +134,7 @@ describe('requestHandler', () => {
292134
293135 setImmediate ( ( ) => {
294136 expect ( res . finished ) . toBe ( true ) ;
137+ done ( ) ;
295138 } ) ;
296139 } ) ;
297140} ) ;
@@ -537,181 +380,6 @@ describe('tracingHandler', () => {
537380 } ) ;
538381} ) ;
539382
540- describe ( 'extractRequestData()' , ( ) => {
541- describe ( 'default behaviour' , ( ) => {
542- test ( 'node' , ( ) => {
543- expect (
544- extractRequestData ( {
545- headers : { host : 'example.com' } ,
546- method : 'GET' ,
547- secure : true ,
548- originalUrl : '/' ,
549- } ) ,
550- ) . toEqual ( {
551- cookies : { } ,
552- headers : {
553- host : 'example.com' ,
554- } ,
555- method : 'GET' ,
556- query_string : null ,
557- url : 'https://example.com/' ,
558- } ) ;
559- } ) ;
560-
561- test ( 'degrades gracefully without request data' , ( ) => {
562- expect ( extractRequestData ( { } ) ) . toEqual ( {
563- cookies : { } ,
564- headers : { } ,
565- method : undefined ,
566- query_string : null ,
567- url : 'http://<no host>' ,
568- } ) ;
569- } ) ;
570- } ) ;
571-
572- describe ( 'cookies' , ( ) => {
573- it ( 'uses `req.cookies` if available' , ( ) => {
574- expect (
575- extractRequestData (
576- {
577- cookies : { foo : 'bar' } ,
578- } ,
579- [ 'cookies' ] ,
580- ) ,
581- ) . toEqual ( {
582- cookies : { foo : 'bar' } ,
583- } ) ;
584- } ) ;
585-
586- it ( 'parses the cookie header' , ( ) => {
587- expect (
588- extractRequestData (
589- {
590- headers : {
591- cookie : 'foo=bar;' ,
592- } ,
593- } ,
594- [ 'cookies' ] ,
595- ) ,
596- ) . toEqual ( {
597- cookies : { foo : 'bar' } ,
598- } ) ;
599- } ) ;
600-
601- it ( 'falls back if no cookies are defined' , ( ) => {
602- expect ( extractRequestData ( { } , [ 'cookies' ] ) ) . toEqual ( {
603- cookies : { } ,
604- } ) ;
605- } ) ;
606- } ) ;
607-
608- describe ( 'data' , ( ) => {
609- it ( 'includes data from `req.body` if available' , ( ) => {
610- expect (
611- extractRequestData (
612- {
613- method : 'POST' ,
614- headers : { 'Content-Type' : 'application/x-www-form-urlencoded' } ,
615- body : 'foo=bar' ,
616- } ,
617- [ 'data' ] ,
618- ) ,
619- ) . toEqual ( {
620- data : 'foo=bar' ,
621- } ) ;
622- } ) ;
623-
624- it ( 'encodes JSON body contents back to a string' , ( ) => {
625- expect (
626- extractRequestData (
627- {
628- method : 'POST' ,
629- headers : { 'Content-Type' : 'application/json' } ,
630- body : { foo : 'bar' } ,
631- } ,
632- [ 'data' ] ,
633- ) ,
634- ) . toEqual ( {
635- data : '{"foo":"bar"}' ,
636- } ) ;
637- } ) ;
638- } ) ;
639-
640- describe ( 'query_string' , ( ) => {
641- it ( 'parses the query parms from the url' , ( ) => {
642- expect (
643- extractRequestData (
644- {
645- headers : { host : 'example.com' } ,
646- secure : true ,
647- originalUrl : '/?foo=bar' ,
648- } ,
649- [ 'query_string' ] ,
650- ) ,
651- ) . toEqual ( {
652- query_string : 'foo=bar' ,
653- } ) ;
654- } ) ;
655-
656- it ( 'gracefully degrades if url cannot be determined' , ( ) => {
657- expect ( extractRequestData ( { } , [ 'query_string' ] ) ) . toEqual ( {
658- query_string : null ,
659- } ) ;
660- } ) ;
661- } ) ;
662-
663- describe ( 'url' , ( ) => {
664- test ( 'express/koa' , ( ) => {
665- expect (
666- extractRequestData (
667- {
668- host : 'example.com' ,
669- protocol : 'https' ,
670- url : '/' ,
671- } ,
672- [ 'url' ] ,
673- ) ,
674- ) . toEqual ( {
675- url : 'https://example.com/' ,
676- } ) ;
677- } ) ;
678-
679- test ( 'node' , ( ) => {
680- expect (
681- extractRequestData (
682- {
683- headers : { host : 'example.com' } ,
684- secure : true ,
685- originalUrl : '/' ,
686- } ,
687- [ 'url' ] ,
688- ) ,
689- ) . toEqual ( {
690- url : 'https://example.com/' ,
691- } ) ;
692- } ) ;
693- } ) ;
694-
695- describe ( 'custom key' , ( ) => {
696- it ( 'includes the custom key if present' , ( ) => {
697- expect (
698- extractRequestData (
699- {
700- httpVersion : '1.1' ,
701- } ,
702- [ 'httpVersion' ] ,
703- ) ,
704- ) . toEqual ( {
705- httpVersion : '1.1' ,
706- } ) ;
707- } ) ;
708-
709- it ( 'gracefully degrades if the custom key is missing' , ( ) => {
710- expect ( extractRequestData ( { } , [ 'httpVersion' ] ) ) . toEqual ( { } ) ;
711- } ) ;
712- } ) ;
713- } ) ;
714-
715383describe ( 'errorHandler()' , ( ) => {
716384 const headers = { ears : 'furry' , nose : 'wet' , tongue : 'spotted' , cookie : 'favorite=zukes' } ;
717385 const method = 'wagging' ;
0 commit comments