1515 */
1616
1717import * as httpModule from 'http' ;
18- import { Agent , ClientRequest , ClientRequestArgs , get , request } from 'http' ;
18+ import { Agent , ClientRequest , ClientRequestArgs , request } from 'http' ;
1919import * as httpsModule from 'https' ;
20- import * as is from 'is' ;
2120import * as semver from 'semver' ;
2221import * as shimmer from 'shimmer' ;
23- import * as url from 'url' ;
22+ import { URL , parse as urlParse } from 'url' ;
2423
2524import { Plugin , Tracer } from '../plugin-types' ;
2625
@@ -31,16 +30,15 @@ type RequestFunction = typeof request;
3130const ERR_HTTP_HEADERS_SENT = 'ERR_HTTP_HEADERS_SENT' ;
3231const ERR_HTTP_HEADERS_SENT_MSG = "Can't set headers after they are sent." ;
3332
34- // tslint:disable:no-any
35- const isString = is . string as ( value : any ) => value is string ;
36- // url.URL is used for type checking, but doesn't exist in Node <7.
33+ // URL is used for type checking, but doesn't exist in Node <7.
3734// This function works around that.
35+ // tslint:disable:no-any
3836const isURL = semver . satisfies ( process . version , '>=7' )
39- ? ( value : any ) : value is url . URL => value instanceof url . URL
40- : ( value : any ) : value is url . URL => false ;
37+ ? ( value : any ) : value is URL => value instanceof URL
38+ : ( value : any ) : value is URL => false ;
4139// tslint:enable:no-any
4240
43- function getSpanName ( options : ClientRequestArgs | url . URL ) {
41+ function getSpanName ( options : ClientRequestArgs | URL ) {
4442 // c.f. _http_client.js ClientRequest constructor
4543 return options . hostname || options . host || 'localhost' ;
4644}
@@ -51,7 +49,7 @@ function getSpanName(options: ClientRequestArgs | url.URL) {
5149 * all-caps for simplicity purposes.
5250 * @param options Options for http.request.
5351 */
54- function hasExpectHeader ( options : ClientRequestArgs | url . URL ) : boolean {
52+ function hasExpectHeader ( options : ClientRequestArgs | URL ) : boolean {
5553 return ! ! (
5654 ( options as ClientRequestArgs ) . headers &&
5755 ( ( options as ClientRequestArgs ) . headers ! . Expect ||
@@ -61,7 +59,7 @@ function hasExpectHeader(options: ClientRequestArgs | url.URL): boolean {
6159}
6260
6361function extractUrl (
64- options : ClientRequestArgs | url . URL ,
62+ options : ClientRequestArgs | URL ,
6563 fallbackProtocol : string
6664) {
6765 let path ;
@@ -88,7 +86,7 @@ function extractUrl(
8886}
8987
9088// tslint:disable-next-line:no-any
91- function isTraceAgentRequest ( options : any , api : Tracer ) {
89+ function isTraceAgentRequest ( options : httpModule . RequestOptions , api : Tracer ) {
9290 return (
9391 options &&
9492 options . headers &&
@@ -103,38 +101,52 @@ function makeRequestTrace(
103101) : RequestFunction {
104102 // On Node 8+ we use the following function to patch both request and get.
105103 // Here `request` may also happen to be `get`.
106- return function requestTrace ( options , callback ) : ClientRequest {
107- if ( ! options ) {
108- return request ( options , callback ) ;
104+ return function requestTrace (
105+ this : never ,
106+ url : httpModule . RequestOptions | string | URL ,
107+ options ?:
108+ | httpModule . RequestOptions
109+ | ( ( res : httpModule . IncomingMessage ) => void ) ,
110+ callback ?: ( res : httpModule . IncomingMessage ) => void
111+ ) : ClientRequest {
112+ // These are error conditions; defer to http.request and don't trace.
113+ if ( ! url || ( typeof url === 'object' && typeof options === 'object' ) ) {
114+ return request . apply ( this , arguments ) ;
115+ }
116+
117+ let urlString ;
118+ if ( typeof url === 'string' ) {
119+ // save the value of uri so we don't have to reconstruct it later
120+ urlString = url ;
121+ url = urlParse ( url ) ;
122+ }
123+ if ( typeof options === 'function' ) {
124+ callback = options ;
125+ options = url ;
126+ } else {
127+ options = Object . assign ( { } , url , options ) ;
109128 }
110129
111130 // Don't trace ourselves lest we get into infinite loops
112131 // Note: this would not be a problem if we guarantee buffering
113132 // of trace api calls. If there is no buffering then each trace is
114133 // an http call which will get a trace which will be an http call
115134 if ( isTraceAgentRequest ( options , api ) ) {
116- return request ( options , callback ) ;
117- }
118-
119- let uri ;
120- if ( isString ( options ) ) {
121- // save the value of uri so we don't have to reconstruct it later
122- uri = options ;
123- options = url . parse ( options ) ;
135+ return request . apply ( this , arguments ) ;
124136 }
125137
126138 const span = api . createChildSpan ( { name : getSpanName ( options ) } ) ;
127139 if ( ! api . isRealSpan ( span ) ) {
128- return request ( options , callback ) ;
140+ return request . apply ( this , arguments ) ;
129141 }
130142
131- if ( ! uri ) {
132- uri = extractUrl ( options , protocol ) ;
143+ if ( ! urlString ) {
144+ urlString = extractUrl ( options , protocol ) ;
133145 }
134146
135147 const method = ( options as ClientRequestArgs ) . method || 'GET' ;
136148 span . addLabel ( api . labels . HTTP_METHOD_LABEL_KEY , method ) ;
137- span . addLabel ( api . labels . HTTP_URL_LABEL_KEY , uri ) ;
149+ span . addLabel ( api . labels . HTTP_URL_LABEL_KEY , urlString ) ;
138150
139151 // If outgoing request headers contain the "Expect" header, the returned
140152 // ClientRequest will throw an error if any new headers are added. For this
@@ -239,8 +251,8 @@ function patchHttp(http: HttpModule, api: Tracer) {
239251 // v9), so we simply follow the latter.
240252 // Ref:
241253 // https://nodejs.org/dist/latest/docs/api/http.html#http_http_get_options_callback
242- return function getTrace ( options , callback ) {
243- const req = http . request ( options , callback ) ;
254+ return function getTrace ( this : never ) {
255+ const req = http . request . apply ( this , arguments ) ;
244256 req . end ( ) ;
245257 return req ;
246258 } ;
@@ -255,8 +267,8 @@ function patchHttps(https: HttpsModule, api: Tracer) {
255267 return makeRequestTrace ( 'https:' , request , api ) ;
256268 } ) ;
257269 shimmer . wrap ( https , 'get' , function getWrap ( ) : typeof httpsModule . get {
258- return function getTrace ( options , callback ) {
259- const req = https . request ( options , callback ) ;
270+ return function getTrace ( this : never ) {
271+ const req = https . request . apply ( this , arguments ) ;
260272 req . end ( ) ;
261273 return req ;
262274 } ;
0 commit comments