mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[tool] clean up https cert configuration handling (#178139)
It's only valid if both the cert and the cert key are set. Makes the code a lot cleaner, too.
This commit is contained in:
parent
d48aa42950
commit
017e4f00fa
@ -1374,13 +1374,7 @@ class DebuggingOptions {
|
||||
webDevServerConfig: WebDevServerConfig(
|
||||
port: json['port'] is int ? json['port']! as int : 8080,
|
||||
host: json['hostname'] is String ? json['hostname']! as String : 'localhost',
|
||||
|
||||
https: (json['tlsCertPath'] != null || json['tlsCertKeyPath'] != null)
|
||||
? HttpsConfig(
|
||||
certPath: json['tlsCertPath'] as String?,
|
||||
certKeyPath: json['tlsCertKeyPath'] as String?,
|
||||
)
|
||||
: null,
|
||||
https: HttpsConfig.parse(json['tlsCertPath'], json['tlsCertKeyPath']),
|
||||
headers: (json['webHeaders']! as Map<dynamic, dynamic>).cast<String, String>(),
|
||||
),
|
||||
);
|
||||
|
||||
@ -197,8 +197,7 @@ class WebAssetServer implements AssetReader {
|
||||
}) async {
|
||||
final String hostname = webDevServerConfig.host;
|
||||
final int port = webDevServerConfig.port;
|
||||
final String? tlsCertPath = webDevServerConfig.https?.certPath;
|
||||
final String? tlsCertKeyPath = webDevServerConfig.https?.certKeyPath;
|
||||
final HttpsConfig? httpsConfig = webDevServerConfig.https;
|
||||
final Map<String, String> extraHeaders = webDevServerConfig.headers;
|
||||
final List<ProxyRule> proxy = webDevServerConfig.proxy;
|
||||
|
||||
@ -217,10 +216,10 @@ class WebAssetServer implements AssetReader {
|
||||
const kMaxRetries = 4;
|
||||
for (var i = 0; i <= kMaxRetries; i++) {
|
||||
try {
|
||||
if (tlsCertPath != null && tlsCertKeyPath != null) {
|
||||
if (httpsConfig != null) {
|
||||
final serverContext = SecurityContext()
|
||||
..useCertificateChain(tlsCertPath)
|
||||
..usePrivateKey(tlsCertKeyPath);
|
||||
..useCertificateChain(httpsConfig.certPath)
|
||||
..usePrivateKey(httpsConfig.certKeyPath);
|
||||
httpServer = await HttpServer.bindSecure(address, port, serverContext);
|
||||
} else {
|
||||
httpServer = await HttpServer.bind(address, port);
|
||||
@ -260,7 +259,7 @@ class WebAssetServer implements AssetReader {
|
||||
final int selectedPort = server.selectedPort;
|
||||
|
||||
final cleanHost = hostname == webDevAnyHostDefault ? 'localhost' : hostname;
|
||||
final scheme = tlsCertPath != null && tlsCertKeyPath != null ? 'https' : 'http';
|
||||
final scheme = httpsConfig != null ? 'https' : 'http';
|
||||
server._baseUri = Uri(
|
||||
scheme: scheme,
|
||||
host: cleanHost,
|
||||
|
||||
@ -189,28 +189,51 @@ WebDevServerConfig:
|
||||
/// Represents the [HttpsConfig] for the web dev server
|
||||
@immutable
|
||||
class HttpsConfig {
|
||||
const HttpsConfig({this.certPath, this.certKeyPath});
|
||||
|
||||
const HttpsConfig({required this.certPath, required this.certKeyPath});
|
||||
factory HttpsConfig.fromYaml(YamlMap yaml) {
|
||||
final String? certPath = _validateType<String>(value: yaml[_kCertPath], fieldName: _kCertPath);
|
||||
if (certPath == null) {
|
||||
throw ArgumentError.value(yaml, 'yaml', '"$_kCertPath" must be defined');
|
||||
}
|
||||
|
||||
final String? certKeyPath = _validateType<String>(
|
||||
value: yaml[_kCertKeyPath],
|
||||
fieldName: _kCertKeyPath,
|
||||
);
|
||||
if (certKeyPath == null) {
|
||||
throw ArgumentError.value(yaml, 'yaml', '"$_kCertKeyPath" must be defined');
|
||||
}
|
||||
|
||||
return HttpsConfig(certPath: certPath, certKeyPath: certKeyPath);
|
||||
}
|
||||
|
||||
/// Creates a copy of this [HttpsConfig] with optional overrides.
|
||||
HttpsConfig copyWith({String? certPath, String? certKeyPath}) {
|
||||
return HttpsConfig(
|
||||
certPath: certPath ?? this.certPath,
|
||||
certKeyPath: certKeyPath ?? this.certKeyPath,
|
||||
);
|
||||
}
|
||||
/// If [tlsCertPath] and [tlsCertKeyPath] are both [String] return an instance.
|
||||
///
|
||||
/// If they are both `null`, return `null`.
|
||||
///
|
||||
/// Otherwise, throw an [Exception].
|
||||
static HttpsConfig? parse(Object? tlsCertPath, Object? tlsCertKeyPath) =>
|
||||
switch ((tlsCertPath, tlsCertKeyPath)) {
|
||||
(final String certPath, final String certKeyPath) => HttpsConfig(
|
||||
certPath: certPath,
|
||||
certKeyPath: certKeyPath,
|
||||
),
|
||||
(null, null) => null,
|
||||
(final Object? certPath, final Object? certKeyPath) => throw ArgumentError(
|
||||
'When providing TLS certificates, both `tlsCertPath` and '
|
||||
'`tlsCertKeyPath` must be provided as strings. '
|
||||
'Found: tlsCertPath: ${certPath ?? 'null'}, tlsCertKeyPath: ${certKeyPath ?? 'null'}',
|
||||
),
|
||||
};
|
||||
|
||||
final String? certPath;
|
||||
final String? certKeyPath;
|
||||
/// Creates a copy of this [HttpsConfig] with optional overrides.
|
||||
HttpsConfig copyWith({String? certPath, String? certKeyPath}) => HttpsConfig(
|
||||
certPath: certPath ?? this.certPath,
|
||||
certKeyPath: certKeyPath ?? this.certKeyPath,
|
||||
);
|
||||
|
||||
final String certPath;
|
||||
final String certKeyPath;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
|
||||
@ -0,0 +1,63 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter_tools/src/web/devfs_config.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:yaml/yaml.dart';
|
||||
|
||||
void main() {
|
||||
group('parse', () {
|
||||
test('returns HttpsConfig when both paths are provided', () {
|
||||
final HttpsConfig result = HttpsConfig.parse('/path/to/cert', '/path/to/key')!;
|
||||
expect(result.certPath, '/path/to/cert');
|
||||
expect(result.certKeyPath, '/path/to/key');
|
||||
});
|
||||
|
||||
test('returns null when both paths are null', () {
|
||||
final HttpsConfig? result = HttpsConfig.parse(null, null);
|
||||
expect(result, isNull);
|
||||
});
|
||||
|
||||
test('throws ArgumentError when only one field is provided', () {
|
||||
expect(() => HttpsConfig.parse('/path/to/cert', null), throwsArgumentError);
|
||||
expect(() => HttpsConfig.parse(null, '/path/to/key'), throwsArgumentError);
|
||||
});
|
||||
|
||||
test('throws ArgumentError when the field is the wrong type', () {
|
||||
expect(() => HttpsConfig.parse(1, '/path/to/key'), throwsArgumentError);
|
||||
expect(() => HttpsConfig.parse('/path/to/cert', 1), throwsArgumentError);
|
||||
});
|
||||
});
|
||||
|
||||
group('fromYaml', () {
|
||||
test('fromYaml throws an ArgumentError if cert-path is not defined', () {
|
||||
expect(
|
||||
() => HttpsConfig.fromYaml(loadYaml('cert-key-path: /path/to/key') as YamlMap),
|
||||
throwsArgumentError,
|
||||
);
|
||||
});
|
||||
|
||||
test('fromYaml throws an ArgumentError if cert-key-path is not defined', () {
|
||||
expect(
|
||||
() => HttpsConfig.fromYaml(loadYaml('cert-path: /path/to/cert') as YamlMap),
|
||||
throwsArgumentError,
|
||||
);
|
||||
});
|
||||
|
||||
test(
|
||||
'fromYaml creates an HttpsConfig object when both certificate and key paths are provided',
|
||||
() {
|
||||
final https = HttpsConfig.fromYaml(
|
||||
loadYaml('''
|
||||
cert-path: /path/to/cert
|
||||
cert-key-path: /path/to/key''')
|
||||
as YamlMap,
|
||||
);
|
||||
|
||||
expect(https.certPath, '/path/to/cert');
|
||||
expect(https.certKeyPath, '/path/to/key');
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user