From ddb0378e40596cf3f0baad7ec9a57a6e1f2b754a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agn=C3=A8s=20Toulet?= <35176601+AgnesToulet@users.noreply.github.com> Date: Thu, 4 May 2023 11:57:46 +0200 Subject: [PATCH 1/7] Settings: Add rendering settings in standalone mode --- src/app.ts | 122 ++++++++++++++++++++++++----------- src/plugin/v2/grpc_plugin.ts | 93 +------------------------- src/service/http-server.ts | 2 +- 3 files changed, 88 insertions(+), 129 deletions(-) diff --git a/src/app.ts b/src/app.ts index beefff8c..1aa8c271 100644 --- a/src/app.ts +++ b/src/app.ts @@ -5,7 +5,7 @@ import { RenderGRPCPluginV2 } from './plugin/v2/grpc_plugin'; import { HttpServer } from './service/http-server'; import { ConsoleLogger, PluginLogger } from './logger'; import * as minimist from 'minimist'; -import { defaultPluginConfig, defaultServiceConfig, readJSONFileSync, PluginConfig, ServiceConfig } from './config'; +import { defaultPluginConfig, defaultServiceConfig, readJSONFileSync, PluginConfig, ServiceConfig, RenderingConfig } from './config'; import { serve } from './node-plugin'; import { createSanitizer } from './sanitizer/Sanitizer'; @@ -83,7 +83,6 @@ main().catch((err) => { }); function populatePluginConfigFromEnv(config: PluginConfig, env: NodeJS.ProcessEnv) { - // Plugin env variables that needs to be initiated early if (env['GF_PLUGIN_GRPC_HOST']) { config.plugin.grpc.host = env['GF_PLUGIN_GRPC_HOST'] as string; } @@ -91,15 +90,16 @@ function populatePluginConfigFromEnv(config: PluginConfig, env: NodeJS.ProcessEn if (env['GF_PLUGIN_GRPC_PORT']) { config.plugin.grpc.port = parseInt(env['GF_PLUGIN_GRPC_PORT'] as string, 10); } -} -function populateServiceConfigFromEnv(config: ServiceConfig, env: NodeJS.ProcessEnv) { - if (env['BROWSER_TZ']) { - config.rendering.timezone = env['BROWSER_TZ']; - } else { - config.rendering.timezone = env['TZ']; + if (env['GF_PLUGIN_AUTH_TOKEN']) { + const authToken = env['GF_PLUGIN_AUTH_TOKEN'] as string; + config.plugin.security.authToken = authToken.includes(' ') ? authToken.split(' ') : authToken; } + populateRenderingConfigFromEnv(config.rendering, env, true) +} + +function populateServiceConfigFromEnv(config: ServiceConfig, env: NodeJS.ProcessEnv) { if (env['HTTP_HOST']) { config.service.host = env['HTTP_HOST']; } @@ -117,53 +117,103 @@ function populateServiceConfigFromEnv(config: ServiceConfig, env: NodeJS.Process config.service.logging.level = env['LOG_LEVEL'] as string; } - if (env['IGNORE_HTTPS_ERRORS']) { - config.rendering.ignoresHttpsErrors = env['IGNORE_HTTPS_ERRORS'] === 'true'; + if (env['ENABLE_METRICS']) { + config.service.metrics.enabled = env['ENABLE_METRICS'] === 'true'; } - if (env['CHROME_BIN']) { - config.rendering.chromeBin = env['CHROME_BIN']; + populateRenderingConfigFromEnv(config.rendering, env, false) +} + + +function populateRenderingConfigFromEnv(config: RenderingConfig, env: NodeJS.ProcessEnv, isPlugin: boolean) { + const pluginPrefix = isPlugin ? "GF_PLUGIN_" : "" + const pluginRenderingPrefix = isPlugin ? pluginPrefix + "RENDERING_" : "" + + if (env[pluginPrefix + 'RENDERING_TIMEZONE']) { + config.timezone = env[pluginPrefix + 'RENDERING_TIMEZONE']; + } else if (env['BROWSER_TZ']) { + config.timezone = env['BROWSER_TZ']; + } else { + config.timezone = env['TZ']; } - if (env['ENABLE_METRICS']) { - config.service.metrics.enabled = env['ENABLE_METRICS'] === 'true'; + if (env[pluginRenderingPrefix + 'CHROME_BIN']) { + config.chromeBin = env[pluginRenderingPrefix + 'CHROME_BIN']; } - if (env['RENDERING_MODE']) { - config.rendering.mode = env['RENDERING_MODE'] as string; + if (env[pluginPrefix + 'RENDERING_ARGS']) { + const args = env[pluginPrefix + 'RENDERING_ARGS'] as string; + if (args.length > 0) { + const argsList = args.split(','); + if (argsList.length > 0) { + config.args = argsList; + } + } } - if (env['RENDERING_CLUSTERING_MODE']) { - config.rendering.clustering.mode = env['RENDERING_CLUSTERING_MODE'] as string; + if (env[pluginRenderingPrefix + 'IGNORE_HTTPS_ERRORS']) { + config.ignoresHttpsErrors = env[pluginRenderingPrefix + 'IGNORE_HTTPS_ERRORS'] === 'true'; } - if (env['RENDERING_CLUSTERING_MAX_CONCURRENCY']) { - config.rendering.clustering.maxConcurrency = parseInt(env['RENDERING_CLUSTERING_MAX_CONCURRENCY'] as string, 10); + // New for remote + if (env[pluginPrefix + 'RENDERING_LANGUAGE']) { + config.acceptLanguage = env[pluginPrefix + 'RENDERING_LANGUAGE']; } - if (env['RENDERING_CLUSTERING_TIMEOUT']) { - config.rendering.clustering.timeout = parseInt(env['RENDERING_CLUSTERING_TIMEOUT'] as string, 10); + // New for remote + if (env[pluginPrefix + 'RENDERING_VIEWPORT_WIDTH']) { + config.width = parseInt(env[pluginPrefix + 'RENDERING_VIEWPORT_WIDTH'] as string, 10); } - if (env['RENDERING_VERBOSE_LOGGING']) { - config.rendering.verboseLogging = env['RENDERING_VERBOSE_LOGGING'] === 'true'; + // New for remote + if (env[pluginPrefix + 'RENDERING_VIEWPORT_HEIGHT']) { + config.height = parseInt(env[pluginPrefix + 'RENDERING_VIEWPORT_HEIGHT'] as string, 10); } - if (env['RENDERING_DUMPIO']) { - config.rendering.dumpio = env['RENDERING_DUMPIO'] === 'true'; + // New for remote + if (env[pluginPrefix + 'RENDERING_VIEWPORT_DEVICE_SCALE_FACTOR']) { + config.deviceScaleFactor = parseFloat(env[pluginPrefix + 'RENDERING_VIEWPORT_DEVICE_SCALE_FACTOR'] as string); } - if (env['RENDERING_VIEWPORT_PAGE_ZOOM_LEVEL']) { - config.rendering.pageZoomLevel = parseFloat(env['RENDERING_VIEWPORT_PAGE_ZOOM_LEVEL'] as string); + // New for remote + if (env[pluginPrefix + 'RENDERING_VIEWPORT_MAX_WIDTH']) { + config.maxWidth = parseInt(env[pluginPrefix + 'RENDERING_VIEWPORT_MAX_WIDTH'] as string, 10); } - if (env['RENDERING_ARGS']) { - const args = env['RENDERING_ARGS'] as string; - if (args.length > 0) { - const argsList = args.split(','); - if (argsList.length > 0) { - config.rendering.args = argsList; - } - } + // New for remote + if (env[pluginPrefix + 'RENDERING_VIEWPORT_MAX_HEIGHT']) { + config.maxHeight = parseInt(env[pluginPrefix + 'RENDERING_VIEWPORT_MAX_HEIGHT'] as string, 10); + } + + if (env[pluginPrefix + 'RENDERING_VIEWPORT_MAX_DEVICE_SCALE_FACTOR']) { + config.maxDeviceScaleFactor = parseFloat(env[pluginPrefix + 'RENDERING_VIEWPORT_MAX_DEVICE_SCALE_FACTOR'] as string); + } + + if (env[pluginPrefix + 'RENDERING_VIEWPORT_PAGE_ZOOM_LEVEL']) { + config.pageZoomLevel = parseFloat(env[pluginPrefix + 'RENDERING_VIEWPORT_PAGE_ZOOM_LEVEL'] as string); + } + + if (env[pluginPrefix + 'RENDERING_MODE']) { + config.mode = env[pluginPrefix + 'RENDERING_MODE'] as string; + } + + if (env[pluginPrefix + 'RENDERING_CLUSTERING_MODE']) { + config.clustering.mode = env[pluginPrefix + 'RENDERING_CLUSTERING_MODE'] as string; + } + + if (env[pluginPrefix + 'RENDERING_CLUSTERING_MAX_CONCURRENCY']) { + config.clustering.maxConcurrency = parseInt(env[pluginPrefix + 'RENDERING_CLUSTERING_MAX_CONCURRENCY'] as string, 10); + } + + if (env[pluginPrefix + 'RENDERING_CLUSTERING_TIMEOUT']) { + config.clustering.timeout = parseInt(env[pluginPrefix + 'RENDERING_CLUSTERING_TIMEOUT'] as string, 10); + } + + if (env[pluginPrefix + 'RENDERING_VERBOSE_LOGGING']) { + config.verboseLogging = env[pluginPrefix + 'RENDERING_VERBOSE_LOGGING'] === 'true'; + } + + if (env[pluginPrefix + 'RENDERING_DUMPIO']) { + config.dumpio = env[pluginPrefix + 'RENDERING_DUMPIO'] === 'true'; } } diff --git a/src/plugin/v2/grpc_plugin.ts b/src/plugin/v2/grpc_plugin.ts index f972731e..f2167fb8 100644 --- a/src/plugin/v2/grpc_plugin.ts +++ b/src/plugin/v2/grpc_plugin.ts @@ -52,9 +52,7 @@ const pluginV2ProtoDescriptor = grpc.loadPackageDefinition(pluginV2PackageDef); const sanitizerProtoDescriptor = grpc.loadPackageDefinition(sanitizerPackageDef); export class RenderGRPCPluginV2 implements GrpcPlugin { - constructor(private config: PluginConfig, private log: Logger) { - populateConfigFromEnv(this.config); - } + constructor(private config: PluginConfig, private log: Logger) { } async grpcServer(server: grpc.Server) { const metrics = setupMetrics(); @@ -237,95 +235,6 @@ class PluginGRPCServer { } } -const populateConfigFromEnv = (config: PluginConfig) => { - const env = Object.assign({}, process.env); - - if (env['GF_PLUGIN_RENDERING_CHROME_BIN']) { - config.rendering.chromeBin = env['GF_PLUGIN_RENDERING_CHROME_BIN']; - } - - if (env['GF_PLUGIN_RENDERING_ARGS']) { - const args = env['GF_PLUGIN_RENDERING_ARGS'] as string; - if (args.length > 0) { - const argsList = args.split(','); - if (argsList.length > 0) { - config.rendering.args = argsList; - } - } - } - - if (env['GF_PLUGIN_RENDERING_IGNORE_HTTPS_ERRORS']) { - config.rendering.ignoresHttpsErrors = env['GF_PLUGIN_RENDERING_IGNORE_HTTPS_ERRORS'] === 'true'; - } - - if (env['GF_PLUGIN_RENDERING_TIMEZONE']) { - config.rendering.timezone = env['GF_PLUGIN_RENDERING_TIMEZONE']; - } else { - config.rendering.timezone = env['TZ']; - } - - if (env['GF_PLUGIN_RENDERING_LANGUAGE']) { - config.rendering.acceptLanguage = env['GF_PLUGIN_RENDERING_LANGUAGE']; - } - - if (env['GF_PLUGIN_RENDERING_VIEWPORT_WIDTH']) { - config.rendering.width = parseInt(env['GF_PLUGIN_RENDERING_VIEWPORT_WIDTH'] as string, 10); - } - - if (env['GF_PLUGIN_RENDERING_VIEWPORT_HEIGHT']) { - config.rendering.height = parseInt(env['GF_PLUGIN_RENDERING_VIEWPORT_HEIGHT'] as string, 10); - } - - if (env['GF_PLUGIN_RENDERING_VIEWPORT_DEVICE_SCALE_FACTOR']) { - config.rendering.deviceScaleFactor = parseFloat(env['GF_PLUGIN_RENDERING_VIEWPORT_DEVICE_SCALE_FACTOR'] as string); - } - - if (env['GF_PLUGIN_RENDERING_VIEWPORT_MAX_WIDTH']) { - config.rendering.maxWidth = parseInt(env['GF_PLUGIN_RENDERING_VIEWPORT_MAX_WIDTH'] as string, 10); - } - - if (env['GF_PLUGIN_RENDERING_VIEWPORT_MAX_HEIGHT']) { - config.rendering.maxHeight = parseInt(env['GF_PLUGIN_RENDERING_VIEWPORT_MAX_HEIGHT'] as string, 10); - } - - if (env['GF_PLUGIN_RENDERING_VIEWPORT_MAX_DEVICE_SCALE_FACTOR']) { - config.rendering.maxDeviceScaleFactor = parseFloat(env['GF_PLUGIN_RENDERING_VIEWPORT_MAX_DEVICE_SCALE_FACTOR'] as string); - } - - if (env['GF_PLUGIN_RENDERING_VIEWPORT_PAGE_ZOOM_LEVEL']) { - config.rendering.pageZoomLevel = parseFloat(env['GF_PLUGIN_RENDERING_VIEWPORT_PAGE_ZOOM_LEVEL'] as string); - } - - if (env['GF_PLUGIN_RENDERING_MODE']) { - config.rendering.mode = env['GF_PLUGIN_RENDERING_MODE'] as string; - } - - if (env['GF_PLUGIN_RENDERING_CLUSTERING_MODE']) { - config.rendering.clustering.mode = env['GF_PLUGIN_RENDERING_CLUSTERING_MODE'] as string; - } - - if (env['GF_PLUGIN_RENDERING_CLUSTERING_MAX_CONCURRENCY']) { - config.rendering.clustering.maxConcurrency = parseInt(env['GF_PLUGIN_RENDERING_CLUSTERING_MAX_CONCURRENCY'] as string, 10); - } - - if (env['GF_PLUGIN_RENDERING_CLUSTERING_TIMEOUT']) { - config.rendering.clustering.timeout = parseInt(env['GF_PLUGIN_RENDERING_CLUSTERING_TIMEOUT'] as string, 10); - } - - if (env['GF_PLUGIN_RENDERING_VERBOSE_LOGGING']) { - config.rendering.verboseLogging = env['GF_PLUGIN_RENDERING_VERBOSE_LOGGING'] === 'true'; - } - - if (env['GF_PLUGIN_RENDERING_DUMPIO']) { - config.rendering.dumpio = env['GF_PLUGIN_RENDERING_DUMPIO'] === 'true'; - } - - if (env['GF_PLUGIN_AUTH_TOKEN']) { - const authToken = env['GF_PLUGIN_AUTH_TOKEN'] as string; - config.plugin.security.authToken = authToken.includes(' ') ? authToken.split(' ') : authToken; - } -}; - interface PluginMetrics { up: promClient.Gauge; browserInfo: promClient.Gauge; diff --git a/src/service/http-server.ts b/src/service/http-server.ts index 7681e56c..f8f67b95 100644 --- a/src/service/http-server.ts +++ b/src/service/http-server.ts @@ -28,7 +28,7 @@ export class HttpServer { app: express.Express; browser: Browser; - constructor(private config: ServiceConfig, private log: Logger, private sanitizer: Sanitizer) {} + constructor(private config: ServiceConfig, private log: Logger, private sanitizer: Sanitizer) { } async start() { this.app = express(); From 176ba6ebb80f4d2c03c2450f87d222a872512482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agn=C3=A8s=20Toulet?= <35176601+AgnesToulet@users.noreply.github.com> Date: Tue, 24 Oct 2023 10:21:17 +0200 Subject: [PATCH 2/7] refactor configuration code --- src/app.ts | 152 ++----------------------------- src/browser/browser.ts | 2 +- src/browser/clustered.ts | 2 +- src/browser/index.ts | 2 +- src/browser/reusable.ts | 2 +- src/config.ts | 159 --------------------------------- src/config/rendering.ts | 167 +++++++++++++++++++++++++++++++++++ src/config/security.ts | 12 +++ src/logger.ts | 2 +- src/plugin/v2/config.ts | 43 +++++++++ src/plugin/v2/grpc_plugin.ts | 3 +- src/service/config.ts | 80 +++++++++++++++++ src/service/http-server.ts | 2 +- src/service/metrics.ts | 2 +- src/service/middlewares.ts | 2 +- src/types.ts | 2 +- tsconfig.json | 9 +- 17 files changed, 325 insertions(+), 318 deletions(-) delete mode 100644 src/config.ts create mode 100644 src/config/rendering.ts create mode 100644 src/config/security.ts create mode 100644 src/plugin/v2/config.ts create mode 100644 src/service/config.ts diff --git a/src/app.ts b/src/app.ts index 09129be5..efb34b69 100644 --- a/src/app.ts +++ b/src/app.ts @@ -4,9 +4,10 @@ import * as fs from 'fs'; import { Browser, computeExecutablePath } from '@puppeteer/browsers'; import { RenderGRPCPluginV2 } from './plugin/v2/grpc_plugin'; import { HttpServer } from './service/http-server'; +import { populateServiceConfigFromEnv, ServiceConfig, defaultServiceConfig } from './service/config'; +import { populatePluginConfigFromEnv, PluginConfig, defaultPluginConfig } from './plugin/v2/config'; import { ConsoleLogger, PluginLogger } from './logger'; import * as minimist from 'minimist'; -import { defaultPluginConfig, defaultServiceConfig, readJSONFileSync, PluginConfig, ServiceConfig, RenderingConfig } from './config'; import { serve } from './node-plugin'; import { createSanitizer } from './sanitizer/Sanitizer'; @@ -86,148 +87,7 @@ main().catch((err) => { process.exit(1); }); -function populatePluginConfigFromEnv(config: PluginConfig, env: NodeJS.ProcessEnv) { - if (env['GF_PLUGIN_GRPC_HOST']) { - config.plugin.grpc.host = env['GF_PLUGIN_GRPC_HOST'] as string; - } - - if (env['GF_PLUGIN_GRPC_PORT']) { - config.plugin.grpc.port = parseInt(env['GF_PLUGIN_GRPC_PORT'] as string, 10); - } - - if (env['GF_PLUGIN_AUTH_TOKEN']) { - const authToken = env['GF_PLUGIN_AUTH_TOKEN'] as string; - config.plugin.security.authToken = authToken.includes(' ') ? authToken.split(' ') : authToken; - } - - populateRenderingConfigFromEnv(config.rendering, env, true) -} - -function populateServiceConfigFromEnv(config: ServiceConfig, env: NodeJS.ProcessEnv) { - if (env['GF_PLUGIN_RENDERING_CHROME_BIN']) { - config.rendering.chromeBin = env['GF_PLUGIN_RENDERING_CHROME_BIN']; - } - - if (env['BROWSER_TZ']) { - config.rendering.timezone = env['BROWSER_TZ']; - } else if (env['TZ']) { - config.rendering.timezone = env['TZ']; - } - - if (env['HTTP_HOST']) { - config.service.host = env['HTTP_HOST']; - } - - if (env['HTTP_PORT']) { - config.service.port = parseInt(env['HTTP_PORT'] as string, 10); - } - - if (env['AUTH_TOKEN']) { - const authToken = env['AUTH_TOKEN'] as string; - config.service.security.authToken = authToken.includes(' ') ? authToken.split(' ') : authToken; - } - - if (env['LOG_LEVEL']) { - config.service.logging.level = env['LOG_LEVEL'] as string; - } - - if (env['ENABLE_METRICS']) { - config.service.metrics.enabled = env['ENABLE_METRICS'] === 'true'; - } - - populateRenderingConfigFromEnv(config.rendering, env, false) -} - - -function populateRenderingConfigFromEnv(config: RenderingConfig, env: NodeJS.ProcessEnv, isPlugin: boolean) { - const pluginPrefix = isPlugin ? "GF_PLUGIN_" : "" - const pluginRenderingPrefix = isPlugin ? pluginPrefix + "RENDERING_" : "" - - if (env[pluginPrefix + 'RENDERING_TIMEZONE']) { - config.timezone = env[pluginPrefix + 'RENDERING_TIMEZONE']; - } else if (env['BROWSER_TZ']) { - config.timezone = env['BROWSER_TZ']; - } else { - config.timezone = env['TZ']; - } - - if (env[pluginRenderingPrefix + 'CHROME_BIN']) { - config.chromeBin = env[pluginRenderingPrefix + 'CHROME_BIN']; - } - - if (env[pluginPrefix + 'RENDERING_ARGS']) { - const args = env[pluginPrefix + 'RENDERING_ARGS'] as string; - if (args.length > 0) { - const argsList = args.split(','); - if (argsList.length > 0) { - config.args = argsList; - } - } - } - - if (env[pluginRenderingPrefix + 'IGNORE_HTTPS_ERRORS']) { - config.ignoresHttpsErrors = env[pluginRenderingPrefix + 'IGNORE_HTTPS_ERRORS'] === 'true'; - } - - // New for remote - if (env[pluginPrefix + 'RENDERING_LANGUAGE']) { - config.acceptLanguage = env[pluginPrefix + 'RENDERING_LANGUAGE']; - } - - // New for remote - if (env[pluginPrefix + 'RENDERING_VIEWPORT_WIDTH']) { - config.width = parseInt(env[pluginPrefix + 'RENDERING_VIEWPORT_WIDTH'] as string, 10); - } - - // New for remote - if (env[pluginPrefix + 'RENDERING_VIEWPORT_HEIGHT']) { - config.height = parseInt(env[pluginPrefix + 'RENDERING_VIEWPORT_HEIGHT'] as string, 10); - } - - // New for remote - if (env[pluginPrefix + 'RENDERING_VIEWPORT_DEVICE_SCALE_FACTOR']) { - config.deviceScaleFactor = parseFloat(env[pluginPrefix + 'RENDERING_VIEWPORT_DEVICE_SCALE_FACTOR'] as string); - } - - // New for remote - if (env[pluginPrefix + 'RENDERING_VIEWPORT_MAX_WIDTH']) { - config.maxWidth = parseInt(env[pluginPrefix + 'RENDERING_VIEWPORT_MAX_WIDTH'] as string, 10); - } - - // New for remote - if (env[pluginPrefix + 'RENDERING_VIEWPORT_MAX_HEIGHT']) { - config.maxHeight = parseInt(env[pluginPrefix + 'RENDERING_VIEWPORT_MAX_HEIGHT'] as string, 10); - } - - if (env[pluginPrefix + 'RENDERING_VIEWPORT_MAX_DEVICE_SCALE_FACTOR']) { - config.maxDeviceScaleFactor = parseFloat(env[pluginPrefix + 'RENDERING_VIEWPORT_MAX_DEVICE_SCALE_FACTOR'] as string); - } - - if (env[pluginPrefix + 'RENDERING_VIEWPORT_PAGE_ZOOM_LEVEL']) { - config.pageZoomLevel = parseFloat(env[pluginPrefix + 'RENDERING_VIEWPORT_PAGE_ZOOM_LEVEL'] as string); - } - - if (env[pluginPrefix + 'RENDERING_MODE']) { - config.mode = env[pluginPrefix + 'RENDERING_MODE'] as string; - } - - if (env[pluginPrefix + 'RENDERING_CLUSTERING_MODE']) { - config.clustering.mode = env[pluginPrefix + 'RENDERING_CLUSTERING_MODE'] as string; - } - - if (env[pluginPrefix + 'RENDERING_CLUSTERING_MAX_CONCURRENCY']) { - config.clustering.maxConcurrency = parseInt(env[pluginPrefix + 'RENDERING_CLUSTERING_MAX_CONCURRENCY'] as string, 10); - } - - if (env[pluginPrefix + 'RENDERING_CLUSTERING_TIMEOUT']) { - config.clustering.timeout = parseInt(env[pluginPrefix + 'RENDERING_CLUSTERING_TIMEOUT'] as string, 10); - } - - if (env[pluginPrefix + 'RENDERING_VERBOSE_LOGGING']) { - config.verboseLogging = env[pluginPrefix + 'RENDERING_VERBOSE_LOGGING'] === 'true'; - } - - if (env[pluginPrefix + 'RENDERING_DUMPIO']) { - config.dumpio = env[pluginPrefix + 'RENDERING_DUMPIO'] === 'true'; - } -} +const readJSONFileSync = (filePath: string): any => { + const rawdata = fs.readFileSync(filePath, 'utf8'); + return JSON.parse(rawdata); +}; diff --git a/src/browser/browser.ts b/src/browser/browser.ts index a0bf6014..431463fe 100644 --- a/src/browser/browser.ts +++ b/src/browser/browser.ts @@ -7,7 +7,7 @@ import * as fs from 'fs'; import * as promClient from 'prom-client'; import * as Jimp from 'jimp'; import { Logger } from '../logger'; -import { RenderingConfig } from '../config'; +import { RenderingConfig } from '../config/rendering'; import { ImageRenderOptions, RenderOptions } from '../types'; export interface Metrics { diff --git a/src/browser/clustered.ts b/src/browser/clustered.ts index fb81506c..0c5072c0 100644 --- a/src/browser/clustered.ts +++ b/src/browser/clustered.ts @@ -3,7 +3,7 @@ import { Cluster as PuppeteerCluster } from 'puppeteer-cluster'; import { ImageRenderOptions, RenderOptions } from '../types'; import { Browser, RenderResponse, RenderCSVResponse, Metrics } from './browser'; import { Logger } from '../logger'; -import { RenderingConfig, ClusteringConfig } from '../config'; +import { RenderingConfig, ClusteringConfig } from '../config/rendering'; enum RenderType { CSV = 'csv', diff --git a/src/browser/index.ts b/src/browser/index.ts index f2645017..b8331edd 100644 --- a/src/browser/index.ts +++ b/src/browser/index.ts @@ -1,4 +1,4 @@ -import { RenderingConfig } from '../config'; +import { RenderingConfig } from '../config/rendering'; import { Logger } from '../logger'; import { Browser, Metrics } from './browser'; import { ClusteredBrowser } from './clustered'; diff --git a/src/browser/reusable.ts b/src/browser/reusable.ts index 154864d3..761c0875 100644 --- a/src/browser/reusable.ts +++ b/src/browser/reusable.ts @@ -2,7 +2,7 @@ import * as puppeteer from 'puppeteer'; import { ImageRenderOptions, RenderOptions } from '../types'; import { Browser, RenderResponse, RenderCSVResponse, Metrics } from './browser'; import { Logger } from '../logger'; -import { RenderingConfig } from '../config'; +import { RenderingConfig } from '../config/rendering'; export class ReusableBrowser extends Browser { browser: puppeteer.Browser; diff --git a/src/config.ts b/src/config.ts deleted file mode 100644 index 8c26b7a6..00000000 --- a/src/config.ts +++ /dev/null @@ -1,159 +0,0 @@ -import * as fs from 'fs'; - -export interface ClusteringConfig { - monitor: boolean; - mode: string; - maxConcurrency: number; - timeout: number; -} - -// https://chromedevtools.github.io/devtools-protocol/tot/Network/#method-emulateNetworkConditions -type NetworkConditions = { - offline: boolean; - downloadThroughput: number; - uploadThroughput: number; - latency: number; -}; - -export interface RenderingConfig { - chromeBin?: string; - args: string[]; - ignoresHttpsErrors: boolean; - timezone?: string; - acceptLanguage?: string; - width: number; - height: number; - deviceScaleFactor: number; - maxWidth: number; - maxHeight: number; - maxDeviceScaleFactor: number; - pageZoomLevel: number; - mode: string; - clustering: ClusteringConfig; - verboseLogging: boolean; - dumpio: boolean; - timingMetrics: boolean; - headed?: boolean; - networkConditions?: NetworkConditions; - emulateNetworkConditions: boolean; -} - -export interface MetricsConfig { - enabled: boolean; - collectDefaultMetrics: boolean; - requestDurationBuckets: number[]; -} - -export interface ConsoleLoggerConfig { - level?: string; - json: boolean; - colorize: boolean; -} - -export interface LoggingConfig { - level: string; - console?: ConsoleLoggerConfig; -} - -export interface SecurityConfig { - authToken: string | string[]; -} - -export interface ServiceConfig { - service: { - host?: string; - port: number; - metrics: MetricsConfig; - logging: LoggingConfig; - security: SecurityConfig; - }; - rendering: RenderingConfig; -} - -export interface PluginConfig { - plugin: { - grpc: { - host: string; - port: number; - }; - security: SecurityConfig; - }; - rendering: RenderingConfig; -} - -const defaultRenderingConfig: RenderingConfig = { - chromeBin: undefined, - args: ['--no-sandbox', '--disable-gpu'], - ignoresHttpsErrors: false, - timezone: undefined, - acceptLanguage: undefined, - width: 1000, - height: 500, - headed: false, - deviceScaleFactor: 1, - maxWidth: 3000, - maxHeight: 3000, - maxDeviceScaleFactor: 4, - pageZoomLevel: 1, - mode: 'default', - clustering: { - monitor: false, - mode: 'browser', - maxConcurrency: 5, - timeout: 30, - }, - emulateNetworkConditions: false, - verboseLogging: false, - dumpio: false, - timingMetrics: false, -}; - -export const defaultServiceConfig: ServiceConfig = { - service: { - host: undefined, - port: 8081, - metrics: { - enabled: false, - collectDefaultMetrics: true, - requestDurationBuckets: [0.5, 1, 3, 5, 7, 10, 20, 30, 60], - }, - logging: { - level: 'info', - console: { - json: true, - colorize: false, - }, - }, - security: { - authToken: '-', - }, - }, - rendering: defaultRenderingConfig, -}; - -export const defaultPluginConfig: PluginConfig = { - plugin: { - grpc: { - host: '127.0.0.1', - port: 0, - }, - security: { - authToken: '-', - }, - }, - rendering: defaultRenderingConfig, -}; - -export const readJSONFileSync = (filePath: string): any => { - const rawdata = fs.readFileSync(filePath, 'utf8'); - return JSON.parse(rawdata); -}; - -export const isAuthTokenValid = (config: SecurityConfig, reqAuthToken: string): boolean => { - let configToken = config.authToken || ['']; - if (typeof configToken === "string") { - configToken = [configToken] - } - - return reqAuthToken !== "" && configToken.includes(reqAuthToken) -} diff --git a/src/config/rendering.ts b/src/config/rendering.ts new file mode 100644 index 00000000..0976f21d --- /dev/null +++ b/src/config/rendering.ts @@ -0,0 +1,167 @@ +export interface ClusteringConfig { + monitor: boolean; + mode: string; + maxConcurrency: number; + timeout: number; +} + +// https://chromedevtools.github.io/devtools-protocol/tot/Network/#method-emulateNetworkConditions +type NetworkConditions = { + offline: boolean; + downloadThroughput: number; + uploadThroughput: number; + latency: number; +}; + +export interface RenderingConfig { + chromeBin?: string; + args: string[]; + ignoresHttpsErrors: boolean; + timezone?: string; + acceptLanguage?: string; + width: number; + height: number; + deviceScaleFactor: number; + maxWidth: number; + maxHeight: number; + maxDeviceScaleFactor: number; + pageZoomLevel: number; + mode: string; + clustering: ClusteringConfig; + verboseLogging: boolean; + dumpio: boolean; + timingMetrics: boolean; + headed?: boolean; + networkConditions?: NetworkConditions; + emulateNetworkConditions: boolean; +} + +export const defaultRenderingConfig: RenderingConfig = { + chromeBin: undefined, + args: ['--no-sandbox', '--disable-gpu'], + ignoresHttpsErrors: false, + timezone: undefined, + acceptLanguage: undefined, + width: 1000, + height: 500, + headed: false, + deviceScaleFactor: 1, + maxWidth: 3000, + maxHeight: 3000, + maxDeviceScaleFactor: 4, + pageZoomLevel: 1, + mode: 'default', + clustering: { + monitor: false, + mode: 'browser', + maxConcurrency: 5, + timeout: 30, + }, + emulateNetworkConditions: false, + verboseLogging: false, + dumpio: false, + timingMetrics: false, +}; + +export function populateRenderingConfigFromEnv(config: RenderingConfig, env: NodeJS.ProcessEnv, isPlugin: boolean) { + const prefix = isPlugin ? "GF_PLUGIN_" : "" + const renderingPrefix = isPlugin ? prefix + "RENDERING_" : "" + + if (env[renderingPrefix + 'CHROME_BIN']) { + config.chromeBin = env[renderingPrefix + 'CHROME_BIN']; + } + + if (env[prefix + 'RENDERING_ARGS']) { + const args = env[prefix + 'RENDERING_ARGS'] as string; + if (args.length > 0) { + const argsList = args.split(','); + if (argsList.length > 0) { + config.args = argsList; + } + } + } + + if (env[renderingPrefix + 'IGNORE_HTTPS_ERRORS']) { + config.ignoresHttpsErrors = env[renderingPrefix + 'IGNORE_HTTPS_ERRORS'] === 'true'; + } + + if (env[prefix + 'RENDERING_TIMEZONE']) { + config.timezone = env[prefix + 'RENDERING_TIMEZONE']; + } else if (env['BROWSER_TZ']) { + config.timezone = env['BROWSER_TZ']; + } else if (env['TZ']) { + config.timezone = env['TZ']; + } + + // New for remote + if (env[prefix + 'RENDERING_LANGUAGE']) { + config.acceptLanguage = env[prefix + 'RENDERING_LANGUAGE']; + } + + // New for remote + if (env[prefix + 'RENDERING_VIEWPORT_WIDTH']) { + config.width = parseInt(env[prefix + 'RENDERING_VIEWPORT_WIDTH'] as string, 10); + } + + // New for remote + if (env[prefix + 'RENDERING_VIEWPORT_HEIGHT']) { + config.height = parseInt(env[prefix + 'RENDERING_VIEWPORT_HEIGHT'] as string, 10); + } + + // New for remote + if (env[prefix + 'RENDERING_VIEWPORT_DEVICE_SCALE_FACTOR']) { + config.deviceScaleFactor = parseFloat(env[prefix + 'RENDERING_VIEWPORT_DEVICE_SCALE_FACTOR'] as string); + } + + // New for remote + if (env[prefix + 'RENDERING_VIEWPORT_MAX_WIDTH']) { + config.maxWidth = parseInt(env[prefix + 'RENDERING_VIEWPORT_MAX_WIDTH'] as string, 10); + } + + // New for remote + if (env[prefix + 'RENDERING_VIEWPORT_MAX_HEIGHT']) { + config.maxHeight = parseInt(env[prefix + 'RENDERING_VIEWPORT_MAX_HEIGHT'] as string, 10); + } + + if (env[prefix + 'RENDERING_VIEWPORT_MAX_DEVICE_SCALE_FACTOR']) { + config.maxDeviceScaleFactor = parseFloat(env[prefix + 'RENDERING_VIEWPORT_MAX_DEVICE_SCALE_FACTOR'] as string); + } + + if (env[prefix + 'RENDERING_VIEWPORT_PAGE_ZOOM_LEVEL']) { + config.pageZoomLevel = parseFloat(env[prefix + 'RENDERING_VIEWPORT_PAGE_ZOOM_LEVEL'] as string); + } + + if (env[prefix + 'RENDERING_MODE']) { + config.mode = env[prefix + 'RENDERING_MODE'] as string; + } + + // New for both + if (env[prefix + 'RENDERING_CLUSTERING_MONITOR']) { + config.clustering.monitor = env[prefix + 'RENDERING_CLUSTERING_MONITOR'] === 'true'; + } + + if (env[prefix + 'RENDERING_CLUSTERING_MODE']) { + config.clustering.mode = env[prefix + 'RENDERING_CLUSTERING_MODE'] as string; + } + + if (env[prefix + 'RENDERING_CLUSTERING_MAX_CONCURRENCY']) { + config.clustering.maxConcurrency = parseInt(env[prefix + 'RENDERING_CLUSTERING_MAX_CONCURRENCY'] as string, 10); + } + + if (env[prefix + 'RENDERING_CLUSTERING_TIMEOUT']) { + config.clustering.timeout = parseInt(env[prefix + 'RENDERING_CLUSTERING_TIMEOUT'] as string, 10); + } + + if (env[prefix + 'RENDERING_VERBOSE_LOGGING']) { + config.verboseLogging = env[prefix + 'RENDERING_VERBOSE_LOGGING'] === 'true'; + } + + if (env[prefix + 'RENDERING_DUMPIO']) { + config.dumpio = env[prefix + 'RENDERING_DUMPIO'] === 'true'; + } + + // New for both + if (env[prefix + 'RENDERING_TIMING_METRICS']) { + config.timingMetrics = env[prefix + 'RENDERING_TIMING_METRICS'] === 'true'; + } +} diff --git a/src/config/security.ts b/src/config/security.ts new file mode 100644 index 00000000..b2c98ac6 --- /dev/null +++ b/src/config/security.ts @@ -0,0 +1,12 @@ +export interface SecurityConfig { + authToken: string | string[]; +} + +export const isAuthTokenValid = (config: SecurityConfig, reqAuthToken: string): boolean => { + let configToken = config.authToken || ['']; + if (typeof configToken === "string") { + configToken = [configToken] + } + + return reqAuthToken !== "" && configToken.includes(reqAuthToken) +} \ No newline at end of file diff --git a/src/logger.ts b/src/logger.ts index b64acd66..c882d938 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -1,5 +1,5 @@ import winston = require('winston'); -import { LoggingConfig } from './config'; +import { LoggingConfig } from './service/config'; export interface LogWriter { write(message, encoding); diff --git a/src/plugin/v2/config.ts b/src/plugin/v2/config.ts new file mode 100644 index 00000000..31de02ac --- /dev/null +++ b/src/plugin/v2/config.ts @@ -0,0 +1,43 @@ +import { SecurityConfig } from '../../config/security' +import { defaultRenderingConfig, populateRenderingConfigFromEnv, RenderingConfig } from '../../config/rendering' + +export interface PluginConfig { + plugin: { + grpc: { + host: string; + port: number; + }; + security: SecurityConfig; + }; + rendering: RenderingConfig; +} + +export const defaultPluginConfig: PluginConfig = { + plugin: { + grpc: { + host: '127.0.0.1', + port: 0, + }, + security: { + authToken: '-', + }, + }, + rendering: defaultRenderingConfig, +}; + +export function populatePluginConfigFromEnv(config: PluginConfig, env: NodeJS.ProcessEnv) { + if (env['GF_PLUGIN_GRPC_HOST']) { + config.plugin.grpc.host = env['GF_PLUGIN_GRPC_HOST'] as string; + } + + if (env['GF_PLUGIN_GRPC_PORT']) { + config.plugin.grpc.port = parseInt(env['GF_PLUGIN_GRPC_PORT'] as string, 10); + } + + if (env['GF_PLUGIN_AUTH_TOKEN']) { + const authToken = env['GF_PLUGIN_AUTH_TOKEN'] as string; + config.plugin.security.authToken = authToken.includes(' ') ? authToken.split(' ') : authToken; + } + + populateRenderingConfigFromEnv(config.rendering, env, true) +} diff --git a/src/plugin/v2/grpc_plugin.ts b/src/plugin/v2/grpc_plugin.ts index f2167fb8..5cf789db 100644 --- a/src/plugin/v2/grpc_plugin.ts +++ b/src/plugin/v2/grpc_plugin.ts @@ -3,7 +3,8 @@ import * as protoLoader from '@grpc/proto-loader'; import * as promClient from 'prom-client'; import { GrpcPlugin } from '../../node-plugin'; import { Logger } from '../../logger'; -import { PluginConfig, SecurityConfig, isAuthTokenValid } from '../../config'; +import { PluginConfig } from './config'; +import { SecurityConfig, isAuthTokenValid } from '../../config/security'; import { createBrowser, Browser } from '../../browser'; import { HTTPHeaders, ImageRenderOptions, RenderOptions } from '../../types'; import { diff --git a/src/service/config.ts b/src/service/config.ts new file mode 100644 index 00000000..823dd45b --- /dev/null +++ b/src/service/config.ts @@ -0,0 +1,80 @@ +import { defaultRenderingConfig, populateRenderingConfigFromEnv, RenderingConfig } from "../config/rendering"; +import { SecurityConfig } from "../config/security"; + +export interface MetricsConfig { + enabled: boolean; + collectDefaultMetrics: boolean; + requestDurationBuckets: number[]; +} + +export interface ConsoleLoggerConfig { + level?: string; + json: boolean; + colorize: boolean; +} + +export interface LoggingConfig { + level: string; + console?: ConsoleLoggerConfig; +} + +export interface ServiceConfig { + service: { + host?: string; + port: number; + metrics: MetricsConfig; + logging: LoggingConfig; + security: SecurityConfig; + }; + rendering: RenderingConfig; +} + +export const defaultServiceConfig: ServiceConfig = { + service: { + host: undefined, + port: 8081, + metrics: { + enabled: false, + collectDefaultMetrics: true, + requestDurationBuckets: [0.5, 1, 3, 5, 7, 10, 20, 30, 60], + }, + logging: { + level: 'info', + console: { + json: true, + colorize: false, + }, + }, + security: { + authToken: '-', + }, + }, + rendering: defaultRenderingConfig, +}; + +export function populateServiceConfigFromEnv(config: ServiceConfig, env: NodeJS.ProcessEnv) { + if (env['HTTP_HOST']) { + config.service.host = env['HTTP_HOST']; + } + + if (env['HTTP_PORT']) { + config.service.port = parseInt(env['HTTP_PORT'] as string, 10); + } + + if (env['AUTH_TOKEN']) { + const authToken = env['AUTH_TOKEN'] as string; + config.service.security.authToken = authToken.includes(' ') ? authToken.split(' ') : authToken; + } + + if (env['LOG_LEVEL']) { + config.service.logging.level = env['LOG_LEVEL'] as string; + } + + if (env['ENABLE_METRICS']) { + config.service.metrics.enabled = env['ENABLE_METRICS'] === 'true'; + } + + populateRenderingConfigFromEnv(config.rendering, env, false) +} + + diff --git a/src/service/http-server.ts b/src/service/http-server.ts index f8f67b95..e17c5236 100644 --- a/src/service/http-server.ts +++ b/src/service/http-server.ts @@ -7,7 +7,7 @@ import morgan = require('morgan'); import * as promClient from 'prom-client'; import { Logger } from '../logger'; import { Browser, createBrowser } from '../browser'; -import { ServiceConfig } from '../config'; +import { ServiceConfig } from './config'; import { setupHttpServerMetrics } from './metrics'; import { HTTPHeaders, ImageRenderOptions, RenderOptions } from '../types'; import { Sanitizer } from '../sanitizer/Sanitizer'; diff --git a/src/service/metrics.ts b/src/service/metrics.ts index a7a4583c..3afeded6 100644 --- a/src/service/metrics.ts +++ b/src/service/metrics.ts @@ -3,7 +3,7 @@ import * as promClient from 'prom-client'; import * as onFinished from 'on-finished'; import express = require('express'); -import { MetricsConfig } from '../config'; +import { MetricsConfig } from './config'; import { Logger } from '../logger'; export const setupHttpServerMetrics = (app: express.Express, config: MetricsConfig, log: Logger) => { diff --git a/src/service/middlewares.ts b/src/service/middlewares.ts index 563919d6..993f3b42 100644 --- a/src/service/middlewares.ts +++ b/src/service/middlewares.ts @@ -1,7 +1,7 @@ import express = require('express'); import * as boom from '@hapi/boom'; import { ImageRenderOptions } from '../types'; -import { SecurityConfig, isAuthTokenValid } from '../config'; +import { SecurityConfig, isAuthTokenValid } from '../config/security'; export const asyncMiddleware = (fn) => (req, res, next) => { Promise.resolve(fn(req, res, next)).catch((err) => { diff --git a/src/types.ts b/src/types.ts index 2b5ccdce..8e66ff7e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -24,4 +24,4 @@ export interface ImageRenderOptions extends RenderOptions { // Runtime options derived from the input fullPageImage?: boolean; scaleImage?: number; -} +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index ceeec5ae..7ce7a4f8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,13 +7,16 @@ "sourceMap": true, "strictNullChecks": true, "allowSyntheticDefaultImports": true, - "typeRoots": ["node_modules/@types"], + "typeRoots": [ + "node_modules/@types" + ], "rootDir": "src" }, "include": [ - "./src/*.ts" + "./src/*.ts", + "src/config/config.ts" ], "exclude": [ "node_modules" ] -} +} \ No newline at end of file From 16e712e7c3c4ebf44dbb87329dd1ae506ea8e61a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agn=C3=A8s=20Toulet?= <35176601+AgnesToulet@users.noreply.github.com> Date: Tue, 24 Oct 2023 10:52:33 +0200 Subject: [PATCH 3/7] clean up comments --- src/config/rendering.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/config/rendering.ts b/src/config/rendering.ts index 0976f21d..72d6e615 100644 --- a/src/config/rendering.ts +++ b/src/config/rendering.ts @@ -93,32 +93,26 @@ export function populateRenderingConfigFromEnv(config: RenderingConfig, env: Nod config.timezone = env['TZ']; } - // New for remote if (env[prefix + 'RENDERING_LANGUAGE']) { config.acceptLanguage = env[prefix + 'RENDERING_LANGUAGE']; } - // New for remote if (env[prefix + 'RENDERING_VIEWPORT_WIDTH']) { config.width = parseInt(env[prefix + 'RENDERING_VIEWPORT_WIDTH'] as string, 10); } - // New for remote if (env[prefix + 'RENDERING_VIEWPORT_HEIGHT']) { config.height = parseInt(env[prefix + 'RENDERING_VIEWPORT_HEIGHT'] as string, 10); } - // New for remote if (env[prefix + 'RENDERING_VIEWPORT_DEVICE_SCALE_FACTOR']) { config.deviceScaleFactor = parseFloat(env[prefix + 'RENDERING_VIEWPORT_DEVICE_SCALE_FACTOR'] as string); } - // New for remote if (env[prefix + 'RENDERING_VIEWPORT_MAX_WIDTH']) { config.maxWidth = parseInt(env[prefix + 'RENDERING_VIEWPORT_MAX_WIDTH'] as string, 10); } - // New for remote if (env[prefix + 'RENDERING_VIEWPORT_MAX_HEIGHT']) { config.maxHeight = parseInt(env[prefix + 'RENDERING_VIEWPORT_MAX_HEIGHT'] as string, 10); } @@ -135,7 +129,6 @@ export function populateRenderingConfigFromEnv(config: RenderingConfig, env: Nod config.mode = env[prefix + 'RENDERING_MODE'] as string; } - // New for both if (env[prefix + 'RENDERING_CLUSTERING_MONITOR']) { config.clustering.monitor = env[prefix + 'RENDERING_CLUSTERING_MONITOR'] === 'true'; } @@ -160,7 +153,6 @@ export function populateRenderingConfigFromEnv(config: RenderingConfig, env: Nod config.dumpio = env[prefix + 'RENDERING_DUMPIO'] === 'true'; } - // New for both if (env[prefix + 'RENDERING_TIMING_METRICS']) { config.timingMetrics = env[prefix + 'RENDERING_TIMING_METRICS'] === 'true'; } From eb9e14bcad5080d42cb5bf1d6ff6d63573b3c712 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agn=C3=A8s=20Toulet?= <35176601+AgnesToulet@users.noreply.github.com> Date: Tue, 24 Oct 2023 11:26:48 +0200 Subject: [PATCH 4/7] clean up --- src/config/rendering.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/config/rendering.ts b/src/config/rendering.ts index 72d6e615..5b672e31 100644 --- a/src/config/rendering.ts +++ b/src/config/rendering.ts @@ -129,10 +129,6 @@ export function populateRenderingConfigFromEnv(config: RenderingConfig, env: Nod config.mode = env[prefix + 'RENDERING_MODE'] as string; } - if (env[prefix + 'RENDERING_CLUSTERING_MONITOR']) { - config.clustering.monitor = env[prefix + 'RENDERING_CLUSTERING_MONITOR'] === 'true'; - } - if (env[prefix + 'RENDERING_CLUSTERING_MODE']) { config.clustering.mode = env[prefix + 'RENDERING_CLUSTERING_MODE'] as string; } From e0c9aea41c38a8ad69549f62a37c688e93d835a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agn=C3=A8s=20Toulet?= <35176601+AgnesToulet@users.noreply.github.com> Date: Tue, 24 Oct 2023 11:50:25 +0200 Subject: [PATCH 5/7] fix + clean up EOF --- src/app.ts | 3 ++- src/config/security.ts | 2 +- src/service/config.ts | 2 -- src/types.ts | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/app.ts b/src/app.ts index efb34b69..dd5247b2 100644 --- a/src/app.ts +++ b/src/app.ts @@ -87,7 +87,8 @@ main().catch((err) => { process.exit(1); }); -const readJSONFileSync = (filePath: string): any => { +function readJSONFileSync(filePath: string) { const rawdata = fs.readFileSync(filePath, 'utf8'); return JSON.parse(rawdata); }; + diff --git a/src/config/security.ts b/src/config/security.ts index b2c98ac6..93b95662 100644 --- a/src/config/security.ts +++ b/src/config/security.ts @@ -9,4 +9,4 @@ export const isAuthTokenValid = (config: SecurityConfig, reqAuthToken: string): } return reqAuthToken !== "" && configToken.includes(reqAuthToken) -} \ No newline at end of file +} diff --git a/src/service/config.ts b/src/service/config.ts index 823dd45b..161ed8f1 100644 --- a/src/service/config.ts +++ b/src/service/config.ts @@ -76,5 +76,3 @@ export function populateServiceConfigFromEnv(config: ServiceConfig, env: NodeJS. populateRenderingConfigFromEnv(config.rendering, env, false) } - - diff --git a/src/types.ts b/src/types.ts index 8e66ff7e..2b5ccdce 100644 --- a/src/types.ts +++ b/src/types.ts @@ -24,4 +24,4 @@ export interface ImageRenderOptions extends RenderOptions { // Runtime options derived from the input fullPageImage?: boolean; scaleImage?: number; -} \ No newline at end of file +} From 304c6f9bf5439123afc40fdd337cddbf9991f630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agn=C3=A8s=20Toulet?= <35176601+AgnesToulet@users.noreply.github.com> Date: Mon, 6 Nov 2023 11:32:57 +0100 Subject: [PATCH 6/7] apply review feedback --- src/config/rendering.ts | 139 ++++++++++++++++++++++++++++------------ 1 file changed, 97 insertions(+), 42 deletions(-) diff --git a/src/config/rendering.ts b/src/config/rendering.ts index 5b672e31..d58a25ca 100644 --- a/src/config/rendering.ts +++ b/src/config/rendering.ts @@ -63,16 +63,73 @@ export const defaultRenderingConfig: RenderingConfig = { timingMetrics: false, }; +enum Mode { + Plugin = 'plugin', + Server = 'server', +} + +type Keys = { + [K in keyof T]?: T[K] extends object ? (T[K] extends any[] ? string : Keys) : string; +}; + +const envConfig: Record> = { + server: { + chromeBin: 'CHROME_BIN', + args: 'RENDERING_ARGS', + ignoresHttpsErrors: 'IGNORE_HTTPS_ERRORS', + timezone: 'BROWSER_TZ', + acceptLanguage: 'RENDERING_LANGUAGE', + width: 'RENDERING_VIEWPORT_WIDTH', + height: 'RENDERING_VIEWPORT_HEIGHT', + deviceScaleFactor: 'RENDERING_VIEWPORT_DEVICE_SCALE_FACTOR', + maxWidth: 'RENDERING_VIEWPORT_MAX_WIDTH', + maxHeight: 'RENDERING_VIEWPORT_MAX_HEIGHT', + maxDeviceScaleFactor: 'RENDERING_VIEWPORT_MAX_DEVICE_SCALE_FACTOR', + pageZoomLevel: 'RENDERING_VIEWPORT_PAGE_ZOOM_LEVEL', + mode: 'RENDERING_MODE', + clustering: { + mode: 'RENDERING_CLUSTERING_MODE', + maxConcurrency: 'RENDERING_CLUSTERING_MAX_CONCURRENCY', + timeout: 'RENDERING_CLUSTERING_TIMEOUT', + }, + verboseLogging: 'RENDERING_VERBOSE_LOGGING', + dumpio: 'RENDERING_DUMPIO', + timingMetrics: 'RENDERING_TIMING_METRICS', + }, + plugin: { + chromeBin: 'GF_PLUGIN_RENDERING_CHROME_BIN', + args: 'GF_PLUGIN_RENDERING_ARGS', + ignoresHttpsErrors: 'GF_PLUGIN_RENDERING_IGNORE_HTTPS_ERRORS', + timezone: 'GF_PLUGIN_RENDERING_TIMEZONE', + acceptLanguage: 'GF_PLUGIN_RENDERING_LANGUAGE', + width: 'GF_PLUGIN_RENDERING_VIEWPORT_WIDTH', + height: 'GF_PLUGIN_RENDERING_VIEWPORT_HEIGHT', + deviceScaleFactor: 'GF_PLUGIN_RENDERING_VIEWPORT_DEVICE_SCALE_FACTOR', + maxWidth: 'GF_PLUGIN_RENDERING_VIEWPORT_MAX_WIDTH', + maxHeight: 'GF_PLUGIN_RENDERING_VIEWPORT_MAX_HEIGHT', + maxDeviceScaleFactor: 'GF_PLUGIN_RENDERING_VIEWPORT_MAX_DEVICE_SCALE_FACTOR', + pageZoomLevel: 'GF_PLUGIN_RENDERING_VIEWPORT_PAGE_ZOOM_LEVEL', + mode: 'GF_PLUGIN_RENDERING_MODE', + clustering: { + mode: 'GF_PLUGIN_RENDERING_CLUSTERING_MODE', + maxConcurrency: 'GF_PLUGIN_RENDERING_CLUSTERING_MAX_CONCURRENCY', + timeout: 'GF_PLUGIN_RENDERING_CLUSTERING_TIMEOUT', + }, + verboseLogging: 'GF_PLUGIN_RENDERING_VERBOSE_LOGGING', + dumpio: 'GF_PLUGIN_RENDERING_DUMPIO', + timingMetrics: 'GF_PLUGIN_RENDERING_TIMING_METRICS', + }, +}; + export function populateRenderingConfigFromEnv(config: RenderingConfig, env: NodeJS.ProcessEnv, isPlugin: boolean) { - const prefix = isPlugin ? "GF_PLUGIN_" : "" - const renderingPrefix = isPlugin ? prefix + "RENDERING_" : "" + const envKeys = envConfig[isPlugin ? Mode.Plugin : Mode.Server]; - if (env[renderingPrefix + 'CHROME_BIN']) { - config.chromeBin = env[renderingPrefix + 'CHROME_BIN']; + if (env[envKeys.chromeBin!]) { + config.chromeBin = env[envKeys.chromeBin!]; } - if (env[prefix + 'RENDERING_ARGS']) { - const args = env[prefix + 'RENDERING_ARGS'] as string; + if (env[envKeys.args!]) { + const args = env[envKeys.args!] as string; if (args.length > 0) { const argsList = args.split(','); if (argsList.length > 0) { @@ -81,75 +138,73 @@ export function populateRenderingConfigFromEnv(config: RenderingConfig, env: Nod } } - if (env[renderingPrefix + 'IGNORE_HTTPS_ERRORS']) { - config.ignoresHttpsErrors = env[renderingPrefix + 'IGNORE_HTTPS_ERRORS'] === 'true'; + if (env[envKeys.ignoresHttpsErrors!]) { + config.ignoresHttpsErrors = env[envKeys.ignoresHttpsErrors!] === 'true'; } - if (env[prefix + 'RENDERING_TIMEZONE']) { - config.timezone = env[prefix + 'RENDERING_TIMEZONE']; - } else if (env['BROWSER_TZ']) { - config.timezone = env['BROWSER_TZ']; + if (env[envKeys.timezone!]) { + config.timezone = env[envKeys.timezone!]; } else if (env['TZ']) { config.timezone = env['TZ']; } - if (env[prefix + 'RENDERING_LANGUAGE']) { - config.acceptLanguage = env[prefix + 'RENDERING_LANGUAGE']; + if (env[envKeys.acceptLanguage!]) { + config.acceptLanguage = env[envKeys.acceptLanguage!]; } - if (env[prefix + 'RENDERING_VIEWPORT_WIDTH']) { - config.width = parseInt(env[prefix + 'RENDERING_VIEWPORT_WIDTH'] as string, 10); + if (env[envKeys.width!]) { + config.width = parseInt(env[envKeys.width!] as string, 10); } - if (env[prefix + 'RENDERING_VIEWPORT_HEIGHT']) { - config.height = parseInt(env[prefix + 'RENDERING_VIEWPORT_HEIGHT'] as string, 10); + if (env[envKeys.height!]) { + config.height = parseInt(env[envKeys.height!] as string, 10); } - if (env[prefix + 'RENDERING_VIEWPORT_DEVICE_SCALE_FACTOR']) { - config.deviceScaleFactor = parseFloat(env[prefix + 'RENDERING_VIEWPORT_DEVICE_SCALE_FACTOR'] as string); + if (env[envKeys.deviceScaleFactor!]) { + config.deviceScaleFactor = parseFloat(env[envKeys.deviceScaleFactor!] as string); } - if (env[prefix + 'RENDERING_VIEWPORT_MAX_WIDTH']) { - config.maxWidth = parseInt(env[prefix + 'RENDERING_VIEWPORT_MAX_WIDTH'] as string, 10); + if (env[envKeys.maxWidth!]) { + config.maxWidth = parseInt(env[envKeys.maxWidth!] as string, 10); } - if (env[prefix + 'RENDERING_VIEWPORT_MAX_HEIGHT']) { - config.maxHeight = parseInt(env[prefix + 'RENDERING_VIEWPORT_MAX_HEIGHT'] as string, 10); + if (env[envKeys.maxHeight!]) { + config.maxHeight = parseInt(env[envKeys.maxHeight!] as string, 10); } - if (env[prefix + 'RENDERING_VIEWPORT_MAX_DEVICE_SCALE_FACTOR']) { - config.maxDeviceScaleFactor = parseFloat(env[prefix + 'RENDERING_VIEWPORT_MAX_DEVICE_SCALE_FACTOR'] as string); + if (env[envKeys.maxDeviceScaleFactor!]) { + config.maxDeviceScaleFactor = parseFloat(env[envKeys.maxDeviceScaleFactor!] as string); } - if (env[prefix + 'RENDERING_VIEWPORT_PAGE_ZOOM_LEVEL']) { - config.pageZoomLevel = parseFloat(env[prefix + 'RENDERING_VIEWPORT_PAGE_ZOOM_LEVEL'] as string); + if (env[envKeys.pageZoomLevel!]) { + config.pageZoomLevel = parseFloat(env[envKeys.pageZoomLevel!] as string); } - if (env[prefix + 'RENDERING_MODE']) { - config.mode = env[prefix + 'RENDERING_MODE'] as string; + if (env[envKeys.mode!]) { + config.mode = env[envKeys.mode!] as string; } - if (env[prefix + 'RENDERING_CLUSTERING_MODE']) { - config.clustering.mode = env[prefix + 'RENDERING_CLUSTERING_MODE'] as string; + if (env[envKeys.clustering?.mode!]) { + config.clustering.mode = env[envKeys.clustering?.mode!] as string; } - if (env[prefix + 'RENDERING_CLUSTERING_MAX_CONCURRENCY']) { - config.clustering.maxConcurrency = parseInt(env[prefix + 'RENDERING_CLUSTERING_MAX_CONCURRENCY'] as string, 10); + if (env[envKeys.clustering?.maxConcurrency!]) { + config.clustering.maxConcurrency = parseInt(env[envKeys.clustering?.maxConcurrency!] as string, 10); } - if (env[prefix + 'RENDERING_CLUSTERING_TIMEOUT']) { - config.clustering.timeout = parseInt(env[prefix + 'RENDERING_CLUSTERING_TIMEOUT'] as string, 10); + if (env[envKeys.clustering?.timeout!]) { + config.clustering.timeout = parseInt(env[envKeys.clustering?.timeout!] as string, 10); } - if (env[prefix + 'RENDERING_VERBOSE_LOGGING']) { - config.verboseLogging = env[prefix + 'RENDERING_VERBOSE_LOGGING'] === 'true'; + if (env[envKeys.verboseLogging!]) { + config.verboseLogging = env[envKeys.verboseLogging!] === 'true'; } - if (env[prefix + 'RENDERING_DUMPIO']) { - config.dumpio = env[prefix + 'RENDERING_DUMPIO'] === 'true'; + if (env[envKeys.dumpio!]) { + config.dumpio = env[envKeys.dumpio!] === 'true'; } - if (env[prefix + 'RENDERING_TIMING_METRICS']) { - config.timingMetrics = env[prefix + 'RENDERING_TIMING_METRICS'] === 'true'; + if (env[envKeys.timingMetrics!]) { + config.timingMetrics = env[envKeys.timingMetrics!] === 'true'; } } From c4116c3ed0f26bbb5858b1f851ff1cb6db7cea3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agn=C3=A8s=20Toulet?= <35176601+AgnesToulet@users.noreply.github.com> Date: Tue, 7 Nov 2023 10:38:42 +0100 Subject: [PATCH 7/7] update populateRenderingConfigFromEnv --- src/config/rendering.ts | 6 +++--- src/plugin/v2/config.ts | 6 +++--- src/service/config.ts | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/config/rendering.ts b/src/config/rendering.ts index d58a25ca..7d92a9c7 100644 --- a/src/config/rendering.ts +++ b/src/config/rendering.ts @@ -63,7 +63,7 @@ export const defaultRenderingConfig: RenderingConfig = { timingMetrics: false, }; -enum Mode { +export enum Mode { Plugin = 'plugin', Server = 'server', } @@ -121,8 +121,8 @@ const envConfig: Record> = { }, }; -export function populateRenderingConfigFromEnv(config: RenderingConfig, env: NodeJS.ProcessEnv, isPlugin: boolean) { - const envKeys = envConfig[isPlugin ? Mode.Plugin : Mode.Server]; +export function populateRenderingConfigFromEnv(config: RenderingConfig, env: NodeJS.ProcessEnv, mode: Mode) { + const envKeys = envConfig[mode]; if (env[envKeys.chromeBin!]) { config.chromeBin = env[envKeys.chromeBin!]; diff --git a/src/plugin/v2/config.ts b/src/plugin/v2/config.ts index 31de02ac..8180d4c2 100644 --- a/src/plugin/v2/config.ts +++ b/src/plugin/v2/config.ts @@ -1,5 +1,5 @@ -import { SecurityConfig } from '../../config/security' -import { defaultRenderingConfig, populateRenderingConfigFromEnv, RenderingConfig } from '../../config/rendering' +import { SecurityConfig } from '../../config/security'; +import { defaultRenderingConfig, populateRenderingConfigFromEnv, Mode, RenderingConfig } from '../../config/rendering'; export interface PluginConfig { plugin: { @@ -39,5 +39,5 @@ export function populatePluginConfigFromEnv(config: PluginConfig, env: NodeJS.Pr config.plugin.security.authToken = authToken.includes(' ') ? authToken.split(' ') : authToken; } - populateRenderingConfigFromEnv(config.rendering, env, true) + populateRenderingConfigFromEnv(config.rendering, env, Mode.Plugin); } diff --git a/src/service/config.ts b/src/service/config.ts index 161ed8f1..d4b852e7 100644 --- a/src/service/config.ts +++ b/src/service/config.ts @@ -1,5 +1,5 @@ -import { defaultRenderingConfig, populateRenderingConfigFromEnv, RenderingConfig } from "../config/rendering"; -import { SecurityConfig } from "../config/security"; +import { defaultRenderingConfig, populateRenderingConfigFromEnv, Mode, RenderingConfig } from '../config/rendering'; +import { SecurityConfig } from '../config/security'; export interface MetricsConfig { enabled: boolean; @@ -74,5 +74,5 @@ export function populateServiceConfigFromEnv(config: ServiceConfig, env: NodeJS. config.service.metrics.enabled = env['ENABLE_METRICS'] === 'true'; } - populateRenderingConfigFromEnv(config.rendering, env, false) + populateRenderingConfigFromEnv(config.rendering, env, Mode.Server); }