@@ -28,6 +28,9 @@ type HttpModule = typeof httpModule;
2828type HttpsModule = typeof httpsModule ;
2929type RequestFunction = typeof request ;
3030
31+ const ERR_HTTP_HEADERS_SENT = 'ERR_HTTP_HEADERS_SENT' ;
32+ const ERR_HTTP_HEADERS_SENT_MSG = 'Can\'t set headers after they are sent.' ;
33+
3134// tslint:disable:no-any
3235const isString = is . string as ( value : any ) => value is string ;
3336// url.URL is used for type checking, but doesn't exist in Node <7.
@@ -44,12 +47,16 @@ function getSpanName(options: ClientRequestArgs|url.URL) {
4447
4548/**
4649 * Returns whether the Expect header is on the given options object.
50+ * Assumes only that the header key is either capitalized, lowercase, or
51+ * all-caps for simplicity purposes.
4752 * @param options Options for http.request.
4853 */
4954function hasExpectHeader ( options : ClientRequestArgs | url . URL ) : boolean {
5055 return ! ! (
5156 ( options as ClientRequestArgs ) . headers &&
52- ( options as ClientRequestArgs ) . headers ! . Expect ) ;
57+ ( ( options as ClientRequestArgs ) . headers ! . Expect ||
58+ ( options as ClientRequestArgs ) . headers ! . expect ||
59+ ( options as ClientRequestArgs ) . headers ! . EXPECT ) ) ;
5360}
5461
5562function extractUrl (
@@ -126,6 +133,8 @@ function makeRequestTrace(
126133 // inject the trace context header instead of using ClientRequest#setHeader.
127134 // (We don't do this generally because cloning the options object is an
128135 // expensive operation.)
136+ // See https://github.com/googleapis/cloud-trace-nodejs/pull/766 for a full
137+ // explanation.
129138 let traceHeaderPreinjected = false ;
130139 if ( hasExpectHeader ( options ) ) {
131140 traceHeaderPreinjected = true ;
@@ -179,8 +188,19 @@ function makeRequestTrace(
179188 // Inject the trace context header, but only if it wasn't already injected
180189 // earlier.
181190 if ( ! traceHeaderPreinjected ) {
182- req . setHeader (
183- api . constants . TRACE_CONTEXT_HEADER_NAME , span . getTraceContext ( ) ) ;
191+ try {
192+ req . setHeader (
193+ api . constants . TRACE_CONTEXT_HEADER_NAME , span . getTraceContext ( ) ) ;
194+ } catch ( e ) {
195+ if ( e . code === ERR_HTTP_HEADERS_SENT ||
196+ e . message === ERR_HTTP_HEADERS_SENT_MSG ) {
197+ // Swallow the error.
198+ // This would happen in the pathological case where the Expect header
199+ // exists but is not detected by hasExpectHeader.
200+ } else {
201+ throw e ;
202+ }
203+ }
184204 }
185205 return req ;
186206 } ;
0 commit comments