private static (HttpMessageHandler handler, Uri uri) ResolveHandlerAndUri(string baseUrl) { ManagedHandler handler; var uri = new Uri(baseUrl.Equals(".") ? DockerApiUri() : baseUrl); switch (uri.Scheme.ToLowerInvariant()) { case "npipe": var segments = uri.Segments; if (segments.Length != 3 || !segments[1].Equals("pipe/", StringComparison.OrdinalIgnoreCase)) { throw new ArgumentException($"{baseUrl} is not a valid npipe URI"); } var serverName = uri.Host; // npipe schemes dont work with npipe://localhost/... and need npipe://./... so fix that for a client here. serverName = string.Equals(serverName, "localhost", StringComparison.OrdinalIgnoreCase) ? "." : serverName; var pipeName = uri.Segments[2]; uri = new UriBuilder("http", pipeName).Uri; handler = new ManagedHandler(async(host, port, cancellationToken) => { var stream = new NamedPipeClientStream(serverName, pipeName, PipeDirection.InOut, PipeOptions.Asynchronous); var dockerStream = new DockerPipeStream(stream); await stream.ConnectAsync(100, cancellationToken); return(dockerStream); }); break; case "unix": handler = new ManagedHandler(async(string host, int port, CancellationToken cancellationToken) => { var sock = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified); await sock.ConnectAsync(new UnixDomainSocketEndPoint(uri.LocalPath), cancellationToken: cancellationToken); return(sock); }); uri = new UriBuilder("http", uri.Segments.Last()).Uri; break; default: throw new UnsupportedProtocolException(uri.Scheme); } return(handler, uri); }
internal DockerAPIClient(APIConfig config, Version apiVersion = null) { Config = config; requestedApiVersion = apiVersion; JsonSerializer = new JsonSerializer(); Images = new ImagesEndpoint(this); ManagedHandler handler; var uri = Config.Endpoint; switch (uri.Scheme.ToLowerInvariant()) { case "npipe": if (Config.Credentials.IsTlsEnabled()) { throw new Exception("TLS not supported over npipe"); } var segments = uri.Segments; if (segments.Length != 3 || !segments[1].Equals("pipe/", StringComparison.OrdinalIgnoreCase)) { throw new ArgumentException($"{Config.Endpoint} is not a valid npipe URI"); } var serverName = uri.Host; var pipeName = uri.Segments[2]; uri = new UriBuilder("http", pipeName).Uri; handler = new ManagedHandler(async(host, port, cancellationToken) => { // NamedPipeClientStream handles file not found by polling until the server arrives. Use a short // timeout so that the user doesn't get stuck waiting for a dockerd instance that is not running. var timeout = 100; // 100ms var stream = new NamedPipeClientStream(serverName, pipeName); var dockerStream = new DockerPipeStream(stream); await stream.ConnectAsync(timeout, cancellationToken); return(dockerStream); }); break; case "tcp": case "http": var builder = new UriBuilder(uri) { Scheme = config.Credentials.IsTlsEnabled() ? "https" : "http" }; uri = builder.Uri; handler = new ManagedHandler(); break; case "https": handler = new ManagedHandler(); break; case "unix": var pipeString = uri.LocalPath; handler = new ManagedHandler(async(string host, int port, CancellationToken cancellationToken) => { var sock = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified); await sock.ConnectAsync(new UnixDomainSocketEndPoint(pipeString)); return(sock); }); uri = new UriBuilder("http", uri.Segments.Last()).Uri; break; default: throw new Exception($"Unknown URL scheme {config.Endpoint.Scheme}"); } endpointBaseUri = uri; client = new HttpClient(Config.Credentials.GetHandler(handler), true); defaultTimeout = client.Timeout; client.Timeout = s_InfiniteTimeout; }