Skip to content

Commit 0ce9f70

Browse files
committed
feat(core): ingress server listen on https and uds http
1 parent 7a6ab5a commit 0ce9f70

File tree

3 files changed

+113
-21
lines changed

3 files changed

+113
-21
lines changed

apps/cli/src/command/helper.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,6 @@ export class BackendCommand<
8888
}
8989

9090
private addBackendOptions() {
91-
const processCertificateFile = (value: string, err: string) => {
92-
const path = resolve(value);
93-
if (!existsSync(path)) throw new Error(err);
94-
return path;
95-
};
96-
9791
const parseResourceTypeFilter = (
9892
cv: ADCSDK.ResourceType,
9993
pv: Array<string> = [],
@@ -217,6 +211,11 @@ export class BackendCommand<
217211
}
218212
}
219213

214+
export const processCertificateFile = (value: string, err: string) => {
215+
const path = resolve(value);
216+
if (!existsSync(path)) throw new InvalidArgumentError(err);
217+
return path;
218+
};
220219
export const NoLintOption = new Option('--no-lint', 'disable lint check');
221220
export const RequestConcurrentOption = new Option(
222221
'--request-concurrent <integer>',

apps/cli/src/command/ingress-server.command.ts

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
import commander from 'commander';
1+
import chalk from 'chalk';
2+
import commander, { Option } from 'commander';
3+
import { readFileSync } from 'node:fs';
24

35
import { ADCServer } from '../server';
4-
import { BaseCommand, BaseOptions } from './helper';
6+
import { BaseCommand, BaseOptions, processCertificateFile } from './helper';
57

68
type IngressServerOptions = {
79
listen?: URL;
10+
caCertFile?: string;
11+
tlsCertFile?: string;
12+
tlsKeyFile?: string;
813
} & BaseOptions;
914

1015
export const IngressServerCommand = new BaseCommand<IngressServerOptions>(
@@ -22,9 +27,61 @@ export const IngressServerCommand = new BaseCommand<IngressServerOptions>(
2227
},
2328
new URL('http://127.0.0.1:3000'),
2429
)
25-
.handle(async ({ listen }) => {
26-
await new ADCServer({
30+
.addOption(
31+
new Option(
32+
'--ca-cert-file <string>',
33+
'path to the CA certificate to verify the client',
34+
).argParser((value) =>
35+
processCertificateFile(
36+
value,
37+
'The specified CA certificate file does not exist',
38+
),
39+
),
40+
)
41+
.addOption(
42+
new Option(
43+
'--tls-cert-file <string>',
44+
'path to the TLS server certificate',
45+
).argParser((value) =>
46+
processCertificateFile(
47+
value,
48+
'The specified TLS server certificate file does not exist',
49+
),
50+
),
51+
)
52+
.addOption(
53+
new Option(
54+
'--tls-key-file <string>',
55+
'path to the TLS server key',
56+
).argParser((value) =>
57+
processCertificateFile(
58+
value,
59+
'The specified TLS server key file does not exist',
60+
),
61+
),
62+
)
63+
.handle(async ({ listen, tlsCertFile, tlsKeyFile, caCertFile }) => {
64+
if (listen.protocol === 'https:' && (!tlsCertFile || !tlsKeyFile)) {
65+
console.error(
66+
chalk.red(
67+
'Error: When using HTTPS, both --tls-cert-file and --tls-key-file must be provided',
68+
),
69+
);
70+
return;
71+
}
72+
73+
const server = new ADCServer({
2774
listen,
28-
}).start();
29-
console.log(`ADC server is running on: ${listen.origin}`);
75+
tlsCert: readFileSync(tlsCertFile, 'utf-8'),
76+
tlsKey: readFileSync(tlsKeyFile, 'utf-8'),
77+
tlsCACert: caCertFile ? readFileSync(caCertFile, 'utf-8') : undefined,
78+
});
79+
await server.start();
80+
console.log(
81+
`ADC server is running on: ${listen.protocol === 'unix:' ? listen.pathname : listen.origin}`,
82+
);
83+
process.on('SIGINT', () => {
84+
console.log('Stopping, see you next time!');
85+
server.stop();
86+
});
3087
});

apps/cli/src/server/index.ts

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,68 @@
11
import express from 'express';
22
import type { Express } from 'express';
3-
import type { Server } from 'node:http';
3+
import * as fs from 'node:fs';
4+
import * as http from 'node:http';
5+
import * as https from 'node:https';
46

57
import { syncHandler } from './sync';
68

79
interface ADCServerOptions {
810
listen: URL;
11+
tlsCert?: string;
12+
tlsKey?: string;
13+
tlsCACert?: string;
914
}
1015
export class ADCServer {
16+
private readonly opts: ADCServerOptions;
1117
private readonly express: Express;
12-
private listen: URL;
13-
private server?: Server;
18+
//private listen: URL;
19+
private server?: http.Server | https.Server;
1420

1521
constructor(opts: ADCServerOptions) {
16-
this.listen = opts.listen;
22+
this.opts = opts;
1723
this.express = express();
1824
this.express.disable('x-powered-by');
1925
this.express.use(express.json({ limit: '100mb' }));
2026
this.express.put('/sync', syncHandler);
2127
}
2228

2329
public async start() {
30+
switch (this.opts.listen.protocol) {
31+
case 'https:':
32+
this.server = https.createServer(
33+
{
34+
cert: this.opts.tlsCert,
35+
key: this.opts.tlsKey,
36+
...(this.opts.tlsCACert
37+
? {
38+
ca: this.opts.tlsCACert,
39+
requestCert: true,
40+
rejectUnauthorized: true,
41+
}
42+
: {}),
43+
},
44+
this.express,
45+
);
46+
break;
47+
case 'http:':
48+
case 'unix:':
49+
default:
50+
this.server = http.createServer(this.express);
51+
break;
52+
}
2453
return new Promise<void>((resolve) => {
25-
this.server = this.express.listen(
26-
parseInt(this.listen.port),
27-
this.listen.hostname,
28-
() => resolve(),
29-
);
54+
const listen = this.opts.listen;
55+
if (listen.protocol === 'unix:') {
56+
if (fs.existsSync(listen.pathname)) fs.unlinkSync(listen.pathname);
57+
this.server.listen(listen.pathname, () => {
58+
fs.chmodSync(listen.pathname, 0o660);
59+
resolve();
60+
});
61+
} else {
62+
this.server.listen(parseInt(listen.port), listen.hostname, () =>
63+
resolve(),
64+
);
65+
}
3066
});
3167
}
3268

0 commit comments

Comments
 (0)