Skip to content

Commit 5b4ca1c

Browse files
t2t2dyladan
andauthored
fix(instrumentation-fetch): fetch(string, Request) silently drops request body (#2411)
* fix(instrumentation-fetch): pass request object as the only parameter * Pass arguments as-is when no span is created Co-authored-by: Daniel Dyla <[email protected]> * fix: typescript not liking arguments Co-authored-by: Daniel Dyla <[email protected]>
1 parent 90ea0fe commit 5b4ca1c

File tree

2 files changed

+32
-15
lines changed

2 files changed

+32
-15
lines changed

packages/opentelemetry-instrumentation-fetch/src/fetch.ts

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -284,23 +284,18 @@ export class FetchInstrumentation extends InstrumentationBase<
284284
/**
285285
* Patches the constructor of fetch
286286
*/
287-
private _patchConstructor(): (
288-
original: (input: RequestInfo, init?: RequestInit) => Promise<Response>
289-
) => (input: RequestInfo, init?: RequestInit) => Promise<Response> {
290-
return (
291-
original: (input: RequestInfo, init?: RequestInit) => Promise<Response>
292-
): ((input: RequestInfo, init?: RequestInit) => Promise<Response>) => {
287+
private _patchConstructor(): (original: Window['fetch']) => Window['fetch'] {
288+
return original => {
293289
const plugin = this;
294290
return function patchConstructor(
295-
this: (input: RequestInfo, init?: RequestInit) => Promise<Response>,
296-
input: RequestInfo,
297-
init?: RequestInit
291+
this: Window,
292+
...args: Parameters<Window['fetch']>
298293
): Promise<Response> {
299-
const url = input instanceof Request ? input.url : input;
300-
const options = input instanceof Request ? input : init || {};
294+
const url = args[0] instanceof Request ? args[0].url : args[0];
295+
const options = args[0] instanceof Request ? args[0] : args[1] || {};
301296
const createdSpan = plugin._createSpan(url, options);
302297
if (!createdSpan) {
303-
return original.apply(this, [url, options]);
298+
return original.apply(this, args);
304299
}
305300
const spanData = plugin._prepareSpanData(url);
306301

@@ -380,7 +375,7 @@ export class FetchInstrumentation extends InstrumentationBase<
380375
plugin._addHeaders(options, url);
381376
plugin._tasksCount++;
382377
return original
383-
.apply(this, [url, options])
378+
.apply(this, options instanceof Request ? [options] : [url, options])
384379
.then(
385380
(onSuccess as any).bind(this, createdSpan, resolve),
386381
onError.bind(this, createdSpan, reject)

packages/opentelemetry-instrumentation-fetch/test/fetch.test.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,16 @@ describe('fetch', () => {
176176
};
177177
response.headers = Object.assign({}, init.headers);
178178

179-
if (init.method === 'DELETE') {
179+
if (init instanceof Request) {
180+
// Passing request as 2nd argument causes missing body bug (#2411)
181+
response.status = 400;
182+
response.statusText = 'Bad Request (Request object as 2nd argument)';
183+
reject(new window.Response(JSON.stringify(response), response));
184+
} else if (init.method === 'DELETE') {
180185
response.status = 405;
181186
response.statusText = 'OK';
182187
resolve(new window.Response('foo', response));
183-
} else if (input === url) {
188+
} else if ((input instanceof Request && input.url === url) || input === url) {
184189
response.status = 200;
185190
response.statusText = 'OK';
186191
resolve(new window.Response(JSON.stringify(response), response));
@@ -530,6 +535,15 @@ describe('fetch', () => {
530535
assert.ok(typeof r.headers.get(X_B3_TRACE_ID) === 'string');
531536
});
532537

538+
it('should pass request object as first parameter to the original function (#2411)', () => {
539+
const r = new Request(url);
540+
return window.fetch(r).then(() => {
541+
assert.ok(true);
542+
}, (response: Response) => {
543+
assert.fail(response.statusText);
544+
});
545+
});
546+
533547
it('should NOT clear the resources', () => {
534548
assert.strictEqual(
535549
clearResourceTimingsSpy.args.length,
@@ -659,6 +673,14 @@ describe('fetch', () => {
659673
it('should NOT create any span', () => {
660674
assert.strictEqual(exportSpy.args.length, 0, "span shouldn't b exported");
661675
});
676+
it('should pass request object as the first parameter to the original function (#2411)', () => {
677+
const r = new Request(url);
678+
return window.fetch(r).then(() => {
679+
assert.ok(true);
680+
}, (response: Response) => {
681+
assert.fail(response.statusText);
682+
});
683+
});
662684
});
663685

664686
describe('when clearTimingResources is TRUE', () => {

0 commit comments

Comments
 (0)