mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

* [tools]some ui polish for build ipa validation * do not print out a few success validations * rename installed type to success for more general usage * forgot nit after reverting custom validation types and re-use doctor types
144 lines
6.3 KiB
Dart
144 lines
6.3 KiB
Dart
// 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 'dart:async';
|
|
|
|
import 'base/io.dart';
|
|
import 'base/platform.dart';
|
|
import 'doctor_validator.dart';
|
|
import 'features.dart';
|
|
|
|
// Overridable environment variables
|
|
const String kEnvPubHostedUrl = 'PUB_HOSTED_URL';
|
|
const String kEnvCloudUrl = 'FLUTTER_STORAGE_BASE_URL';
|
|
const String kDoctorHostTimeout = 'FLUTTER_DOCTOR_HOST_TIMEOUT';
|
|
|
|
/// Common Flutter HTTP hosts.
|
|
const String kPubDevHttpHost = 'https://pub.dev/';
|
|
const String kgCloudHttpHost = 'https://cloud.google.com/';
|
|
|
|
/// MacOS specific required HTTP hosts.
|
|
const List<String> macOSRequiredHttpHosts = <String>[
|
|
'https://cocoapods.org/',
|
|
];
|
|
|
|
/// Android specific required HTTP hosts.
|
|
List<String> androidRequiredHttpHosts(Platform platform) {
|
|
return <String>[
|
|
// If kEnvCloudUrl is set, it will be used as the maven host
|
|
if (!platform.environment.containsKey(kEnvCloudUrl))
|
|
'https://maven.google.com/',
|
|
];
|
|
}
|
|
|
|
// Validator that checks all provided hosts are reachable and responsive
|
|
class HttpHostValidator extends DoctorValidator {
|
|
HttpHostValidator({
|
|
required Platform platform,
|
|
required FeatureFlags featureFlags,
|
|
required HttpClient httpClient,
|
|
}) : _platform = platform,
|
|
_featureFlags = featureFlags,
|
|
_httpClient = httpClient,
|
|
super('HTTP Host Availability');
|
|
|
|
final Platform _platform;
|
|
final FeatureFlags _featureFlags;
|
|
final HttpClient _httpClient;
|
|
|
|
@override
|
|
String get slowWarning => 'HTTP Host availability check is taking a long time...';
|
|
|
|
List<String> get _requiredHosts => <String>[
|
|
if (_featureFlags.isMacOSEnabled) ...macOSRequiredHttpHosts,
|
|
if (_featureFlags.isAndroidEnabled) ...androidRequiredHttpHosts(_platform),
|
|
_platform.environment[kEnvPubHostedUrl] ?? kPubDevHttpHost,
|
|
_platform.environment[kEnvCloudUrl] ?? kgCloudHttpHost,
|
|
];
|
|
|
|
/// Make a head request to the HTTP host for checking availability
|
|
Future<_HostValidationResult> _checkHostAvailability(String host) async {
|
|
late final int timeout;
|
|
try {
|
|
timeout = int.parse(_platform.environment[kDoctorHostTimeout] ?? '10');
|
|
final HttpClientRequest req = await _httpClient.headUrl(Uri.parse(host));
|
|
await req.close().timeout(Duration(seconds: timeout));
|
|
// HTTP host is available if no exception happened
|
|
return _HostValidationResult.success(host);
|
|
} on TimeoutException {
|
|
return _HostValidationResult.fail(host, 'Failed to connect to host in $timeout second${timeout == 1 ? '': 's'}');
|
|
} on SocketException catch (e) {
|
|
return _HostValidationResult.fail(host, 'An error occurred while checking the HTTP host: ${e.message}');
|
|
} on HttpException catch (e) {
|
|
return _HostValidationResult.fail(host, 'An error occurred while checking the HTTP host: ${e.message}');
|
|
} on HandshakeException catch (e) {
|
|
return _HostValidationResult.fail(host, 'An error occurred while checking the HTTP host: ${e.message}');
|
|
} on OSError catch (e) {
|
|
return _HostValidationResult.fail(host, 'An error occurred while checking the HTTP host: ${e.message}');
|
|
} on FormatException catch (e) {
|
|
if (e.message.contains('Invalid radix-10 number')) {
|
|
return _HostValidationResult.fail(host, 'The value of $kDoctorHostTimeout(${_platform.environment[kDoctorHostTimeout]}) is not a valid duration in seconds');
|
|
} else if (e.message.contains('Invalid empty scheme')){
|
|
// Check if the invalid host is kEnvPubHostedUrl, else it must be kEnvCloudUrl
|
|
final String? pubHostedUrl = _platform.environment[kEnvPubHostedUrl];
|
|
if (pubHostedUrl != null && host == pubHostedUrl) {
|
|
return _HostValidationResult.fail(host, 'The value of $kEnvPubHostedUrl(${_platform.environment[kEnvPubHostedUrl]}) could not be parsed as a valid url');
|
|
}
|
|
return _HostValidationResult.fail(host, 'The value of $kEnvCloudUrl(${_platform.environment[kEnvCloudUrl]}) could not be parsed as a valid url');
|
|
}
|
|
return _HostValidationResult.fail(host, 'An error occurred while checking the HTTP host: ${e.message}');
|
|
} on ArgumentError catch (e) {
|
|
final String exceptionMessage = e.message.toString();
|
|
if (exceptionMessage.contains('No host specified')) {
|
|
// Check if the invalid host is kEnvPubHostedUrl, else it must be kEnvCloudUrl
|
|
final String? pubHostedUrl = _platform.environment[kEnvPubHostedUrl];
|
|
if (pubHostedUrl != null && host == pubHostedUrl) {
|
|
return _HostValidationResult.fail(host, 'The value of $kEnvPubHostedUrl(${_platform.environment[kEnvPubHostedUrl]}) is not a valid host');
|
|
}
|
|
return _HostValidationResult.fail(host, 'The value of $kEnvCloudUrl(${_platform.environment[kEnvCloudUrl]}) is not a valid host');
|
|
}
|
|
return _HostValidationResult.fail(host, 'An error occurred while checking the HTTP host: $exceptionMessage');
|
|
}
|
|
}
|
|
|
|
@override
|
|
Future<ValidationResult> validate() async {
|
|
final List<ValidationMessage> messages = <ValidationMessage>[];
|
|
final Iterable<Future<_HostValidationResult>> availabilityResultFutures = _requiredHosts.map(_checkHostAvailability);
|
|
final List<_HostValidationResult> availabilityResults = await Future.wait(availabilityResultFutures);
|
|
|
|
if (availabilityResults.every((_HostValidationResult result) => result.available)) {
|
|
return ValidationResult(
|
|
ValidationType.success,
|
|
messages..add(const ValidationMessage('All required HTTP hosts are available')),
|
|
);
|
|
}
|
|
|
|
availabilityResults.removeWhere((_HostValidationResult result) => result.available);
|
|
|
|
for (final _HostValidationResult result in availabilityResults) {
|
|
messages.add(ValidationMessage.error('HTTP host "${result.host}" is not reachable. Reason: ${result.failResultInfo}'));
|
|
}
|
|
|
|
return ValidationResult(
|
|
availabilityResults.length == _requiredHosts.length
|
|
? ValidationType.notAvailable
|
|
: ValidationType.partial,
|
|
messages,
|
|
);
|
|
}
|
|
}
|
|
|
|
class _HostValidationResult {
|
|
_HostValidationResult.success(this.host)
|
|
: failResultInfo = '',
|
|
available = true;
|
|
|
|
_HostValidationResult.fail(this.host, this.failResultInfo) : available = false;
|
|
|
|
final String failResultInfo;
|
|
final String host;
|
|
final bool available;
|
|
}
|