|
| 1 | +from threading import RLock |
1 | 2 | from urllib.parse import urlsplit |
2 | 3 |
|
3 | 4 | from django.conf import settings |
|
9 | 10 |
|
10 | 11 |
|
11 | 12 | class ProxyUrlsRegistry: |
12 | | - _last_registry_load = None |
13 | 13 | _registry_reload_threshold = getattr(settings, "PROXY_RELOAD_REGISTRY_THRESHOLD_DAYS", 1) |
14 | 14 |
|
15 | | - def initialize(self): |
| 15 | + def __init__(self): |
| 16 | + self._lock = RLock() |
| 17 | + self._last_registry_load = None |
| 18 | + self._proxy_allowed_hosts = None |
| 19 | + |
| 20 | + def _needs_initialization(self): |
| 21 | + return ( |
| 22 | + self._last_registry_load is None |
| 23 | + or (now() - self._last_registry_load).days >= self._registry_reload_threshold |
| 24 | + ) |
| 25 | + |
| 26 | + @property |
| 27 | + def proxy_allowed_hosts(self): |
| 28 | + # We register remote hosts from remote URLs at creation time, inside ImporterViewSet.create(). |
| 29 | + # If for some reason the creation fails we end up having stale or wrong URLs inside the registry. |
| 30 | + # We check the last time the registry was updated, and after a certain delta we reinitialize the registry |
| 31 | + # which removes any URLs that are not connected to remote datasets. |
| 32 | + if self._needs_initialization(): |
| 33 | + with self._lock: |
| 34 | + if self._needs_initialization(): |
| 35 | + self._initialize() |
| 36 | + return self._proxy_allowed_hosts |
| 37 | + |
| 38 | + @proxy_allowed_hosts.setter |
| 39 | + def proxy_allowed_hosts(self, hosts): |
| 40 | + self._proxy_allowed_hosts = set(hosts) |
| 41 | + |
| 42 | + def _initialize(self): |
16 | 43 | from geonode.base.models import Link |
17 | 44 | from geonode.geoserver.helpers import ogc_server_settings |
18 | 45 |
|
19 | | - self.proxy_allowed_hosts = set([site_url.hostname] + list(getattr(settings, "PROXY_ALLOWED_HOSTS", ()))) |
| 46 | + proxy_allowed_hosts = set([site_url.hostname] + list(getattr(settings, "PROXY_ALLOWED_HOSTS", ()))) |
20 | 47 |
|
21 | 48 | if ogc_server_settings: |
22 | | - self.register_host(ogc_server_settings.hostname) |
| 49 | + proxy_allowed_hosts.add(ogc_server_settings.hostname) |
23 | 50 |
|
24 | 51 | for link in Link.objects.filter(resource__sourcetype="REMOTE", link_type__in=PROXIED_LINK_TYPES): |
25 | 52 | remote_host = urlsplit(link.url).hostname |
26 | | - self.register_host(remote_host) |
| 53 | + proxy_allowed_hosts.add(remote_host) |
27 | 54 |
|
| 55 | + self.proxy_allowed_hosts = proxy_allowed_hosts |
28 | 56 | self._last_registry_load = now() |
29 | 57 |
|
| 58 | + def initialize(self): |
| 59 | + """Rebuild the registry safely for direct callers.""" |
| 60 | + with self._lock: |
| 61 | + self._initialize() |
| 62 | + |
30 | 63 | def set(self, hosts): |
31 | | - self.proxy_allowed_hosts = set(hosts) |
32 | | - self._last_registry_load = now() |
| 64 | + with self._lock: |
| 65 | + self.proxy_allowed_hosts = set(hosts) |
| 66 | + self._last_registry_load = now() |
33 | 67 | return self |
34 | 68 |
|
35 | 69 | def clear(self): |
36 | | - self.proxy_allowed_hosts = set() |
37 | | - self._last_registry_load = now() |
| 70 | + with self._lock: |
| 71 | + self.proxy_allowed_hosts = set() |
| 72 | + self._last_registry_load = now() |
38 | 73 | return self |
39 | 74 |
|
40 | 75 | def register_host(self, host): |
41 | | - self.proxy_allowed_hosts.add(host) |
| 76 | + with self._lock: |
| 77 | + self.proxy_allowed_hosts.add(host) |
42 | 78 |
|
43 | 79 | def unregister_host(self, host): |
44 | | - self.proxy_allowed_hosts.remove(host) |
| 80 | + with self._lock: |
| 81 | + self.proxy_allowed_hosts.remove(host) |
45 | 82 |
|
46 | 83 | def get_proxy_allowed_hosts(self): |
47 | | - # We register remote hosts from remote URLs at creation time, inside ImporterViewSet.create(). |
48 | | - # If for some reason the creation fails we end up having stale or wrong URLs inside the registry. |
49 | | - # We check the last time the registry was updated, and after a certain delta we reinitialize the registry |
50 | | - # which removes any URLs that are not connected to remote datasets |
51 | | - if ( |
52 | | - self._last_registry_load is None |
53 | | - or (now() - self._last_registry_load).days >= self._registry_reload_threshold |
54 | | - ): |
55 | | - self.initialize() |
56 | 84 | return self.proxy_allowed_hosts |
57 | 85 |
|
58 | 86 |
|
|
0 commit comments