From ce160d33a1e8146a2dc026cfba9fb42289a85255 Mon Sep 17 00:00:00 2001 From: Aymeric Mortemousque Date: Mon, 30 Aug 2021 17:20:19 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fix=20dd-request-id=20endpoint?= =?UTF-8?q?=20query=20param?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/configuration/endpointBuilder.ts | 5 +- .../core/src/transport/httpRequest.spec.ts | 48 +++++++++++++++++++ packages/core/src/transport/httpRequest.ts | 20 +++++++- 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/packages/core/src/domain/configuration/endpointBuilder.ts b/packages/core/src/domain/configuration/endpointBuilder.ts index 1b2c3e1c5e..362323a56c 100644 --- a/packages/core/src/domain/configuration/endpointBuilder.ts +++ b/packages/core/src/domain/configuration/endpointBuilder.ts @@ -69,9 +69,8 @@ export function createEndpointBuilder( if (shouldUseIntakeV2(endpointType)) { parameters += `&dd-api-key=${clientToken}&` + - `dd-evp-origin-version=${sdkVersion}&` + - `dd-evp-origin=browser&` + - `dd-request-id=${generateUUID()}` + `dd-evp-origin-version=${encodeURIComponent(sdkVersion)}&` + + `dd-evp-origin=browser` } return `${buildIntakeUrl(endpointType)}?${parameters}` diff --git a/packages/core/src/transport/httpRequest.spec.ts b/packages/core/src/transport/httpRequest.spec.ts index 7bb35c2e2d..f21767bca5 100644 --- a/packages/core/src/transport/httpRequest.spec.ts +++ b/packages/core/src/transport/httpRequest.spec.ts @@ -1,5 +1,7 @@ /* eslint-disable @typescript-eslint/unbound-method */ import sinon from 'sinon' +import { BuildEnv, BuildMode } from '../boot/init' +import { createEndpointBuilder } from '../domain/configuration/endpointBuilder' import { HttpRequest } from './httpRequest' describe('httpRequest', () => { @@ -63,3 +65,49 @@ describe('httpRequest', () => { expect(server.requests.length).toEqual(1) }) }) + +describe('httpRequest parameters', () => { + const BATCH_BYTES_LIMIT = 100 + const clientToken = 'some_client_token' + const buildEnv: BuildEnv = { + buildMode: BuildMode.RELEASE, + sdkVersion: 'some_version', + } + let server: sinon.SinonFakeServer + let sendBeaconSpy: jasmine.Spy<(url: string, data?: BodyInit | null) => boolean> + beforeEach(() => { + server = sinon.fakeServer.create() + sendBeaconSpy = jasmine.createSpy() + navigator.sendBeacon = sendBeaconSpy + }) + + afterEach(() => { + server.restore() + }) + + it('should add batch_time', () => { + const request = new HttpRequest('https://my.website', BATCH_BYTES_LIMIT, true) + + request.send('{"foo":"bar1"}', 10) + + expect(sendBeaconSpy.calls.argsFor(0)[0]).toContain(`batch_time=`) + }) + + it('should add dd-request-id query attribute when the intake v2 enabled', () => { + const endpointBuilder = createEndpointBuilder({ clientToken, intakeApiVersion: 2 }, buildEnv, true) + const request = new HttpRequest(endpointBuilder.build('rum'), BATCH_BYTES_LIMIT) + + request.send('{"foo":"bar1"}', 10) + + expect(sendBeaconSpy.calls.argsFor(0)[0]).toContain(`&dd-request-id=`) + }) + + it('should not add dd-request-id query attribute when the intake v1 enabled', () => { + const endpointBuilder = createEndpointBuilder({ clientToken }, buildEnv, true) + const request = new HttpRequest(endpointBuilder.build('rum'), BATCH_BYTES_LIMIT) + + request.send('{"foo":"bar1"}', 10) + + expect(sendBeaconSpy.calls.argsFor(0)[0]).not.toContain(`&dd-request-id=`) + }) +}) diff --git a/packages/core/src/transport/httpRequest.ts b/packages/core/src/transport/httpRequest.ts index 4ab59e1143..904db0269b 100644 --- a/packages/core/src/transport/httpRequest.ts +++ b/packages/core/src/transport/httpRequest.ts @@ -1,4 +1,5 @@ import { monitor, addErrorToMonitoringBatch, addMonitoringMessage } from '../domain/internalMonitoring' +import { generateUUID, includes } from '../tools/utils' let hasReportedXhrError = false @@ -14,7 +15,16 @@ export class HttpRequest { constructor(private endpointUrl: string, private bytesLimit: number, private withBatchTime: boolean = false) {} send(data: string | FormData, size: number) { - const url = this.withBatchTime ? addBatchTime(this.endpointUrl) : this.endpointUrl + let url = this.endpointUrl + + if (isEndpointIntakeV2(url)) { + url = addRequestId(url) + } + + if (this.withBatchTime) { + url = addBatchTime(url) + } + const tryBeacon = !!navigator.sendBeacon && size < this.bytesLimit if (tryBeacon) { try { @@ -67,6 +77,14 @@ function addBatchTime(url: string) { return `${url}${url.indexOf('?') === -1 ? '?' : '&'}batch_time=${new Date().getTime()}` } +function addRequestId(url: string) { + return `${url}${url.indexOf('?') === -1 ? '?' : '&'}dd-request-id=${generateUUID()}` +} + +function isEndpointIntakeV2(url: string) { + return includes(url, '/api/v2') +} + let hasReportedBeaconError = false function reportBeaconError(e: unknown) { if (!hasReportedBeaconError) {