@@ -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 { 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} ) ;
@@ -530,181 +373,6 @@ describe('tracingHandler', () => {
530373 } ) ;
531374} ) ;
532375
533- describe ( 'extractRequestData()' , ( ) => {
534- describe ( 'default behaviour' , ( ) => {
535- test ( 'node' , ( ) => {
536- expect (
537- extractRequestData ( {
538- headers : { host : 'example.com' } ,
539- method : 'GET' ,
540- secure : true ,
541- originalUrl : '/' ,
542- } ) ,
543- ) . toEqual ( {
544- cookies : { } ,
545- headers : {
546- host : 'example.com' ,
547- } ,
548- method : 'GET' ,
549- query_string : null ,
550- url : 'https://example.com/' ,
551- } ) ;
552- } ) ;
553-
554- test ( 'degrades gracefully without request data' , ( ) => {
555- expect ( extractRequestData ( { } ) ) . toEqual ( {
556- cookies : { } ,
557- headers : { } ,
558- method : undefined ,
559- query_string : null ,
560- url : 'http://<no host>' ,
561- } ) ;
562- } ) ;
563- } ) ;
564-
565- describe ( 'cookies' , ( ) => {
566- it ( 'uses `req.cookies` if available' , ( ) => {
567- expect (
568- extractRequestData (
569- {
570- cookies : { foo : 'bar' } ,
571- } ,
572- [ 'cookies' ] ,
573- ) ,
574- ) . toEqual ( {
575- cookies : { foo : 'bar' } ,
576- } ) ;
577- } ) ;
578-
579- it ( 'parses the cookie header' , ( ) => {
580- expect (
581- extractRequestData (
582- {
583- headers : {
584- cookie : 'foo=bar;' ,
585- } ,
586- } ,
587- [ 'cookies' ] ,
588- ) ,
589- ) . toEqual ( {
590- cookies : { foo : 'bar' } ,
591- } ) ;
592- } ) ;
593-
594- it ( 'falls back if no cookies are defined' , ( ) => {
595- expect ( extractRequestData ( { } , [ 'cookies' ] ) ) . toEqual ( {
596- cookies : { } ,
597- } ) ;
598- } ) ;
599- } ) ;
600-
601- describe ( 'data' , ( ) => {
602- it ( 'includes data from `req.body` if available' , ( ) => {
603- expect (
604- extractRequestData (
605- {
606- method : 'POST' ,
607- headers : { 'Content-Type' : 'application/x-www-form-urlencoded' } ,
608- body : 'foo=bar' ,
609- } ,
610- [ 'data' ] ,
611- ) ,
612- ) . toEqual ( {
613- data : 'foo=bar' ,
614- } ) ;
615- } ) ;
616-
617- it ( 'encodes JSON body contents back to a string' , ( ) => {
618- expect (
619- extractRequestData (
620- {
621- method : 'POST' ,
622- headers : { 'Content-Type' : 'application/json' } ,
623- body : { foo : 'bar' } ,
624- } ,
625- [ 'data' ] ,
626- ) ,
627- ) . toEqual ( {
628- data : '{"foo":"bar"}' ,
629- } ) ;
630- } ) ;
631- } ) ;
632-
633- describe ( 'query_string' , ( ) => {
634- it ( 'parses the query parms from the url' , ( ) => {
635- expect (
636- extractRequestData (
637- {
638- headers : { host : 'example.com' } ,
639- secure : true ,
640- originalUrl : '/?foo=bar' ,
641- } ,
642- [ 'query_string' ] ,
643- ) ,
644- ) . toEqual ( {
645- query_string : 'foo=bar' ,
646- } ) ;
647- } ) ;
648-
649- it ( 'gracefully degrades if url cannot be determined' , ( ) => {
650- expect ( extractRequestData ( { } , [ 'query_string' ] ) ) . toEqual ( {
651- query_string : null ,
652- } ) ;
653- } ) ;
654- } ) ;
655-
656- describe ( 'url' , ( ) => {
657- test ( 'express/koa' , ( ) => {
658- expect (
659- extractRequestData (
660- {
661- host : 'example.com' ,
662- protocol : 'https' ,
663- url : '/' ,
664- } ,
665- [ 'url' ] ,
666- ) ,
667- ) . toEqual ( {
668- url : 'https://example.com/' ,
669- } ) ;
670- } ) ;
671-
672- test ( 'node' , ( ) => {
673- expect (
674- extractRequestData (
675- {
676- headers : { host : 'example.com' } ,
677- secure : true ,
678- originalUrl : '/' ,
679- } ,
680- [ 'url' ] ,
681- ) ,
682- ) . toEqual ( {
683- url : 'https://example.com/' ,
684- } ) ;
685- } ) ;
686- } ) ;
687-
688- describe ( 'custom key' , ( ) => {
689- it ( 'includes the custom key if present' , ( ) => {
690- expect (
691- extractRequestData (
692- {
693- httpVersion : '1.1' ,
694- } ,
695- [ 'httpVersion' ] ,
696- ) ,
697- ) . toEqual ( {
698- httpVersion : '1.1' ,
699- } ) ;
700- } ) ;
701-
702- it ( 'gracefully degrades if the custom key is missing' , ( ) => {
703- expect ( extractRequestData ( { } , [ 'httpVersion' ] ) ) . toEqual ( { } ) ;
704- } ) ;
705- } ) ;
706- } ) ;
707-
708376describe ( 'errorHandler()' , ( ) => {
709377 const headers = { ears : 'furry' , nose : 'wet' , tongue : 'spotted' , cookie : 'favorite=zukes' } ;
710378 const method = 'wagging' ;
0 commit comments