Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(core): Port path, host, port, listen_address and protocol config (no-changelog) #10223

Merged
merged 5 commits into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion packages/@n8n/config/src/index.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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';
}
5 changes: 5 additions & 0 deletions packages/@n8n/config/test/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
12 changes: 6 additions & 6 deletions packages/cli/src/AbstractServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;

Expand Down Expand Up @@ -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<void>((resolve) => this.server.listen(PORT, ADDRESS, () => resolve()));
await new Promise<void>((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<void> {
Expand Down
4 changes: 1 addition & 3 deletions packages/cli/src/PublicApi/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -25,7 +23,7 @@ async function createApiRouter(
handlersDirectory: string,
publicApiEndpoint: string,
): Promise<Router> {
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
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/commands/start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');

Expand Down Expand Up @@ -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',
Expand Down
34 changes: 0 additions & 34 deletions packages/cli/src/config/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
8 changes: 3 additions & 5 deletions packages/cli/src/services/url.service.ts
Original file line number Diff line number Diff line change
@@ -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();
}

Expand All @@ -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}`;
Expand Down
12 changes: 10 additions & 2 deletions packages/cli/test/unit/services/user.service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
Loading