|
22 | 22 | from collections import namedtuple |
23 | 23 | from socket import getaddrinfo, gaierror, SOCK_STREAM, IPPROTO_TCP |
24 | 24 |
|
25 | | -from neo4j.compat import urlparse |
| 25 | +from neo4j.compat import urlparse, parse_qs |
26 | 26 | from neo4j.exceptions import AddressError |
27 | 27 |
|
28 | | -try: |
29 | | - from urllib.parse import parse_qs |
30 | | -except ImportError: |
31 | | - from urlparse import parse_qs |
32 | | - |
33 | 28 |
|
34 | 29 | VALID_IPv4_SEGMENTS = [str(i).encode("latin1") for i in range(0x100)] |
35 | 30 | VALID_IPv6_SEGMENT_CHARS = b"0123456789abcdef" |
@@ -103,17 +98,46 @@ def parse_routing_context(cls, uri): |
103 | 98 | return context |
104 | 99 |
|
105 | 100 |
|
106 | | -def resolve(socket_address): |
107 | | - try: |
108 | | - info = getaddrinfo(socket_address[0], socket_address[1], 0, SOCK_STREAM, IPPROTO_TCP) |
109 | | - except gaierror: |
110 | | - raise AddressError("Cannot resolve address {!r}".format(socket_address[0])) |
111 | | - else: |
112 | | - addresses = [] |
113 | | - for _, _, _, _, address in info: |
114 | | - if len(address) == 4 and address[3] != 0: |
115 | | - # skip any IPv6 addresses with a non-zero scope id |
116 | | - # as these appear to cause problems on some platforms |
117 | | - continue |
118 | | - addresses.append(address) |
119 | | - return addresses |
| 101 | +class Resolver(object): |
| 102 | + """ A Resolver instance stores a list of addresses, each in a tuple, and |
| 103 | + provides methods to perform resolution on these, thereby replacing them |
| 104 | + with the resolved values. |
| 105 | + """ |
| 106 | + |
| 107 | + def __init__(self, custom_resolver=None): |
| 108 | + self.addresses = [] |
| 109 | + self.custom_resolver = custom_resolver |
| 110 | + |
| 111 | + def custom_resolve(self): |
| 112 | + """ If a custom resolver is defined, perform custom resolution on |
| 113 | + the contained addresses. |
| 114 | +
|
| 115 | + :return: |
| 116 | + """ |
| 117 | + if not callable(self.custom_resolver): |
| 118 | + return |
| 119 | + new_addresses = [] |
| 120 | + for address in self.addresses: |
| 121 | + for new_address in self.custom_resolver(address): |
| 122 | + new_addresses.append(new_address) |
| 123 | + self.addresses = new_addresses |
| 124 | + |
| 125 | + def dns_resolve(self): |
| 126 | + """ Perform DNS resolution on the contained addresses. |
| 127 | +
|
| 128 | + :return: |
| 129 | + """ |
| 130 | + new_addresses = [] |
| 131 | + for address in self.addresses: |
| 132 | + try: |
| 133 | + info = getaddrinfo(address[0], address[1], 0, SOCK_STREAM, IPPROTO_TCP) |
| 134 | + except gaierror: |
| 135 | + raise AddressError("Cannot resolve address {!r}".format(address)) |
| 136 | + else: |
| 137 | + for _, _, _, _, address in info: |
| 138 | + if len(address) == 4 and address[3] != 0: |
| 139 | + # skip any IPv6 addresses with a non-zero scope id |
| 140 | + # as these appear to cause problems on some platforms |
| 141 | + continue |
| 142 | + new_addresses.append(address) |
| 143 | + self.addresses = new_addresses |
0 commit comments