queryRouter is a function which routes the route to specific controller. under this there is router.use() which act as middleware for route, here i`m receiving the req params from the client side.
import { NextFunction, Request, Response, Router } from "express";
import { Logger } from "../../../common/logger/logger";
import { QueryableDataCube } from "../../../common/models/data-cube/queryable-data-cube";
import { Essence } from "../../../common/models/essence/essence";
import { Timekeeper } from "../../../common/models/timekeeper/timekeeper";
import {
DEFAULT_VIEW_DEFINITION_VERSION,
definitionConverters,
} from "../../../common/view-definitions";
import { createEssence } from "../../utils/essence/create-essence";
import { asyncHandler } from "../../utils/express/async-handler";
import {
AppliedQueryDecorator,
getQueryDecorator,
} from "../../utils/query-decorator-loader/get-query-decorator";
import { handleRequestErrors } from "../../utils/request-errors/handle-request-errors";
import { parseDataCube } from "../../utils/request-params/parse-data-cube";
import { parseViewDefinition } from "../../utils/request-params/parse-view-definition";
import { SettingsManager } from "../../utils/settings-manager/settings-manager";
import booleanFilterRoute from "./routes/boolean-filter";
import numberFilterRoute from "./routes/number-filter";
import pinboardRoute from "./routes/pinboard";
import rawDataRoute from "./routes/raw-data";
import stringFilterRoute from "./routes/string-filter";
import visualizationRoute from "./routes/visualization";
const converter = definitionConverters[DEFAULT_VIEW_DEFINITION_VERSION];
interface QueryRouterContext {
dataCube: QueryableDataCube;
essence: Essence;
decorator: AppliedQueryDecorator;
timekeeper: Timekeeper;
logger: Logger;
headers: any; // Add the headers property
}
export type QueryRouterRequest = Request & {
context?: QueryRouterContext;
};
export function queryRouter(
settings: Pick<
SettingsManager,
"logger" | "getSources" | "appSettings" | "anchorPath" | "getTimekeeper"
>
) {
// console.log('ClusterManager', ClusterManager);
const logger = settings.logger;
const router = Router();
router.use(
asyncHandler(async (req: Request, res: Response, next: NextFunction) => {
console.log("req===================================", req.headers);
// headers = req.headers;
const dataCube = await parseDataCube(req, settings);
const viewDefinition = parseViewDefinition(req);
const essence = createEssence(
viewDefinition,
converter,
dataCube,
settings.appSettings
);
const decorator = getQueryDecorator(req, dataCube, settings);
(req as QueryRouterRequest).context = {
logger,
dataCube,
essence,
decorator,
timekeeper: settings.getTimekeeper(),
headers: req.headers,
};
next();
})
);
router.post("/visualization", asyncHandler(visualizationRoute));
router.post("/raw-data", asyncHandler(rawDataRoute));
router.post("/boolean-filter", asyncHandler(booleanFilterRoute));
router.post("/string-filter", asyncHandler(stringFilterRoute));
router.post("/number-filter", asyncHandler(numberFilterRoute));
router.post("/pinboard", asyncHandler(pinboardRoute));
router.use(
(error: Error, req: Request, res: Response, next: NextFunction) => {
handleRequestErrors(error, res, logger);
}
);
return router;
}
//I need to transport req.headers data to utils folder under clustermanager file
import { External } from "plywood";
import { PlywoodRequester } from "plywood-base-api";
import {
DecoratorRequest,
DruidRequestDecorator,
} from "plywood-druid-requester";
import { Logger } from "../../../common/logger/logger";
import {
Cluster,
makeExternalFromSourceName,
shouldScanSources,
} from "../../../common/models/cluster/cluster";
import { constant, noop } from "../../../common/utils/functional/functional";
import { isNil } from "../../../common/utils/general/general";
import { loadModule } from "../module-loader/module-loader";
import { DruidRequestDecoratorModule } from "../request-decorator/request-decorator";
import { properRequesterFactory } from "../requester/requester";
import { QueryRouterRequest } from "../../routes/query/query";
const CONNECTION_RETRY_TIMEOUT = 20000;
const DRUID_REQUEST_DECORATOR_MODULE_VERSION = 1;
// For each external we want to maintain its source and whether it should introspect at all
export interface ManagedExternal {
name: string;
external: External;
autoDiscovered?: boolean;
suppressIntrospection?: boolean;
}
export interface ClusterManagerOptions {
logger: Logger;
verbose?: boolean;
anchorPath: string;
initialExternals?: ManagedExternal[];
onExternalChange?: (name: string, external: External) => Promise<void>;
onExternalRemoved?: (name: string, external: External) => Promise<void>;
generateExternalName?: (external: External) => string;
}
function emptyResolve(): Promise<void> {
return Promise.resolve(null);
}
function getSourceFromExternal(external: External): string {
return String(external.source);
}
function externalContainsSource(external: External, source: string): boolean {
return Array.isArray(external.source)
? external.source.indexOf(source) > -1
: String(external.source) === source;
}
export class ClusterManager {
public logger: Logger;
public verbose: boolean;
public anchorPath: string;
public cluster: Cluster;
public initialConnectionEstablished: boolean;
public introspectedSources: Record<string, boolean>;
public version: string;
public managedExternals: ManagedExternal[] = [];
public onExternalChange: (name: string, external: External) => Promise<void>;
public onExternalRemoved: (name: string, external: External) => Promise<void>;
public generateExternalName: (external: External) => string;
private requester: PlywoodRequester<any>;
private sourceListRefreshInterval = 0;
private sourceListRefreshTimer: NodeJS.Timer = null;
private sourceReintrospectInterval = 0;
private sourceReintrospectTimer: NodeJS.Timer = null;
private initialConnectionTimer: NodeJS.Timer = null;
public headers: any;
constructor(cluster: Cluster, options: ClusterManagerOptions) {
if (!cluster) throw new Error("must have cluster");
this.logger = options.logger;
this.verbose = Boolean(options.verbose);
this.anchorPath = options.anchorPath;
this.cluster = cluster;
this.initialConnectionEstablished = false;
this.introspectedSources = {};
this.version = cluster.version;
this.managedExternals = options.initialExternals || [];
this.onExternalChange = options.onExternalChange || emptyResolve;
this.onExternalRemoved = options.onExternalRemoved || emptyResolve;
this.generateExternalName =
options.generateExternalName || getSourceFromExternal;
this.requester = this.initRequester();
this.someMethod = this.someMethod;
this.managedExternals.forEach((managedExternal) => {
managedExternal.external = managedExternal.external.attachRequester(
this.requester
);
});
}
// Do initialization
public init(): Promise<void> {
const { cluster, logger } = this;
if (cluster.sourceListRefreshOnLoad) {
logger.log(`Cluster '${cluster.name}' will refresh source list on load`);
}
if (cluster.sourceReintrospectOnLoad) {
logger.log(`Cluster '${cluster.name}' will reintrospect sources on load`);
}
return this.establishInitialConnection()
.then(() => this.introspectSources())
.then(() => this.scanSourceList());
}
public destroy() {
if (this.sourceListRefreshTimer) {
clearInterval(this.sourceListRefreshTimer);
this.sourceListRefreshTimer = null;
}
if (this.sourceReintrospectTimer) {
clearInterval(this.sourceReintrospectTimer);
this.sourceReintrospectTimer = null;
}
if (this.initialConnectionTimer) {
clearTimeout(this.initialConnectionTimer);
this.initialConnectionTimer = null;
}
}
private addManagedExternal(managedExternal: ManagedExternal): Promise<void> {
this.managedExternals.push(managedExternal);
return this.onExternalChange(
managedExternal.name,
managedExternal.external
);
}
private updateManagedExternal(
managedExternal: ManagedExternal,
newExternal: External
): Promise<void> {
if (managedExternal.external.equals(newExternal)) return null;
managedExternal.external = newExternal;
return this.onExternalChange(
managedExternal.name,
managedExternal.external
);
}
private removeManagedExternal(
managedExternal: ManagedExternal
): Promise<void> {
this.managedExternals = this.managedExternals.filter(
(ext) => ext.external !== managedExternal.external
);
return this.onExternalRemoved(
managedExternal.name,
managedExternal.external
);
}
private initRequester(): PlywoodRequester<any> {
const { cluster } = this;
const druidRequestDecorator = this.createDruidRequestDecorator();
return properRequesterFactory({
cluster,
verbose: this.verbose,
concurrentLimit: 5,
druidRequestDecorator,
});
}
private clusterAuthHeaders(): Record<"Authorization", string> | undefined {
const { auth } = this.cluster;
console.log("auth", this.cluster);
if (isNil(auth)) return undefined;
switch (auth.type) {
case "http-basic": {
const credentials = `${auth.username}:${auth.password}`;
const Authorization = `Basic ${Buffer.from(credentials).toString(
"base64"
)}`;
return { Authorization };
}
}
}