| // 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_core/flutter_tools_core.dart'; | |
| import 'base/io.dart'; | |
| import 'base/platform.dart'; | |
| import 'doctor_validator.dart'; | |
| /// A validator that displays configured HTTP_PROXY environment variables. | |
| /// | |
| /// if the `HTTP_PROXY` environment variable is non-empty, the contents are | |
| /// validated along with `NO_PROXY`. | |
| class ProxyValidator extends DoctorValidator { | |
| ProxyValidator({required Platform platform}) | |
| : shouldShow = _getEnv('HTTP_PROXY', platform).isNotEmpty, | |
| _httpProxy = _getEnv('HTTP_PROXY', platform), | |
| _noProxy = _getEnv('NO_PROXY', platform), | |
| super('Proxy Configuration'); | |
| final bool shouldShow; | |
| final String _httpProxy; | |
| final String _noProxy; | |
| /// Gets a trimmed, non-null environment variable. If the variable is not set | |
| /// an empty string will be returned. Checks for the lowercase version of the | |
| /// environment variable first, then uppercase to match Dart's HTTP implementation. | |
| static String _getEnv(String key, Platform platform) => | |
| platform.environment[key.toLowerCase()]?.trim() ?? | |
| platform.environment[key.toUpperCase()]?.trim() ?? | |
| ''; | |
| @override | |
| Future<ValidationResult> validateImpl() async { | |
| if (_httpProxy.isEmpty) { | |
| return ValidationResult(ValidationType.success, const <ValidationMessage>[]); | |
| } | |
| final messages = <ValidationMessage>[const ValidationMessage('HTTP_PROXY is set')]; | |
| if (_noProxy.isEmpty) { | |
| messages.add(const ValidationMessage.hint('NO_PROXY is not set')); | |
| } else { | |
| messages.add(ValidationMessage('NO_PROXY is $_noProxy')); | |
| final Set<String> proxyHosts = _noProxy.split(',').map((String e) => e.trim()).toSet(); | |
| final List<String> loopbackAddresses = await _getLoopbackAddresses(); | |
| for (final host in loopbackAddresses) { | |
| if (proxyHosts.contains(host)) { | |
| messages.add(ValidationMessage('NO_PROXY contains $host')); | |
| } else { | |
| messages.add(ValidationMessage.hint('NO_PROXY does not contain $host')); | |
| } | |
| } | |
| } | |
| final bool hasIssues = messages.any((ValidationMessage msg) => msg.isHint || msg.isError); | |
| return ValidationResult(hasIssues ? ValidationType.partial : ValidationType.success, messages); | |
| } | |
| Future<List<String>> _getLoopbackAddresses() async { | |
| final List<NetworkInterface> networkInterfaces = await listNetworkInterfaces( | |
| includeLinkLocal: true, | |
| includeLoopback: true, | |
| ); | |
| return <String>[ | |
| 'localhost', | |
| for (final NetworkInterface networkInterface in networkInterfaces) | |
| for (final InternetAddress internetAddress in networkInterface.addresses) | |
| if (internetAddress.isLoopback) internetAddress.address, | |
| ]; | |
| } | |
| } |