_HttpClientRequest send()

in lib/src/http_impl.dart [1566:1686]


  _HttpClientRequest send(Uri uri, int port, String method, _Proxy proxy) {
    if (closed) {
      throw HttpException("Socket closed before request was sent", uri: uri);
    }
    _currentUri = uri;
    // Start with pausing the parser.
    _subscription.pause();
    _ProxyCredentials proxyCreds; // Credentials used to authorize proxy.
    _SiteCredentials creds; // Credentials used to authorize this request.
    var outgoing = _HttpOutgoing(_socket);
    // Create new request object, wrapping the outgoing connection.
    var request =
        _HttpClientRequest(outgoing, uri, method, proxy, _httpClient, this);
    // For the Host header an IPv6 address must be enclosed in []'s.
    var host = uri.host;
    if (host.contains(':')) host = "[$host]";
    request.headers
      ..host = host
      ..port = port
      ..add(HttpHeaders.ACCEPT_ENCODING, "gzip");
    if (_httpClient.userAgent != null) {
      request.headers.add('user-agent', _httpClient.userAgent);
    }
    if (proxy.isAuthenticated) {
      // If the proxy configuration contains user information use that
      // for proxy basic authorization.
      String auth = CryptoUtils.bytesToBase64(
          utf8.encode("${proxy.username}:${proxy.password}"));
      request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth");
    } else if (!proxy.isDirect && _httpClient._proxyCredentials.isNotEmpty) {
      proxyCreds = _httpClient._findProxyCredentials(proxy);
      if (proxyCreds != null) {
        proxyCreds.authorize(request);
      }
    }
    if (uri.userInfo != null && uri.userInfo.isNotEmpty) {
      // If the URL contains user information use that for basic
      // authorization.
      String auth = CryptoUtils.bytesToBase64(utf8.encode(uri.userInfo));
      request.headers.set(HttpHeaders.AUTHORIZATION, "Basic $auth");
    } else {
      // Look for credentials.
      creds = _httpClient._findCredentials(uri);
      if (creds != null) {
        creds.authorize(request);
      }
    }
    // Start sending the request (lazy, delayed until the user provides
    // data).
    _httpParser.isHead = method == "HEAD";
    _streamFuture = outgoing.done.then<Socket>((Socket s) {
      // Request sent, set up response completer.
      _nextResponseCompleter = Completer<HttpIncoming>();

      // Listen for response.
      _nextResponseCompleter.future.then((incoming) {
        _currentUri = null;
        incoming.dataDone.then((closing) {
          if (incoming.upgraded) {
            _httpClient._connectionClosed(this);
            startTimer();
            return;
          }
          if (closed) return;
          if (!closing &&
              !_dispose &&
              incoming.headers.persistentConnection &&
              request.persistentConnection) {
            // Return connection, now we are done.
            _httpClient._returnConnection(this);
            _subscription.resume();
          } else {
            destroy();
          }
        });
        // For digest authentication if proxy check if the proxy
        // requests the client to start using a new nonce for proxy
        // authentication.
        if (proxyCreds != null &&
            proxyCreds.scheme == _AuthenticationScheme.DIGEST) {
          var authInfo = incoming.headers["proxy-authentication-info"];
          if (authInfo != null && authInfo.length == 1) {
            var header =
                HeaderValueImpl.parse(authInfo[0], parameterSeparator: ',');
            var nextnonce = header.parameters["nextnonce"];
            if (nextnonce != null) proxyCreds.nonce = nextnonce;
          }
        }
        // For digest authentication check if the server requests the
        // client to start using a new nonce.
        if (creds != null && creds.scheme == _AuthenticationScheme.DIGEST) {
          var authInfo = incoming.headers["authentication-info"];
          if (authInfo != null && authInfo.length == 1) {
            var header =
                HeaderValueImpl.parse(authInfo[0], parameterSeparator: ',');
            var nextnonce = header.parameters["nextnonce"];
            if (nextnonce != null) creds.nonce = nextnonce;
          }
        }
        request._onIncoming(incoming);
      })
          // If we see a state error, we failed to get the 'first'
          // element.
          .catchError((error) {
        throw HttpException("Connection closed before data was received",
            uri: uri);
      }, test: (error) => error is StateError).catchError(
              (error, StackTrace stackTrace) {
        // We are done with the socket.
        destroy();
        request._onError(error, stackTrace);
      });

      // Resume the parser now we have a handler.
      _subscription.resume();
      return s;
    }, onError: (e) {
      destroy();
    });
    return request;
  }