Validates a host string Returns a 2-tuple of host followed by port where port is default_port if it wasn't specified in the string. :param entity: A host or host:port string where host could be a hostname or IP address. :param default_port: The port number to us
(entity: str, default_port: Optional[int] = DEFAULT_PORT)
| 170 | |
| 171 | |
| 172 | def parse_host(entity: str, default_port: Optional[int] = DEFAULT_PORT) -> _Address: |
| 173 | """Validates a host string |
| 174 | |
| 175 | Returns a 2-tuple of host followed by port where port is default_port |
| 176 | if it wasn't specified in the string. |
| 177 | |
| 178 | :param entity: A host or host:port string where host could be a |
| 179 | hostname or IP address. |
| 180 | :param default_port: The port number to use when one wasn't |
| 181 | specified in entity. |
| 182 | """ |
| 183 | host = entity |
| 184 | port: Optional[Union[str, int]] = default_port |
| 185 | if entity[0] == "[": |
| 186 | host, port = parse_ipv6_literal_host(entity, default_port) |
| 187 | elif entity.endswith(".sock"): |
| 188 | return entity, default_port |
| 189 | elif entity.find(":") != -1: |
| 190 | if entity.count(":") > 1: |
| 191 | raise ValueError( |
| 192 | "Reserved characters such as ':' must be " |
| 193 | "escaped according RFC 2396. An IPv6 " |
| 194 | "address literal must be enclosed in '[' " |
| 195 | "and ']' according to RFC 2732." |
| 196 | ) |
| 197 | host, port = host.split(":", 1) |
| 198 | if isinstance(port, str): |
| 199 | if not port.isdigit(): |
| 200 | # Special case check for mistakes like "mongodb://localhost:27017 ". |
| 201 | if all(c.isspace() or c.isdigit() for c in port): |
| 202 | for c in port: |
| 203 | if c.isspace(): |
| 204 | raise ValueError(f"Port contains whitespace character: {c!r}") |
| 205 | |
| 206 | # A non-digit port indicates that the URI is invalid, likely because the password |
| 207 | # or username were not escaped. |
| 208 | raise ValueError( |
| 209 | "Port contains non-digit characters. Hint: username and password must be escaped according to " |
| 210 | "RFC 3986, use urllib.parse.quote_plus" |
| 211 | ) |
| 212 | if int(port) > 65535 or int(port) <= 0: |
| 213 | raise ValueError("Port must be an integer between 0 and 65535") |
| 214 | port = int(port) |
| 215 | |
| 216 | # Normalize hostname to lowercase, since DNS is case-insensitive: |
| 217 | # https://tools.ietf.org/html/rfc4343 |
| 218 | # This prevents useless rediscovery if "foo.com" is in the seed list but |
| 219 | # "FOO.com" is in the hello response. |
| 220 | return host.lower(), port |
| 221 | |
| 222 | |
| 223 | # Options whose values are implicitly determined by tlsInsecure. |
no test coverage detected