| | | 1 | | using System; |
| | | 2 | | using System.Collections.Generic; |
| | | 3 | | using System.Globalization; |
| | | 4 | | using System.Linq; |
| | | 5 | | using Grpc.Core; |
| | | 6 | | |
| | | 7 | | namespace dotnet_etcd; |
| | | 8 | | |
| | | 9 | | /// <summary> |
| | | 10 | | /// Handles parsing of connection strings for etcd client |
| | | 11 | | /// </summary> |
| | | 12 | | public class ConnectionStringParser |
| | | 13 | | { |
| | | 14 | | private const string InsecurePrefix = "http://"; |
| | | 15 | | private const string SecurePrefix = "https://"; |
| | | 16 | | private const string StaticHostsPrefix = "static://"; |
| | | 17 | | private const string DnsPrefix = "dns://"; |
| | | 18 | | private const string AlternateDnsPrefix = "discovery-srv://"; |
| | | 19 | | |
| | | 20 | | /// <summary> |
| | | 21 | | /// Parses a connection string and returns the appropriate URI and connection type |
| | | 22 | | /// </summary> |
| | | 23 | | /// <param name="connectionString">The connection string to parse</param> |
| | | 24 | | /// <param name="port">The port to use if not specified in the connection string</param> |
| | | 25 | | /// <param name="credentials">The credentials to use for the connection</param> |
| | | 26 | | /// <returns>A tuple containing the parsed URI and whether it's a DNS connection</returns> |
| | | 27 | | public (Uri[] Uris, bool IsDnsConnection) ParseConnectionString(string connectionString, int port, ChannelCredential |
| | 22 | 28 | | { |
| | 22 | 29 | | if (string.IsNullOrWhiteSpace(connectionString)) |
| | 2 | 30 | | { |
| | 2 | 31 | | throw new ArgumentNullException(nameof(connectionString)); |
| | | 32 | | } |
| | | 33 | | |
| | 20 | 34 | | if (connectionString.StartsWith(AlternateDnsPrefix, StringComparison.InvariantCultureIgnoreCase)) |
| | 1 | 35 | | { |
| | 1 | 36 | | connectionString = connectionString.Substring(AlternateDnsPrefix.Length); |
| | 1 | 37 | | connectionString = DnsPrefix + connectionString; |
| | 1 | 38 | | } |
| | | 39 | | |
| | 20 | 40 | | if (connectionString.StartsWith(DnsPrefix, StringComparison.InvariantCultureIgnoreCase)) |
| | 3 | 41 | | { |
| | 3 | 42 | | return (new[] { new Uri(connectionString) }, true); |
| | | 43 | | } |
| | | 44 | | |
| | 17 | 45 | | string[] hosts = connectionString.Split(','); |
| | 17 | 46 | | List<Uri> nodes = new(); |
| | | 47 | | |
| | 91 | 48 | | foreach (string host in hosts) |
| | 20 | 49 | | { |
| | 20 | 50 | | string processedHost = host.Trim(); |
| | | 51 | | |
| | | 52 | | // Only append port if no port is specified and it's not a full URL |
| | 20 | 53 | | if (!processedHost.Contains(':') && |
| | 20 | 54 | | !processedHost.StartsWith(InsecurePrefix, StringComparison.InvariantCultureIgnoreCase) && |
| | 20 | 55 | | !processedHost.StartsWith(SecurePrefix, StringComparison.InvariantCultureIgnoreCase)) |
| | 9 | 56 | | { |
| | 9 | 57 | | processedHost += $":{Convert.ToString(port, CultureInfo.InvariantCulture)}"; |
| | 9 | 58 | | } |
| | | 59 | | |
| | 20 | 60 | | if (!(processedHost.StartsWith(InsecurePrefix, StringComparison.InvariantCultureIgnoreCase) || |
| | 20 | 61 | | processedHost.StartsWith(SecurePrefix, StringComparison.InvariantCultureIgnoreCase))) |
| | 18 | 62 | | { |
| | 18 | 63 | | processedHost = credentials == ChannelCredentials.Insecure |
| | 18 | 64 | | ? $"{InsecurePrefix}{processedHost}" |
| | 18 | 65 | | : $"{SecurePrefix}{processedHost}"; |
| | 18 | 66 | | } |
| | | 67 | | |
| | 20 | 68 | | nodes.Add(new Uri(processedHost)); |
| | 20 | 69 | | } |
| | | 70 | | |
| | 17 | 71 | | return (nodes.ToArray(), false); |
| | 20 | 72 | | } |
| | | 73 | | } |