|
18 | 18 | DEFAULT_DOMAIN = 'api.opencagedata.com' |
19 | 19 |
|
20 | 20 |
|
| 21 | +def _validate_domain(domain): |
| 22 | + """Validate that the API domain is an allowed hostname. |
| 23 | +
|
| 24 | + Only subdomains of opencagedata.com, localhost, and 0.0.0.0 are |
| 25 | + permitted. An optional port suffix (e.g. ``localhost:8080``) is allowed. |
| 26 | +
|
| 27 | + Args: |
| 28 | + domain: Hostname string, optionally with a port. |
| 29 | +
|
| 30 | + Returns: |
| 31 | + The validated domain string. |
| 32 | +
|
| 33 | + Raises: |
| 34 | + ValueError: If the domain is not in the allow-list. |
| 35 | + """ |
| 36 | + # Strip optional port |
| 37 | + host = domain.rsplit(':', 1)[0] if ':' in domain else domain |
| 38 | + |
| 39 | + if host in ('localhost', '0.0.0.0'): |
| 40 | + return domain |
| 41 | + |
| 42 | + if host.endswith('.opencagedata.com'): |
| 43 | + return domain |
| 44 | + |
| 45 | + raise ValueError( |
| 46 | + f"Invalid API domain '{domain}'. " |
| 47 | + f"Must be a subdomain of opencagedata.com, localhost, or 0.0.0.0." |
| 48 | + ) |
| 49 | + |
| 50 | + |
21 | 51 | def backoff_max_time(): |
22 | 52 | """Return the maximum backoff time in seconds for retrying API requests. |
23 | 53 |
|
@@ -146,6 +176,7 @@ def __init__( |
146 | 176 |
|
147 | 177 | if protocol and protocol not in ('http', 'https'): |
148 | 178 | protocol = 'https' |
| 179 | + _validate_domain(domain) |
149 | 180 | self.url = protocol + '://' + domain + '/geocode/v1/json' |
150 | 181 |
|
151 | 182 | # https://docs.aiohttp.org/en/stable/client_advanced.html#ssl-control-for-tcp-sockets |
@@ -353,7 +384,8 @@ def _opencage_headers(self, client): |
353 | 384 |
|
354 | 385 | comment = '' |
355 | 386 | if self.user_agent_comment: |
356 | | - comment = f" ({self.user_agent_comment})" |
| 387 | + clean = self.user_agent_comment.replace('\r', '').replace('\n', '') |
| 388 | + comment = f" ({clean})" |
357 | 389 |
|
358 | 390 | return { |
359 | 391 | 'User-Agent': f"opencage-python/{__version__} Python/{py_version} {client}/{client_version}{comment}" |
|
0 commit comments