diff --git a/packages/@n8n/config/src/index.ts b/packages/@n8n/config/src/index.ts index b32c7c7dc3..fee6718c6a 100644 --- a/packages/@n8n/config/src/index.ts +++ b/packages/@n8n/config/src/index.ts @@ -1,4 +1,4 @@ -import { Config, Nested } from './decorators'; +import { Config, Env, Nested } from './decorators'; import { CredentialsConfig } from './configs/credentials'; import { DatabaseConfig } from './configs/database'; import { EmailConfig } from './configs/email'; @@ -51,4 +51,24 @@ export class GlobalConfig { @Nested readonly workflows: WorkflowsConfig; + + /** Path n8n is deployed to */ + @Env('N8N_PATH') + readonly path: string = '/'; + + /** Host name n8n can be reached */ + @Env('N8N_HOST') + readonly host: string = 'localhost'; + + /** HTTP port n8n can be reached */ + @Env('N8N_PORT') + readonly port: number = 5678; + + /** IP address n8n should listen on */ + @Env('N8N_LISTEN_ADDRESS') + readonly listen_address: string = '0.0.0.0'; + + /** HTTP Protocol via which n8n can be reached */ + @Env('N8N_PROTOCOL') + readonly protocol: 'http' | 'https' = 'http'; } diff --git a/packages/@n8n/config/test/config.test.ts b/packages/@n8n/config/test/config.test.ts index 90c9ee3240..97afb0cda4 100644 --- a/packages/@n8n/config/test/config.test.ts +++ b/packages/@n8n/config/test/config.test.ts @@ -18,6 +18,11 @@ describe('GlobalConfig', () => { }); const defaultConfig: GlobalConfig = { + path: '/', + host: 'localhost', + port: 5678, + listen_address: '0.0.0.0', + protocol: 'http', database: { logging: { enabled: false, diff --git a/packages/cli/src/AbstractServer.ts b/packages/cli/src/AbstractServer.ts index b458981c15..bef45bb143 100644 --- a/packages/cli/src/AbstractServer.ts +++ b/packages/cli/src/AbstractServer.ts @@ -22,6 +22,7 @@ import { Logger } from '@/Logger'; import { ServiceUnavailableError } from './errors/response-errors/service-unavailable.error'; import { OnShutdown } from '@/decorators/OnShutdown'; import { ActiveWebhooks } from '@/ActiveWebhooks'; +import { GlobalConfig } from '@n8n/config'; @Service() export abstract class AbstractServer { @@ -33,7 +34,7 @@ export abstract class AbstractServer { protected externalHooks: ExternalHooks; - protected protocol = config.getEnv('protocol'); + protected protocol = Container.get(GlobalConfig).protocol; protected sslKey: string; @@ -149,25 +150,24 @@ export abstract class AbstractServer { this.server = http.createServer(app); } - const PORT = config.getEnv('port'); - const ADDRESS = config.getEnv('listen_address'); + const { port, listen_address: address } = Container.get(GlobalConfig); this.server.on('error', (error: Error & { code: string }) => { if (error.code === 'EADDRINUSE') { this.logger.info( - `n8n's port ${PORT} is already in use. Do you have another instance of n8n running already?`, + `n8n's port ${port} is already in use. Do you have another instance of n8n running already?`, ); process.exit(1); } }); - await new Promise((resolve) => this.server.listen(PORT, ADDRESS, () => resolve())); + await new Promise((resolve) => this.server.listen(port, address, () => resolve())); this.externalHooks = Container.get(ExternalHooks); await this.setupHealthCheck(); - this.logger.info(`n8n ready on ${ADDRESS}, port ${PORT}`); + this.logger.info(`n8n ready on ${address}, port ${port}`); } async start(): Promise { diff --git a/packages/cli/src/PublicApi/index.ts b/packages/cli/src/PublicApi/index.ts index 3ebb67f210..d484a34e36 100644 --- a/packages/cli/src/PublicApi/index.ts +++ b/packages/cli/src/PublicApi/index.ts @@ -10,8 +10,6 @@ import type { HttpError } from 'express-openapi-validator/dist/framework/types'; import type { OpenAPIV3 } from 'openapi-types'; import type { JsonObject } from 'swagger-ui-express'; -import config from '@/config'; - import { License } from '@/License'; import { UserRepository } from '@db/repositories/user.repository'; import { UrlService } from '@/services/url.service'; @@ -25,7 +23,7 @@ async function createApiRouter( handlersDirectory: string, publicApiEndpoint: string, ): Promise { - const n8nPath = config.getEnv('path'); + const n8nPath = Container.get(GlobalConfig).path; const swaggerDocument = YAML.load(openApiSpecPath) as JsonObject; // add the server depending on the config so the user can interact with the API // from the Swagger UI diff --git a/packages/cli/src/commands/start.ts b/packages/cli/src/commands/start.ts index b1ebd50393..2e88c62e06 100644 --- a/packages/cli/src/commands/start.ts +++ b/packages/cli/src/commands/start.ts @@ -124,7 +124,7 @@ export class Start extends BaseCommand { private async generateStaticAssets() { // Read the index file and replace the path placeholder - const n8nPath = config.getEnv('path'); + const n8nPath = Container.get(GlobalConfig).path; const restEndpoint = config.getEnv('endpoints.rest'); const hooksUrls = config.getEnv('externalFrontendHooksUrls'); @@ -283,7 +283,7 @@ export class Start extends BaseCommand { } const { default: localtunnel } = await import('@n8n/localtunnel'); - const port = config.getEnv('port'); + const { port } = Container.get(GlobalConfig); const webhookTunnel = await localtunnel(port, { host: 'https://hooks.n8n.cloud', diff --git a/packages/cli/src/config/schema.ts b/packages/cli/src/config/schema.ts index 061ab08b36..1e6d00aed7 100644 --- a/packages/cli/src/config/schema.ts +++ b/packages/cli/src/config/schema.ts @@ -307,40 +307,6 @@ export const schema = { }, }, - // How n8n can be reached (Editor & REST-API) - path: { - format: String, - default: '/', - arg: 'path', - env: 'N8N_PATH', - doc: 'Path n8n is deployed to', - }, - host: { - format: String, - default: 'localhost', - arg: 'host', - env: 'N8N_HOST', - doc: 'Host name n8n can be reached', - }, - port: { - format: Number, - default: 5678, - arg: 'port', - env: 'N8N_PORT', - doc: 'HTTP port n8n can be reached', - }, - listen_address: { - format: String, - default: '0.0.0.0', - env: 'N8N_LISTEN_ADDRESS', - doc: 'IP address n8n should listen on', - }, - protocol: { - format: ['http', 'https'] as const, - default: 'http', - env: 'N8N_PROTOCOL', - doc: 'HTTP Protocol via which n8n can be reached', - }, secure_cookie: { doc: 'This sets the `Secure` flag on n8n auth cookie', format: Boolean, diff --git a/packages/cli/src/services/url.service.ts b/packages/cli/src/services/url.service.ts index b1ef737c2f..8c0e1948fc 100644 --- a/packages/cli/src/services/url.service.ts +++ b/packages/cli/src/services/url.service.ts @@ -1,12 +1,13 @@ import { Service } from 'typedi'; import config from '@/config'; +import { GlobalConfig } from '@n8n/config'; @Service() export class UrlService { /** Returns the base URL n8n is reachable from */ readonly baseUrl: string; - constructor() { + constructor(private readonly globalConfig: GlobalConfig) { this.baseUrl = this.generateBaseUrl(); } @@ -27,10 +28,7 @@ export class UrlService { } private generateBaseUrl(): string { - const protocol = config.getEnv('protocol'); - const host = config.getEnv('host'); - const port = config.getEnv('port'); - const path = config.getEnv('path'); + const { path, port, host, protocol } = this.globalConfig; if ((protocol === 'http' && port === 80) || (protocol === 'https' && port === 443)) { return `${protocol}://${host}${path}`; diff --git a/packages/cli/test/unit/services/user.service.test.ts b/packages/cli/test/unit/services/user.service.test.ts index 9f84b1d202..89929f57b0 100644 --- a/packages/cli/test/unit/services/user.service.test.ts +++ b/packages/cli/test/unit/services/user.service.test.ts @@ -6,11 +6,19 @@ import { UserService } from '@/services/user.service'; import { UrlService } from '@/services/url.service'; import { mockInstance } from '../../shared/mocking'; import { UserRepository } from '@/databases/repositories/user.repository'; +import { GlobalConfig } from '@n8n/config'; describe('UserService', () => { - const urlService = new UrlService(); + const globalConfig = mockInstance(GlobalConfig, { + host: 'localhost', + path: '/', + port: 5678, + listen_address: '0.0.0.0', + protocol: 'http', + }); + const urlService = new UrlService(globalConfig); const userRepository = mockInstance(UserRepository); - const userService = new UserService(mock(), userRepository, mock(), urlService); + const userService = new UserService(mock(), userRepository, mock(), urlService, mock()); const commonMockUser = Object.assign(new User(), { id: uuid(),