Skip to content

Commit

Permalink
Move from req (#1952)
Browse files Browse the repository at this point in the history
  • Loading branch information
melikhov-dev authored Dec 18, 2024
1 parent 5edf11c commit 1c0cd70
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
import {registry} from '../../../../registry';
import {config} from '../../constants';
import type {ChartsEngine} from '../../index';
import type {Source, SourceConfig} from '../../types';
import type {AdapterContext, Source, SourceConfig} from '../../types';
import {Request as RequestPromise} from '../request';
import {hideSensitiveData} from '../utils';

Expand Down Expand Up @@ -149,6 +149,29 @@ export type DataFetcherResult = {
data?: any;
};

type ZitadelParams = {
accessToken?: string;
serviceUserAccessToken?: string;
};

function addZitadelHeaders({
headers,
zitadelParams,
}: {
headers: IncomingHttpHeaders;
zitadelParams: ZitadelParams;
}) {
if (zitadelParams?.accessToken) {
Object.assign(headers, {authorization: `Bearer ${zitadelParams.accessToken}`});
}

if (zitadelParams?.serviceUserAccessToken) {
Object.assign(headers, {
[SERVICE_USER_ACCESS_TOKEN_HEADER]: zitadelParams.serviceUserAccessToken,
});
}
}

export class DataFetcher {
static fetch({
chartsEngine,
Expand Down Expand Up @@ -186,6 +209,28 @@ export class DataFetcher {
const queue = new PQueue({concurrency: CONCURRENT_REQUESTS_LIMIT});
const fetchPromisesList: (() => unknown)[] = [];

const isEmbed = req.headers[DL_EMBED_TOKEN_HEADER] !== undefined;

const zitadelParams = ctx.config.isZitadelEnabled
? {
accessToken: req.user?.accessToken,
serviceUserAccessToken: req.serviceUserAccessToken,
}
: undefined;

const originalReqHeaders = {
xRealIP: req.headers['x-real-ip'],
xForwardedFor: req.headers['x-forwarded-for'],
xChartsFetcherVia: req.headers['x-charts-fetcher-via'],
referer: req.headers.referer,
};
const adapterContext: AdapterContext = {
headers: {
['x-forwarded-for']: req.headers['x-forwarded-for'],
cookie: req.headers.cookie,
},
};

Object.keys(sources).forEach((sourceName) => {
const source = sources[sourceName];

Expand All @@ -205,6 +250,10 @@ export class DataFetcher {
userLogin,
iamToken,
workbookId,
isEmbed,
zitadelParams,
originalReqHeaders,
adapterContext,
})
: {
sourceId: sourceName,
Expand Down Expand Up @@ -420,6 +469,10 @@ export class DataFetcher {
userLogin,
iamToken,
workbookId,
isEmbed,
zitadelParams,
originalReqHeaders,
adapterContext,
}: {
sourceName: string;
source: Source;
Expand All @@ -434,6 +487,15 @@ export class DataFetcher {
userLogin?: string | null;
iamToken?: string | null;
workbookId?: WorkbookId;
isEmbed: boolean;
zitadelParams: ZitadelParams | undefined;
originalReqHeaders: {
xRealIP: IncomingHttpHeaders['x-real-ip'];
xForwardedFor: IncomingHttpHeaders['x-forwarded-for'];
xChartsFetcherVia: IncomingHttpHeaders['x-charts-fetcher-via'];
referer: IncomingHttpHeaders['referer'];
};
adapterContext: AdapterContext;
}) {
const singleFetchingTimeout =
chartsEngine.config.singleFetchingTimeout || DEFAULT_SINGLE_FETCHING_TIMEOUT;
Expand Down Expand Up @@ -528,7 +590,7 @@ export class DataFetcher {
const sourceConfig = DataFetcher.getSourceConfig({
chartsEngine,
sourcePath: targetUri,
isEmbed: req.headers[DL_EMBED_TOKEN_HEADER] !== undefined,
isEmbed,
});

if (!sourceConfig) {
Expand Down Expand Up @@ -593,6 +655,15 @@ export class DataFetcher {
});
}

if (sourceConfig.adapterWithContext) {
return sourceConfig.adapterWithContext({
targetUri: croppedTargetUri,
sourceName,
adapterContext,
ctx,
});
}

const headers: IncomingHttpHeaders = Object.assign(
{},
{
Expand All @@ -602,7 +673,7 @@ export class DataFetcher {
);

if (sourceType === 'charts') {
const incomingHeader = req.headers['x-charts-fetcher-via'] || '';
const incomingHeader = originalReqHeaders.xChartsFetcherVia || '';

const scriptName = req.body.params ? '/editor/' + req.body.params.name : req.body.path;

Expand All @@ -627,8 +698,8 @@ export class DataFetcher {
: scriptName;
}

if (req.headers.referer) {
headers.referer = ctx.utils.redactSensitiveQueryParams(req.headers.referer);
if (originalReqHeaders.referer) {
headers.referer = ctx.utils.redactSensitiveQueryParams(originalReqHeaders.referer);
}

const proxyHeaders = ctx.config.chartsEngineConfig.dataFetcherProxiedHeaders || [
Expand All @@ -651,14 +722,8 @@ export class DataFetcher {
headers[WORKBOOK_ID_HEADER] = workbookId;
}

if (req.user?.accessToken) {
Object.assign(headers, {authorization: `Bearer ${req.user.accessToken}`});
}

if (req.serviceUserAccessToken) {
Object.assign(headers, {
[SERVICE_USER_ACCESS_TOKEN_HEADER]: req.serviceUserAccessToken,
});
if (zitadelParams) {
addZitadelHeaders({headers, zitadelParams});
}

if (passedCredentials) {
Expand All @@ -678,7 +743,7 @@ export class DataFetcher {

if (extraHeaders) {
if (typeof extraHeaders === 'function') {
const extraHeadersResult = extraHeaders(req);
const extraHeadersResult = extraHeaders();

Object.assign(headers, extraHeadersResult);
} else if (typeof extraHeaders === 'object') {
Expand Down Expand Up @@ -726,7 +791,7 @@ export class DataFetcher {
}

if (ctx.config.appEnv !== 'development') {
requestOptions.headers['x-forwarded-for'] = req.headers['x-forwarded-for'];
requestOptions.headers['x-forwarded-for'] = originalReqHeaders.xForwardedFor;
}

if (isSourceWithMiddlewareUrl(source)) {
Expand Down Expand Up @@ -767,7 +832,7 @@ export class DataFetcher {
const publicSourceData = hideSensitiveData(sourceData);

if (!requestOptions.headers['x-real-ip']) {
requestOptions.headers['x-real-ip'] = req.headers['x-real-ip'];
requestOptions.headers['x-real-ip'] = originalReqHeaders.xRealIP;
}

const traceId = ctx.getTraceId();
Expand Down
26 changes: 24 additions & 2 deletions src/server/components/charts-engine/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type {OutgoingHttpHeaders} from 'http';
import type {IncomingHttpHeaders, OutgoingHttpHeaders} from 'http';

import type {AppMiddleware, AppRouteDescription, Request, Response} from '@gravity-ui/expresskit';
import type {HttpMethod} from '@gravity-ui/expresskit/dist/types';
Expand Down Expand Up @@ -125,6 +125,13 @@ export type Source<T = string | Record<string, string>> = {
sourceArgs?: SourcesArgs;
};

export type AdapterContext = {
headers: {
cookie: IncomingHttpHeaders['cookie'];
['x-forwarded-for']: IncomingHttpHeaders['x-forwarded-for'];
};
};

export type SourceConfig = {
description?: {
title: {
Expand All @@ -139,12 +146,15 @@ export type SourceConfig = {
uiEndpointFormatter?: (url: string, sourceData?: Source['data']) => string | null;
uiEndpoint?: string;
passedCredentials?: Record<string, boolean>;
extraHeaders?: Record<string, string | undefined> | ((req: Request) => Record<string, string>);
extraHeaders?: Record<string, string | undefined> | (() => Record<string, string>);
sourceType?: string;
dataEndpoint?: string;
preprocess?: (url: string) => string;
allowedMethods?: ('GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE')[];

/**
* @deprecated
**/
adapter?: ({
targetUri,
sourceName,
Expand All @@ -157,6 +167,18 @@ export type SourceConfig = {
ctx: AppContext;
}) => unknown;

adapterWithContext?: ({
targetUri,
sourceName,
adapterContext,
ctx,
}: {
targetUri: string;
sourceName: string;
adapterContext: AdapterContext;
ctx: AppContext;
}) => unknown;

middlewareAdapter?: (args: MiddlewareSourceAdapterArgs) => Promise<any>;
check?: (targetUri: string, params?: Request['body']['params']) => Promise<boolean>;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type {Request} from '@gravity-ui/expresskit';
import type {AppContext} from '@gravity-ui/nodekit';

import type {
ApiV2Filter,
Expand Down Expand Up @@ -85,14 +85,14 @@ export const getDistinctsRequestBody = ({
shared,
params,
datasetFields,
req,
ctx,
}: {
shared: ControlShared;
params: StringParams;
datasetFields: PartialDatasetField[];
req?: Request;
ctx?: AppContext;
}): ApiV2RequestBody => {
req?.ctx?.log?.('CONTROLS_START_PREPARING_DISTINCTS_BODY');
ctx?.log('CONTROLS_START_PREPARING_DISTINCTS_BODY');
const targetParam = shared.param;

const where: {
Expand All @@ -101,7 +101,7 @@ export const getDistinctsRequestBody = ({
values: string[];
}[] = [];

req?.ctx?.log?.('CONTROLS_START_MAPPING_DATASET_FIELDS');
ctx?.log('CONTROLS_START_MAPPING_DATASET_FIELDS');

const datasetFieldsMap = datasetFields.reduce(
(acc, field) => {
Expand All @@ -117,29 +117,29 @@ export const getDistinctsRequestBody = ({
{} as Record<string, {guid: string; fieldType: string}>,
);

req?.ctx?.log?.('CONTROLS_END_MAPPING_DATASET_FIELDS');
ctx?.log('CONTROLS_END_MAPPING_DATASET_FIELDS');

req?.ctx?.log?.('CONTROLS_START_TRANSFORMING_PARAMS');
ctx?.log?.('CONTROLS_START_TRANSFORMING_PARAMS');

const urlSearchParams = transformParamsToUrlParams(params);

req?.ctx?.log?.('CONTROLS_END_TRANSFORMING_PARAMS');
ctx?.log?.('CONTROLS_END_TRANSFORMING_PARAMS');

req?.ctx?.log?.('CONTROLS_START_SPLIT_PARAMS');
ctx?.log?.('CONTROLS_START_SPLIT_PARAMS');

const {filtersParams, parametersParams} = splitParamsToParametersAndFilters(
urlSearchParams,
datasetFields,
);

req?.ctx?.log?.('CONTROLS_START_TRANSFORMING_PARAMS');
ctx?.log?.('CONTROLS_START_TRANSFORMING_PARAMS');

const transformedFilterParams = transformUrlParamsToParams(filtersParams);
const transformedParametersParams = transformUrlParamsToParams(parametersParams);

req?.ctx?.log?.('CONTROLS_END_TRANSFORMING_PARAMS');
ctx?.log?.('CONTROLS_END_TRANSFORMING_PARAMS');

req?.ctx?.log('CONTROLS_START_PROCESSING_FILTERS');
ctx?.log('CONTROLS_START_PROCESSING_FILTERS');

Object.keys(transformedFilterParams).forEach((param) => {
if (param === targetParam) {
Expand Down Expand Up @@ -190,7 +190,7 @@ export const getDistinctsRequestBody = ({
}
});

req?.ctx?.log('CONTROLS_END_PROCESSING_FILTERS');
ctx?.log('CONTROLS_END_PROCESSING_FILTERS');

const apiV2RequestBody = buildDistinctsBodyRequest({
where,
Expand All @@ -199,7 +199,7 @@ export const getDistinctsRequestBody = ({
datasetFieldsMap,
});

req?.ctx?.log('CONTROLS_END_PREPARING_DISTINCTS_BODY');
ctx?.log('CONTROLS_END_PREPARING_DISTINCTS_BODY');

return apiV2RequestBody;
};
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export default async (
datasetId,
workbookId: workbookId ?? null,
req,
ctx: req.ctx,
cacheClient,
userId,
iamToken,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ export default async (
pluginOptions,
} = args;

const ctx = req.ctx;

const cacheClient = ChartsEngine.cacheClient as Cache;

const datasetId = source.datasetId || '';
Expand All @@ -29,6 +31,7 @@ export default async (
datasetId,
workbookId: workbookId ?? null,
req,
ctx,
cacheClient,
userId,
iamToken,
Expand All @@ -38,18 +41,18 @@ export default async (

const datasetFields = datasetFieldsResponse.datasetFields;

req.ctx.log('CONTROLS_DATASET_FIELDS_RECEIVED', {
ctx.log('CONTROLS_DATASET_FIELDS_RECEIVED', {
count: datasetFields.length,
});

const data = getDistinctsRequestBody({
params: source.sourceArgs.params,
shared: source.sourceArgs.shared as unknown as ControlShared,
datasetFields,
req,
ctx,
});

req.ctx.log('CONTROLS_DATASET_FIELDS_PROCESSED');
ctx.log('CONTROLS_DATASET_FIELDS_PROCESSED');

return {
...source,
Expand Down
Loading

0 comments on commit 1c0cd70

Please sign in to comment.