Skip to content

Commit ba414ab

Browse files
sbaramovBrocco
authored andcommitted
feat(ssl): add support for the ssl options of the ng serve task: --ssl, --ssl-cert, and --ssl-key (#2792)
1 parent e844706 commit ba414ab

File tree

7 files changed

+115
-4
lines changed

7 files changed

+115
-4
lines changed

packages/angular-cli/custom-typings.d.ts

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ interface IWebpackDevServerConfigurationOptions {
1717
headers?: { [key: string]: string };
1818
stats?: { [key: string]: boolean };
1919
inline: boolean;
20+
https?: boolean;
21+
key?: string;
22+
cert?: string;
2023
}
2124

2225
interface WebpackProgressPluginOutputOptions {

packages/angular-cli/tasks/serve-webpack.ts

+21-2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,19 @@ export default Task.extend({
5252
}
5353
}
5454

55+
let sslKey: string = null;
56+
let sslCert: string = null;
57+
if (commandOptions.ssl) {
58+
const keyPath = path.resolve(this.project.root, commandOptions.sslKey);
59+
if (fs.existsSync(keyPath)) {
60+
sslKey = fs.readFileSync(keyPath, 'utf-8');
61+
}
62+
const certPath = path.resolve(this.project.root, commandOptions.sslCert);
63+
if (fs.existsSync(certPath)) {
64+
sslCert = fs.readFileSync(certPath, 'utf-8');
65+
}
66+
}
67+
5568
const webpackDevServerConfiguration: IWebpackDevServerConfigurationOptions = {
5669
contentBase: path.resolve(
5770
this.project.root,
@@ -66,13 +79,19 @@ export default Task.extend({
6679
compress: commandOptions.target === 'production',
6780
watchOptions: {
6881
poll: CliConfig.fromProject().config.defaults.poll
69-
}
82+
},
83+
https: commandOptions.ssl
7084
};
7185

86+
if (sslKey != null && sslCert != null) {
87+
webpackDevServerConfiguration.key = sslKey;
88+
webpackDevServerConfiguration.cert = sslCert;
89+
}
90+
7291
ui.writeLine(chalk.green(oneLine`
7392
**
7493
NG Live Development Server is running on
75-
http://${commandOptions.host}:${commandOptions.port}.
94+
http${commandOptions.ssl ? 's' : ''}://${commandOptions.host}:${commandOptions.port}.
7695
**
7796
`));
7897

tests/e2e/assets/ssl/server.crt

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIID5jCCAs6gAwIBAgIJAJOebwfGCm61MA0GCSqGSIb3DQEBBQUAMFUxCzAJBgNV
3+
BAYTAlVTMRAwDgYDVQQIEwdHZW9yZ2lhMRAwDgYDVQQHEwdBdGxhbnRhMRAwDgYD
4+
VQQKEwdBbmd1bGFyMRAwDgYDVQQLEwdBbmd1bGFyMB4XDTE2MTAwNDAxMDAyMVoX
5+
DTI2MTAwMjAxMDAyMVowVTELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0dlb3JnaWEx
6+
EDAOBgNVBAcTB0F0bGFudGExEDAOBgNVBAoTB0FuZ3VsYXIxEDAOBgNVBAsTB0Fu
7+
Z3VsYXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDT6Q4d1+mw81SC
8+
4K1qLbsMn4O459XDiDDU/cGBiE0byqi6RpaB0MujCPn35xdeCf1mdDw929leEIRB
9+
w/fCN3VwE+4ZDM7sF6SgoSDN8YT/OOush4tDu0djH110I+i1Bfg4m7gVkUnJLUCv
10+
vMMOlD19LDqqaxdY3ojXx8gZJW9sNtUH2vCICwsZ7aNZp2NcCNKpU7LppP4IomCd
11+
GfG501kY/UtELVgNGX+zuJwIiH/2AQZ+fsaDBBD0Azanck2M/aq5yVKMG8y/S5WP
12+
7LMvZs8ZHPSG73QINogRTYW0EKx7nT87vmrHRtCc9u4coPdqOzQN9BigCYVkYrTv
13+
xkOX9VDHAgMBAAGjgbgwgbUwHQYDVR0OBBYEFG4VV6/aNLx/qFIS9MhAWuyeV5OX
14+
MIGFBgNVHSMEfjB8gBRuFVev2jS8f6hSEvTIQFrsnleTl6FZpFcwVTELMAkGA1UE
15+
BhMCVVMxEDAOBgNVBAgTB0dlb3JnaWExEDAOBgNVBAcTB0F0bGFudGExEDAOBgNV
16+
BAoTB0FuZ3VsYXIxEDAOBgNVBAsTB0FuZ3VsYXKCCQCTnm8HxgputTAMBgNVHRME
17+
BTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQDO4jZT/oKVxaiWr+jV5TD+qwThl9zT
18+
Uw/ZpFDkdbZdY/baCFaLCiJwkK9+puMOabLvm1VzcnHHWCoiUNbWpw8AOumLEnTv
19+
ze/5OZXJ6XlA9kd9f3hDlN5zNB3S+Z2nKIrkPGfxQZ603QCbWaptip5dxgek6oDZ
20+
YXVtnbOnPznRsG5jh07U49RO8CNebqZLzdRToLgObbqYlfRMcbUxCOHXjnB5wUlp
21+
377Iivm4ldnCTvFOjEiDh+FByWL5xic7PjyJPZFMidiYTmsGilP9XTFC83CRZwz7
22+
vW+RCSlU6x8Uejz98BPmASoqCuCTUeOo+2pFelFhX9NwR/Sb6b7ybdPv
23+
-----END CERTIFICATE-----

tests/e2e/assets/ssl/server.key

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIIEpAIBAAKCAQEA0+kOHdfpsPNUguCtai27DJ+DuOfVw4gw1P3BgYhNG8qoukaW
3+
gdDLowj59+cXXgn9ZnQ8PdvZXhCEQcP3wjd1cBPuGQzO7BekoKEgzfGE/zjrrIeL
4+
Q7tHYx9ddCPotQX4OJu4FZFJyS1Ar7zDDpQ9fSw6qmsXWN6I18fIGSVvbDbVB9rw
5+
iAsLGe2jWadjXAjSqVOy6aT+CKJgnRnxudNZGP1LRC1YDRl/s7icCIh/9gEGfn7G
6+
gwQQ9AM2p3JNjP2quclSjBvMv0uVj+yzL2bPGRz0hu90CDaIEU2FtBCse50/O75q
7+
x0bQnPbuHKD3ajs0DfQYoAmFZGK078ZDl/VQxwIDAQABAoIBAEl17kXcNo/4GqDw
8+
QE2hoslCdwhfnhQVn1AG09ESriBnRcylccF4308aaoVM4CXicqzUuJl9IEJimWav
9+
B7GVRinfTtfyP71KiPCCSvv5sPBFDDYYGugVAS9UjTIYzLAMbLs7CDq5zglmnZkO
10+
Z9QjAZnl/kRbsZFGO8wJ3s0Q1Cp/ygZcvFU331K2jHXW7B4YXiFOH/lBQrjdz0Gy
11+
WBjX4zIdNWnwarvxu46IS/0z1P1YOHM8+B1Uv54MG94A6szBdd/Vp0cQRs78t/Cu
12+
BQ1Rnuk16Pi+ieC5K04yUgeuNusYW0PWLtPX1nKNp9z46bmD1NHKAxaoDFXr7qP3
13+
pZCaDMkCgYEA8mmTYrhXJTRIrOxoUwM1e3OZ0uOxVXJJ8HF6X8t+UO6dFxXB/JC9
14+
ZBc+94cZQapaKFOeMmd/j3L2CQIjChk5yKV/G3Io+raxIoAAKPCkMF4NQQVvvNkS
15+
CAGl61Qa78DoF5Habumz0AC1R9P877kNTC0aPSt4lhPWgfotbZNNMlMCgYEA38nM
16+
s4a0pZseXPkuOtPYX/3Ms3E+d70XKSFuIMCHCg79YGsQ8h/9apYcPyeYkpQ0a4gs
17+
I3IUqMaXC2OyqWA5LU1BZv51mXb6zcb2pokZfpiSWk+7sy5XjkE9EmQxp3xHfV3c
18+
EO/DxHfWNvtMjESMbhu0yVzM2O/Aa53Tl9lqAT0CgYEA1dXBuHyqCtyTG08zO78B
19+
55Ny5rAJ1zkI9jvz2hr0o0nJcvqzcyruliNXXRxkcCNoglg4nXfk81JSrGGhLSBR
20+
c6hhdoF+mqKboLZO7c5Q14WvpWK5TVoiaMOja/J2DHYbhecYS2yGPH7TargaUBDq
21+
JP9IPRtitOhs+Z0Jg7ZDi5cCgYAMb7B6gY/kbBxh2k8hYchyfS41AqQQD2gMFxmB
22+
pHFcs7yM8SY97l0s4S6sq8ykyKupFiYtyhcv0elu7pltJDXJOLPbv2RVpPEHInlu
23+
g8vw5xWrAydRK9Adza5RKVRBFHz8kIy8PDbK4kX7RDfay6xqKgv/7LJNk/VDhb/O
24+
fnyPmQKBgQDg/o8Ubf/gxA9Husnuld4DBu3wwFhkMlWqyO9QH3cKgojQ2JGSrfDz
25+
xHhetmhionEyzg0JCaMSpzgIHY+8o/NAwc++OjNHEoYp3XWM9GTp81ROMz6b83jV
26+
biVR9N0MhONdwF6vtzDCcJxNIUe2p4lTvLf/Xd9jaQDNXe35Gxsdyg==
27+
-----END RSA PRIVATE KEY-----

tests/e2e/tests/misc/ssl-default.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { request } from '../../utils/http';
2+
import { killAllProcesses } from '../../utils/process';
3+
import { ngServe } from '../../utils/project';
4+
5+
6+
export default function() {
7+
return Promise.resolve()
8+
.then(() => ngServe('--ssl', 'true'))
9+
.then(() => request('https://localhost:4200/'))
10+
.then(body => {
11+
if (!body.match(/<app-root>Loading...<\/app-root>/)) {
12+
throw new Error('Response does not match expected value.');
13+
}
14+
})
15+
.then(() => killAllProcesses(), (err) => { killAllProcesses(); throw err; });
16+
}

tests/e2e/tests/misc/ssl-with-cert.ts

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { request } from '../../utils/http';
2+
import { assetDir } from '../../utils/assets';
3+
import { killAllProcesses } from '../../utils/process';
4+
import { ngServe } from '../../utils/project';
5+
6+
7+
export default function() {
8+
return Promise.resolve()
9+
.then(() => ngServe(
10+
'--ssl', 'true',
11+
'--ssl-key', assetDir('ssl/server.key'),
12+
'--ssl-cert', assetDir('ssl/server.crt')
13+
))
14+
.then(() => request('https://localhost:4200/'))
15+
.then(body => {
16+
if (!body.match(/<app-root>Loading...<\/app-root>/)) {
17+
throw new Error('Response does not match expected value.');
18+
}
19+
})
20+
.then(() => killAllProcesses(), (err) => { killAllProcesses(); throw err; });
21+
22+
}

tests/e2e/utils/http.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ import * as _request from 'request';
44

55
export function request(url: string): Promise<string> {
66
return new Promise((resolve, reject) => {
7-
_request(url, (error: any, response: IncomingMessage, body: string) => {
7+
let options = { url: url, agentOptions: { rejectUnauthorized: false }};
8+
_request(options, (error: any, response: IncomingMessage, body: string) => {
89
if (error) {
910
reject(error);
1011
} else if (response.statusCode >= 400) {
11-
reject(new Error(`Requesting "${url}" returned status code ${response.statusCode}.`);
12+
reject(new Error(`Requesting "${url}" returned status code ${response.statusCode}.`));
1213
} else {
1314
resolve(body);
1415
}

0 commit comments

Comments
 (0)