1 module hunt.http.codec.http.model.HostPort; 2 3 import hunt.Exceptions; 4 import hunt.text.Common; 5 import hunt.text.StringUtils; 6 7 import std.array; 8 import std.string; 9 10 /** 11 * Parse an authority string into Host and Port 12 * <p> 13 * Parse a string in the form "host:port", handling IPv4 an IPv6 hosts 14 * </p> 15 * 16 */ 17 class HostPort { 18 private string _host; 19 private int _port; 20 21 this(string authority) { 22 if (authority.empty) 23 throw new IllegalArgumentException("No Authority"); 24 try { 25 if (authority[0] == '[') { 26 // ipv6reference 27 int close = cast(int)authority.lastIndexOf(']'); 28 if (close < 0) 29 throw new IllegalArgumentException("Bad IPv6 host"); 30 _host = authority[0..close + 1]; 31 32 if (authority.length > close + 1) { 33 if (authority[close + 1] != ':') 34 throw new IllegalArgumentException("Bad IPv6 port"); 35 _port = StringUtils.toInt(authority, close + 2); 36 } else 37 _port = 0; 38 } else { 39 // ipv4address or hostname 40 int c = cast(int)authority.lastIndexOf(':'); 41 if (c >= 0) { 42 _host = authority[0..c]; 43 _port = StringUtils.toInt(authority, c + 1); 44 } else { 45 _host = authority; 46 _port = 0; 47 } 48 } 49 } catch (IllegalArgumentException iae) { 50 throw iae; 51 } catch (Exception ex) { 52 throw new IllegalArgumentException("Bad HostPort"); 53 } 54 if (_host.empty()) 55 throw new IllegalArgumentException("Bad host"); 56 if (_port < 0) 57 throw new IllegalArgumentException("Bad port"); 58 } 59 60 /** 61 * Get the host. 62 * 63 * @return the host 64 */ 65 string getHost() { 66 return _host; 67 } 68 69 /** 70 * Get the port. 71 * 72 * @return the port 73 */ 74 int getPort() { 75 return _port; 76 } 77 78 /** 79 * Get the port. 80 * 81 * @param defaultPort, 82 * the default port to return if a port is not specified 83 * @return the port 84 */ 85 int getPort(int defaultPort) { 86 return _port > 0 ? _port : defaultPort; 87 } 88 89 /** 90 * Normalize IPv6 address as per https://www.ietf.org/rfc/rfc2732.txt 91 * 92 * @param host 93 * A host name 94 * @return Host name surrounded by '[' and ']' as needed. 95 */ 96 static string normalizeHost(string host) { 97 // if it is normalized IPv6 or could not be IPv6, return 98 if (host.empty() || host[0] == '[' || host.indexOf(':') < 0) 99 return host; 100 101 // normalize with [ ] 102 return "[" ~ host ~ "]"; 103 } 104 }