diff --git a/apps/cli/e2e/server/basic.e2e-spec.ts b/apps/cli/e2e/server/basic.e2e-spec.ts index d8ac375b..b9ffd154 100644 --- a/apps/cli/e2e/server/basic.e2e-spec.ts +++ b/apps/cli/e2e/server/basic.e2e-spec.ts @@ -1,4 +1,5 @@ import * as ADCSDK from '@api7/adc-sdk'; +import axios from 'axios'; import { lastValueFrom } from 'rxjs'; import request from 'supertest'; @@ -11,7 +12,7 @@ describe('Server - Basic', () => { beforeAll(async () => { mockedBackend = jestMockBackend(); - server = new ADCServer(); + server = new ADCServer({ listen: new URL('http://127.0.1:3000') }); }); it('test mocked load backend', async () => { @@ -69,7 +70,7 @@ describe('Server - Basic', () => { server: 'http://1.1.1.1:3000', token: 'mock', }, - config: config, + config, }, }); @@ -77,4 +78,25 @@ describe('Server - Basic', () => { expect(body.status).toBe('success'); await expect(lastValueFrom(mockedBackend.dump())).resolves.toEqual(config); }); + + it('test server listen', async () => { + const url = new URL(`http://127.0.0.1:48562`); + const server = new ADCServer({ listen: url }); + await server.start(); + + const { status, data } = await axios.put(`${url.origin}/sync`, { + task: { + opts: { + backend: 'mock', + server: 'http://1.1.1.1:3000', + token: 'mock', + }, + config: {}, + }, + }); + expect(status).toBe(202); + expect(data.status).toBe('success'); + + await server.stop(); + }); }); diff --git a/apps/cli/src/command/helper.ts b/apps/cli/src/command/helper.ts index 800e5415..323efc3d 100644 --- a/apps/cli/src/command/helper.ts +++ b/apps/cli/src/command/helper.ts @@ -70,18 +70,21 @@ export class BackendCommand< this.addBackendOptions(); } - public handle(cb: (opts: OPTS, command: Command) => void | Promise) { - const opts = this.opts(); - - if (!has(opts, 'tlsClientCertFile') || !has(opts, 'tlsClientKeyFile')) { - console.log( - chalk.red( - 'TLS client certificate and key must be provided at the same time', - ), - ); - return this; - } - return super.handle(cb); + public handle(func: (opts: OPTS, command: Command) => void | Promise) { + return super.handle(async (opts, command) => { + if ( + (has(opts, 'tlsClientCertFile') && !has(opts, 'tlsClientKeyFile')) || + (!has(opts, 'tlsClientCertFile') && has(opts, 'tlsClientKeyFile')) + ) { + console.log( + chalk.red( + 'TLS client certificate and key must be provided at the same time', + ), + ); + return; + } + await func(opts, command); + }); } private addBackendOptions() { diff --git a/apps/cli/src/command/ingress-server.command.ts b/apps/cli/src/command/ingress-server.command.ts index 1e63bb9d..98da6f61 100644 --- a/apps/cli/src/command/ingress-server.command.ts +++ b/apps/cli/src/command/ingress-server.command.ts @@ -1,9 +1,30 @@ +import commander from 'commander'; + import { ADCServer } from '../server'; -import { BaseCommand } from './helper'; +import { BaseCommand, BaseOptions } from './helper'; + +type IngressServerOptions = { + listen?: URL; +} & BaseOptions; -export const IngressServerCommand = new BaseCommand('server').handle( - async () => { - await new ADCServer().start(); - console.log('ADC server is running on: http://127.0.0.1:3000'); - }, -); +export const IngressServerCommand = new BaseCommand( + 'server', +) + .option( + '--listen ', + 'listen address of ADC server, the format is scheme://host:port', + (val) => { + try { + return new URL(val); + } catch (err) { + throw new commander.InvalidArgumentError(err); + } + }, + new URL('http://127.0.0.1:3000'), + ) + .handle(async ({ listen }) => { + await new ADCServer({ + listen, + }).start(); + console.log(`ADC server is running on: ${listen.origin}`); + }); diff --git a/apps/cli/src/server/index.ts b/apps/cli/src/server/index.ts index 54e93702..9c7b4f41 100644 --- a/apps/cli/src/server/index.ts +++ b/apps/cli/src/server/index.ts @@ -4,11 +4,16 @@ import type { Server } from 'node:http'; import { syncHandler } from './sync'; +interface ADCServerOptions { + listen: URL; +} export class ADCServer { private readonly express: Express; + private listen: URL; private server?: Server; - constructor() { + constructor(opts: ADCServerOptions) { + this.listen = opts.listen; this.express = express(); this.express.disable('x-powered-by'); this.express.use(express.json({ limit: '100mb' })); @@ -17,7 +22,21 @@ export class ADCServer { public async start() { return new Promise((resolve) => { - this.server = this.express.listen(3000, '127.0.0.1', () => resolve()); + this.server = this.express.listen( + parseInt(this.listen.port), + this.listen.hostname, + () => resolve(), + ); + }); + } + + public async stop() { + return new Promise((resolve) => { + if (this.server) { + this.server.close(() => resolve()); + } else { + resolve(); + } }); }