diff --git a/src/env.ts b/src/env.ts index 721f4ff..13010b8 100644 --- a/src/env.ts +++ b/src/env.ts @@ -1,6 +1,20 @@ -const headersTimeout = Number(process.env['HEADERS_TIMEOUT']) || 10000; -const requestTimeout = Number(process.env['REQUEST_TIMEOUT']) || 30000; -const keepAliveTimeout = Number(process.env['KEEP_ALIVE_TIMEOUT']) || 5000; +import { toSafeInteger } from './utils/number.js'; + +const parseEnvInteger = (envVar: string, defaultValue: number): number => { + const value = process.env[envVar]; + if (value === undefined) { + return defaultValue; + } + const parsed = toSafeInteger(value); + if (parsed === undefined) { + throw new Error(`Invalid ${envVar} environment variable: "${value}" is not a valid integer`); + } + return parsed; +}; + +const headersTimeout = parseEnvInteger('HEADERS_TIMEOUT', 10000); +const requestTimeout = parseEnvInteger('REQUEST_TIMEOUT', 30000); +const keepAliveTimeout = parseEnvInteger('KEEP_ALIVE_TIMEOUT', 5000); if (headersTimeout <= keepAliveTimeout) { throw new Error( @@ -19,9 +33,9 @@ export const environment = { headersTimeout, keepAliveTimeout, logLevel: process.env['LOG_LEVEL'] || 'info', - maxDelay: Number(process.env['MAX_DELAY']) || 10000, + maxDelay: parseEnvInteger('MAX_DELAY', 10000), nodeEnv: process.env['NODE_ENV'] || 'development', origin: process.env['ORIGIN'] || '*', - port: Number(process.env['PORT']) || 8000, + port: parseEnvInteger('PORT', 8000), requestTimeout, }; diff --git a/tests/ut/env.test.ts b/tests/ut/env.test.ts index 80ee025..7674858 100644 --- a/tests/ut/env.test.ts +++ b/tests/ut/env.test.ts @@ -80,4 +80,52 @@ describe('Environment configuration', () => { requestTimeout: 40000, }); }); + + it('should throw an error when HEADERS_TIMEOUT is not a valid integer', async () => { + process.env.HEADERS_TIMEOUT = 'invalid'; + + await expect(loadEnv()).rejects.toThrow( + 'Invalid HEADERS_TIMEOUT environment variable: "invalid" is not a valid integer' + ); + }); + + it('should throw an error when REQUEST_TIMEOUT is not a valid integer', async () => { + process.env.REQUEST_TIMEOUT = '1.5'; + + await expect(loadEnv()).rejects.toThrow( + 'Invalid REQUEST_TIMEOUT environment variable: "1.5" is not a valid integer' + ); + }); + + it('should throw an error when KEEP_ALIVE_TIMEOUT is not a valid integer', async () => { + process.env.KEEP_ALIVE_TIMEOUT = '2e10'; + + await expect(loadEnv()).rejects.toThrow( + 'Invalid KEEP_ALIVE_TIMEOUT environment variable: "2e10" is not a valid integer' + ); + }); + + it('should throw an error when MAX_DELAY is not a valid integer', async () => { + process.env.MAX_DELAY = 'abc'; + + await expect(loadEnv()).rejects.toThrow( + 'Invalid MAX_DELAY environment variable: "abc" is not a valid integer' + ); + }); + + it('should throw an error when PORT is not a valid integer', async () => { + process.env.PORT = '8000.0'; + + await expect(loadEnv()).rejects.toThrow( + 'Invalid PORT environment variable: "8000.0" is not a valid integer' + ); + }); + + it('should throw an error when integer is out of safe range', async () => { + process.env.PORT = '9007199254740992'; + + await expect(loadEnv()).rejects.toThrow( + 'Invalid PORT environment variable: "9007199254740992" is not a valid integer' + ); + }); });