From 3b60290f43e9b050151c5ba5e7405192b41997dc Mon Sep 17 00:00:00 2001 From: Charles Morin Date: Tue, 17 Oct 2023 15:21:20 -0400 Subject: [PATCH] Added http cursor basic auth --- src/commander.ts | 6 ++++++ src/cursor/httpCursor.ts | 5 +++-- src/prometheus.ts | 2 +- src/setup.ts | 3 ++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/commander.ts b/src/commander.ts index c907d05..1d96615 100644 --- a/src/commander.ts +++ b/src/commander.ts @@ -22,6 +22,7 @@ export interface RunOptions { authIssueUrl: string; delayBeforeStart: number; cursorPath: string; + httpCursorAuth: string; productionMode: string; restartInactivitySeconds: number; hostname: string; @@ -73,6 +74,10 @@ function handleHeaders(value: string, previous: Headers) { return headers; } +function handleHttpCursorAuth(value: string) { + return btoa(value); +} + export function run(program: Command, pkg: Package) { return program.command("run") .showHelpAfterError() @@ -87,6 +92,7 @@ export function run(program: Command, pkg: Package) { .addOption(new Option("--auth-issue-url ", "URL used to issue a token").default(DEFAULT_AUTH_ISSUE_URL).env("AUTH_ISSUE_URL")) .addOption(new Option("--delay-before-start ", "Delay (ms) before starting Substreams").default(DEFAULT_DELAY_BEFORE_START).env("DELAY_BEFORE_START")) .addOption(new Option("--cursor-path ", "File path or URL to cursor lock file").default(DEFAULT_CURSOR_PATH).env("CURSOR_PATH")) + .addOption(new Option("--http-cursor-auth ", "Basic auth credentials for http cursor (ex: username:password)").env("HTTP_CURSOR_AUTH").argParser(handleHttpCursorAuth)) .addOption(new Option("--production-mode ", "Enable production mode, allows cached substreams data if available").default(DEFAULT_PRODUCTION_MODE).env("PRODUCTION_MODE")) .addOption(new Option("--restart-inactivity-seconds ", "If set, the sink will restart when inactive for over a certain amount of seconds").default(DEFAULT_RESTART_INACTIVITY_SECONDS).env("RESTART_INACTIVITY_SECONDS")) .addOption(new Option("--hostname ", "The process will listen on this hostname for any HTTP and Prometheus metrics requests").default(DEFAULT_HOSTNAME).env("HOSTNAME")) diff --git a/src/cursor/httpCursor.ts b/src/cursor/httpCursor.ts index 406ea61..41b1b57 100644 --- a/src/cursor/httpCursor.ts +++ b/src/cursor/httpCursor.ts @@ -7,8 +7,9 @@ export function onCursor(emitter: BlockEmitter, cursorPath: string) { }); } -export async function readCursor(cursorPath: string) { - const response = await fetch(cursorPath); +export async function readCursor(cursorPath: string, httpCursorAuth?: string) { + const headers = httpCursorAuth ? { Authorization: `Basic ${httpCursorAuth}` } : undefined; + const response = await fetch(cursorPath, { headers }); if (!response.ok) { return ""; diff --git a/src/prometheus.ts b/src/prometheus.ts index 746abc1..0545a8e 100644 --- a/src/prometheus.ts +++ b/src/prometheus.ts @@ -102,7 +102,7 @@ export function handleSession(session: SessionInit) { } export function handleManifest(emitter: BlockEmitter, moduleHash: string, options: RunOptions) { - logger.info("manifest", { moduleHash, manifest: options.manifest, substreamsEndpoint: options.substreamsEndpoint, finalBlocksOnly: options.finalBlocksOnly, production_mode: options.productionMode }); + logger.info("manifest", { moduleHash, manifest: options.manifest, substreamsEndpoint: options.substreamsEndpoint, finalBlocksOnly: options.finalBlocksOnly, productionMode: options.productionMode }); const labelNames = ["module_hash", "manifest", "output_module", "substreams_endpoint", "start_block_num", "stop_block_num", "production_mode", "final_blocks_only"]; const gauge = registerGauge("manifest", "Substreams manifest and sha256 hash of map module", labelNames) as Gauge; gauge.labels({ diff --git a/src/setup.ts b/src/setup.ts index 194625b..2c2b95d 100644 --- a/src/setup.ts +++ b/src/setup.ts @@ -33,6 +33,7 @@ export async function setup(options: RunOptions) { const params = options.params; const headers = options.headers; const cursorPath = options.cursorPath; + const httpCursorAuth = options.httpCursorAuth; const productionMode = String(options.productionMode) === "true"; const finalBlocksOnly = String(options.finalBlocksOnly) === "true"; @@ -51,7 +52,7 @@ export async function setup(options: RunOptions) { const cursor = cursorPath.startsWith("http") ? httpCursor : fileCursor; // Connect Transport - const startCursor = await cursor.readCursor(cursorPath); + const startCursor = await cursor.readCursor(cursorPath, httpCursorAuth); const registry = createRegistry(substreamPackage); const transport = createDefaultTransport(baseUrl, token, registry, headers); const request = createRequest({