// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

/// @assertion String findProxyFromEnvironment(
///  Uri url, {
///  Map<String, String> environment
///  })
/// Function for resolving the proxy server to be used for an HTTP connection from
/// the proxy configuration specified through environment variables.
///
/// The following environment variables are taken into account:
///
/// http_proxy
/// https_proxy
/// no_proxy
/// HTTP_PROXY
/// HTTPS_PROXY
/// NO_PROXY
/// http_proxy and HTTP_PROXY specify the proxy server to use for http:// urls.
/// Use the format hostname:port. If no port is used a default of 1080 will be
/// used. If both are set the lower case one takes precedence.
///
/// https_proxy and HTTPS_PROXY specify the proxy server to use for https://
/// urls. Use the format hostname:port. If no port is used a default of 1080 will
/// be used. If both are set the lower case one takes precedence.
///
/// no_proxy and NO_PROXY specify a comma separated list of postfixes of
/// hostnames for which not to use the proxy server. E.g. the value
/// "localhost,127.0.0.1" will make requests to both "localhost" and "127.0.0.1"
/// not use a proxy. If both are set the lower case one takes precedence.
///
/// To activate this way of resolving proxies assign this function to the
/// findProxy property on the HttpClient.
///
/// HttpClient client = new HttpClient();
/// client.findProxy = HttpClient.findProxyFromEnvironment;
/// If you don't want to use the system environment you can use a different one
/// by wrapping the function.
///
/// HttpClient client = new HttpClient();
/// client.findProxy = (url) {
///   return HttpClient.findProxyFromEnvironment(
///     url, {"http_proxy": ..., "no_proxy": ...});
///   }
/// If a proxy requires authentication it is possible to configure the username
/// and password as well. Use the format username:password@hostname:port to
/// include the username and password. Alternatively the API addProxyCredentials
/// can be used to set credentials for proxies which require authentication.
///
/// @description Checks that if no port specified the default value 1080 is used
/// @author sgrekhov@unipro.ru

import "dart:io";
import "dart:convert";
import "../../../Utils/expect.dart";

var localhost = InternetAddress.loopbackIPv4.address;

test() async {
  bool findProxyCalled = false;
  String hello = "Hello world!";
  HttpServer server = await HttpServer.bind(localhost, 1080);
  server.listen((HttpRequest request) {
    Expect.isTrue(findProxyCalled);
    request.response.close();
    server.close();
    asyncEnd();
  });

  HttpClient client = new HttpClient();
  client.findProxy = (Uri url) {
    findProxyCalled = true;
    return HttpClient.findProxyFromEnvironment(url,
        environment: {"http_proxy": localhost});
  };

  client.get(localhost, server.port, "")
      .then((HttpClientRequest request) => request.close())
      .then((HttpClientResponse response) {
    response.cast<List<int>>().transform(utf8.decoder).listen((content) {
      Expect.equals(hello, content);
    });
  });
}

main() {
  asyncStart();
  test();
}
