Skip to content

Commit

Permalink
Catch gql header in XHR proxy
Browse files Browse the repository at this point in the history
  • Loading branch information
louiszawadzki committed Sep 21, 2023
1 parent 76c715d commit b45680a
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 8 deletions.
10 changes: 9 additions & 1 deletion packages/core/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ import { SdkVerbosity } from './SdkVerbosity';
import { TrackingConsent } from './TrackingConsent';
import { DdLogs } from './logs/DdLogs';
import { DdRum } from './rum/DdRum';
import {
DATADOG_GRAPH_QL_OPERATION_TYPE_HEADER,
DATADOG_GRAPH_QL_OPERATION_NAME_HEADER,
DATADOG_GRAPH_QL_VARIABLES_HEADER
} from './rum/instrumentation/resourceTracking/graphql/graphqlHeaders';
import { RumActionType, ErrorSource, PropagatorType } from './rum/types';
import { DatadogProvider } from './sdk/DatadogProvider/DatadogProvider';
import { DdTrace } from './trace/DdTrace';
Expand All @@ -42,5 +47,8 @@ export {
VitalsUpdateFrequency,
PropagatorType,
UploadFrequency,
BatchSize
BatchSize,
DATADOG_GRAPH_QL_OPERATION_TYPE_HEADER,
DATADOG_GRAPH_QL_OPERATION_NAME_HEADER,
DATADOG_GRAPH_QL_VARIABLES_HEADER
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {
DATADOG_GRAPH_QL_OPERATION_NAME_HEADER,
DATADOG_GRAPH_QL_OPERATION_TYPE_HEADER,
DATADOG_GRAPH_QL_VARIABLES_HEADER,
isDatadogCustomHeader
} from '../graphqlHeaders';

describe('GraphQL custom headers', () => {
it.each([
DATADOG_GRAPH_QL_OPERATION_NAME_HEADER,
DATADOG_GRAPH_QL_OPERATION_TYPE_HEADER,
DATADOG_GRAPH_QL_VARIABLES_HEADER
])('%s matches the custom header pattern', header => {
expect(isDatadogCustomHeader(header)).toBeTruthy();
});

describe('isDatadogCustomHeader', () => {
it('returns false for non-custom headers', () => {
expect(isDatadogCustomHeader('non-custom-header')).toBeFalsy();
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const DATADOG_CUSTOM_HEADER_PREFIX = '_dd-custom-header';

export const DATADOG_GRAPH_QL_OPERATION_NAME_HEADER = `${DATADOG_CUSTOM_HEADER_PREFIX}-graph-ql-operation-name`;
export const DATADOG_GRAPH_QL_VARIABLES_HEADER = `${DATADOG_CUSTOM_HEADER_PREFIX}-graph-ql-variables`;
export const DATADOG_GRAPH_QL_OPERATION_TYPE_HEADER = `${DATADOG_CUSTOM_HEADER_PREFIX}-graph-ql-operation-type`;

export const isDatadogCustomHeader = (header: string) => {
return header.match(new RegExp(`^${DATADOG_CUSTOM_HEADER_PREFIX}`));
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ import Timer from '../../../../../Timer';
import { getTracingHeaders } from '../../distributedTracing/distributedTracingHeaders';
import type { DdRumResourceTracingAttributes } from '../../distributedTracing/distributedTracing';
import { getTracingAttributes } from '../../distributedTracing/distributedTracing';
import {
DATADOG_GRAPH_QL_OPERATION_NAME_HEADER,
DATADOG_GRAPH_QL_OPERATION_TYPE_HEADER,
DATADOG_GRAPH_QL_VARIABLES_HEADER,
isDatadogCustomHeader
} from '../../graphql/graphqlHeaders';
import type { RequestProxyOptions } from '../interfaces/RequestProxy';
import { RequestProxy } from '../interfaces/RequestProxy';

Expand Down Expand Up @@ -41,6 +47,7 @@ export class XHRProxy extends RequestProxy {
private providers: XHRProxyProviders;
private static originalXhrOpen: typeof XMLHttpRequest.prototype.open;
private static originalXhrSend: typeof XMLHttpRequest.prototype.send;
private static originalXhrSetRequestHeader: typeof XMLHttpRequest.prototype.setRequestHeader;

constructor(providers: XHRProxyProviders) {
super();
Expand All @@ -50,12 +57,15 @@ export class XHRProxy extends RequestProxy {
onTrackingStart = (context: RequestProxyOptions) => {
XHRProxy.originalXhrOpen = this.providers.xhrType.prototype.open;
XHRProxy.originalXhrSend = this.providers.xhrType.prototype.send;
XHRProxy.originalXhrSetRequestHeader = this.providers.xhrType.prototype.setRequestHeader;
proxyRequests(this.providers, context);
};

onTrackingStop = () => {
this.providers.xhrType.prototype.open = XHRProxy.originalXhrOpen;
this.providers.xhrType.prototype.send = XHRProxy.originalXhrSend;
this.providers.xhrType.prototype.setRequestHeader =
XHRProxy.originalXhrSetRequestHeader;
};
}

Expand All @@ -65,6 +75,7 @@ const proxyRequests = (
): void => {
proxyOpen(providers, context);
proxySend(providers);
proxySetRequestHeader(providers);
};

const proxyOpen = (
Expand Down Expand Up @@ -181,3 +192,32 @@ const reportXhr = async (
resourceContext: xhrProxy
});
};

const proxySetRequestHeader = (providers: XHRProxyProviders): void => {
const xhrType = providers.xhrType;
const originalXhrSetRequestHeader = xhrType.prototype.setRequestHeader;

xhrType.prototype.setRequestHeader = function (
this: DdRumXhr,
header: string,
value: string
) {
if (isDatadogCustomHeader(header)) {
if (header === DATADOG_GRAPH_QL_OPERATION_NAME_HEADER) {
// TODO: add information to request
return;
}
if (header === DATADOG_GRAPH_QL_OPERATION_TYPE_HEADER) {
// TODO: add information to request
return;
}
if (header === DATADOG_GRAPH_QL_VARIABLES_HEADER) {
// TODO: add information to request
return;
}
}

// eslint-disable-next-line prefer-rest-params
return originalXhrSetRequestHeader.apply(this, arguments as any);
};
};
27 changes: 20 additions & 7 deletions packages/react-native-apollo-client/src/DatadogLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
*/

import { ApolloLink } from '@apollo/client';
import {
DATADOG_GRAPH_QL_OPERATION_TYPE_HEADER,
DATADOG_GRAPH_QL_OPERATION_NAME_HEADER,
DATADOG_GRAPH_QL_VARIABLES_HEADER
} from '@datadog/mobile-react-native';

import { getOperationName, getVariables, getOperationType } from './helpers';

Expand All @@ -16,14 +21,22 @@ export class DatadogLink extends ApolloLink {
const operationType = getOperationType(operation);

operation.setContext(({ headers = {} }) => {
const newHeaders: Record<string, string | null> = {
...headers
};

newHeaders[
DATADOG_GRAPH_QL_OPERATION_TYPE_HEADER
] = operationType;
newHeaders[
DATADOG_GRAPH_QL_OPERATION_NAME_HEADER
] = operationName;
newHeaders[
DATADOG_GRAPH_QL_VARIABLES_HEADER
] = formattedVariables;

return {
headers: {
...headers,
// TODO: import headers from core
'_dd-graph-ql-operation-name': operationName,
'_dd-graph-ql-variables': formattedVariables,
'_dd-graph-ql-operation-type': operationType
}
headers: newHeaders
};
});

Expand Down

0 comments on commit b45680a

Please sign in to comment.