Skip to content

Commit c3a42f3

Browse files
authored
fix(integrations): Ensure httpclient integration works with Request (#7786)
1 parent a2cda4d commit c3a42f3

File tree

12 files changed

+273
-5
lines changed

12 files changed

+273
-5
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import * as Sentry from '@sentry/browser';
2+
import { HttpClient } from '@sentry/integrations';
3+
4+
window.Sentry = Sentry;
5+
6+
Sentry.init({
7+
dsn: 'https://[email protected]/1337',
8+
integrations: [new HttpClient()],
9+
tracesSampleRate: 1,
10+
sendDefaultPii: true,
11+
});

packages/browser-integration-tests/suites/integrations/httpclient/fetch/test.ts renamed to packages/browser-integration-tests/suites/integrations/httpclient/fetch/simple/test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { expect } from '@playwright/test';
22
import type { Event } from '@sentry/types';
33

4-
import { sentryTest } from '../../../../utils/fixtures';
5-
import { getFirstSentryEnvelopeRequest } from '../../../../utils/helpers';
4+
import { sentryTest } from '../../../../../utils/fixtures';
5+
import { getFirstSentryEnvelopeRequest } from '../../../../../utils/helpers';
66

77
sentryTest(
88
'should assign request and response context from a failed 500 fetch request',
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const request = new Request('http://localhost:7654/foo', {
2+
method: 'POST',
3+
credentials: 'include',
4+
headers: {
5+
Accept: 'application/json',
6+
'Content-Type': 'application/json',
7+
Cache: 'no-cache',
8+
},
9+
body: JSON.stringify({ test: true }),
10+
});
11+
12+
fetch(request);
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { expect } from '@playwright/test';
2+
import type { Event } from '@sentry/types';
3+
4+
import { sentryTest } from '../../../../../utils/fixtures';
5+
import { getFirstSentryEnvelopeRequest } from '../../../../../utils/helpers';
6+
7+
sentryTest('works with a Request passed in', async ({ getLocalTestPath, page }) => {
8+
const url = await getLocalTestPath({ testDir: __dirname });
9+
10+
await page.route('**/foo', route => {
11+
return route.fulfill({
12+
status: 500,
13+
body: JSON.stringify({
14+
error: {
15+
message: 'Internal Server Error',
16+
},
17+
}),
18+
headers: {
19+
'Content-Type': 'text/html',
20+
},
21+
});
22+
});
23+
24+
const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
25+
26+
expect(eventData.exception?.values).toHaveLength(1);
27+
28+
// Not able to get the cookies from the request/response because of Playwright bug
29+
// https://github.com/microsoft/playwright/issues/11035
30+
expect(eventData).toMatchObject({
31+
message: 'HTTP Client Error with status code: 500',
32+
exception: {
33+
values: [
34+
{
35+
type: 'Error',
36+
value: 'HTTP Client Error with status code: 500',
37+
mechanism: {
38+
type: 'http.client',
39+
handled: true,
40+
},
41+
},
42+
],
43+
},
44+
request: {
45+
url: 'http://localhost:7654/foo',
46+
method: 'POST',
47+
headers: {
48+
accept: 'application/json',
49+
cache: 'no-cache',
50+
'content-type': 'application/json',
51+
},
52+
},
53+
contexts: {
54+
response: {
55+
status_code: 500,
56+
body_size: 45,
57+
headers: {
58+
'content-type': 'text/html',
59+
'content-length': '45',
60+
},
61+
},
62+
},
63+
});
64+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const request = new Request('http://localhost:7654/foo', {
2+
method: 'POST',
3+
credentials: 'include',
4+
headers: {
5+
Accept: 'application/json',
6+
'Content-Type': 'application/json',
7+
Cache: 'no-cache',
8+
},
9+
body: JSON.stringify({ test: true }),
10+
});
11+
12+
fetch(request, {
13+
headers: {
14+
Accept: 'application/json',
15+
'Content-Type': 'application/json',
16+
Cache: 'cache',
17+
},
18+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { expect } from '@playwright/test';
2+
import type { Event } from '@sentry/types';
3+
4+
import { sentryTest } from '../../../../../utils/fixtures';
5+
import { getFirstSentryEnvelopeRequest } from '../../../../../utils/helpers';
6+
7+
sentryTest(
8+
'works with a Request (with body) & options passed in - handling used body',
9+
async ({ getLocalTestPath, page }) => {
10+
const url = await getLocalTestPath({ testDir: __dirname });
11+
12+
await page.route('**/foo', route => {
13+
return route.fulfill({
14+
status: 500,
15+
body: JSON.stringify({
16+
error: {
17+
message: 'Internal Server Error',
18+
},
19+
}),
20+
headers: {
21+
'Content-Type': 'text/html',
22+
},
23+
});
24+
});
25+
26+
const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
27+
28+
expect(eventData.exception?.values).toHaveLength(1);
29+
30+
// Not able to get the cookies from the request/response because of Playwright bug
31+
// https://github.com/microsoft/playwright/issues/11035
32+
expect(eventData).toMatchObject({
33+
message: 'HTTP Client Error with status code: 500',
34+
exception: {
35+
values: [
36+
{
37+
type: 'Error',
38+
value: 'HTTP Client Error with status code: 500',
39+
mechanism: {
40+
type: 'http.client',
41+
handled: true,
42+
},
43+
},
44+
],
45+
},
46+
request: {
47+
url: 'http://localhost:7654/foo',
48+
method: 'POST',
49+
headers: {
50+
accept: 'application/json',
51+
cache: 'no-cache',
52+
'content-type': 'application/json',
53+
},
54+
},
55+
contexts: {
56+
response: {
57+
status_code: 500,
58+
body_size: 45,
59+
headers: {
60+
'content-type': 'text/html',
61+
'content-length': '45',
62+
},
63+
},
64+
},
65+
});
66+
},
67+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const request = new Request('http://localhost:7654/foo', {
2+
method: 'POST',
3+
credentials: 'include',
4+
headers: {
5+
Accept: 'application/json',
6+
'Content-Type': 'application/json',
7+
Cache: 'no-cache',
8+
},
9+
});
10+
11+
fetch(request, {
12+
headers: {
13+
Accept: 'application/json',
14+
'Content-Type': 'application/json',
15+
Cache: 'cache',
16+
},
17+
});
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { expect } from '@playwright/test';
2+
import type { Event } from '@sentry/types';
3+
4+
import { sentryTest } from '../../../../../utils/fixtures';
5+
import { getFirstSentryEnvelopeRequest } from '../../../../../utils/helpers';
6+
7+
sentryTest('works with a Request (without body) & options passed in', async ({ getLocalTestPath, page }) => {
8+
const url = await getLocalTestPath({ testDir: __dirname });
9+
10+
await page.route('**/foo', route => {
11+
return route.fulfill({
12+
status: 500,
13+
body: JSON.stringify({
14+
error: {
15+
message: 'Internal Server Error',
16+
},
17+
}),
18+
headers: {
19+
'Content-Type': 'text/html',
20+
},
21+
});
22+
});
23+
24+
const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
25+
26+
expect(eventData.exception?.values).toHaveLength(1);
27+
28+
// Not able to get the cookies from the request/response because of Playwright bug
29+
// https://github.com/microsoft/playwright/issues/11035
30+
expect(eventData).toMatchObject({
31+
message: 'HTTP Client Error with status code: 500',
32+
exception: {
33+
values: [
34+
{
35+
type: 'Error',
36+
value: 'HTTP Client Error with status code: 500',
37+
mechanism: {
38+
type: 'http.client',
39+
handled: true,
40+
},
41+
},
42+
],
43+
},
44+
request: {
45+
url: 'http://localhost:7654/foo',
46+
method: 'POST',
47+
headers: {
48+
accept: 'application/json',
49+
cache: 'cache',
50+
'content-type': 'application/json',
51+
},
52+
},
53+
contexts: {
54+
response: {
55+
status_code: 500,
56+
body_size: 45,
57+
headers: {
58+
'content-type': 'text/html',
59+
'content-length': '45',
60+
},
61+
},
62+
},
63+
});
64+
});

packages/integration-shims/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"build:dev": "yarn build",
1515
"build:watch": "run-p build:transpile:watch build:types:watch",
1616
"build:dev:watch": "run-p build:watch",
17-
"build:transpile:watch": "yarn build:rollup --watch",
17+
"build:transpile:watch": "yarn build:transpile --watch",
1818
"build:types:watch": "yarn build:types --watch",
1919
"clean": "rimraf build",
2020
"fix": "run-s fix:eslint fix:prettier",

packages/integrations/src/httpclient.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export class HttpClient implements Integration {
9090
*/
9191
private _fetchResponseHandler(requestInfo: RequestInfo, response: Response, requestInit?: RequestInit): void {
9292
if (this._getCurrentHub && this._shouldCaptureResponse(response.status, response.url)) {
93-
const request = new Request(requestInfo, requestInit);
93+
const request = _getRequest(requestInfo, requestInit);
9494
const hub = this._getCurrentHub();
9595

9696
let requestHeaders, responseHeaders, requestCookies, responseCookies;
@@ -417,3 +417,18 @@ export class HttpClient implements Integration {
417417
return event;
418418
}
419419
}
420+
421+
function _getRequest(requestInfo: RequestInfo, requestInit?: RequestInit): Request {
422+
if (!requestInit && requestInfo instanceof Request) {
423+
return requestInfo;
424+
}
425+
426+
// If both are set, we try to construct a new Request with the given arguments
427+
// However, if e.g. the original request has a `body`, this will throw an error because it was already accessed
428+
// In this case, as a fallback, we just use the original request - using both is rather an edge case
429+
if (requestInfo instanceof Request && requestInfo.bodyUsed) {
430+
return requestInfo;
431+
}
432+
433+
return new Request(requestInfo, requestInit);
434+
}

packages/replay-worker/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"build:dev": "yarn build",
1515
"build:watch": "run-p build:transpile:watch build:types:watch",
1616
"build:dev:watch": "run-p build:watch",
17-
"build:transpile:watch": "yarn build:rollup --watch",
17+
"build:transpile:watch": "yarn build:transpile --watch",
1818
"build:types:watch": "yarn build:types --watch",
1919
"clean": "rimraf build",
2020
"fix": "run-s fix:eslint fix:prettier",

0 commit comments

Comments
 (0)