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