comparison libervia/web/server/proxy.py @ 1518:eb00d593801d

refactoring: rename `libervia` to `libervia.web` + update imports following backend changes
author Goffi <goffi@goffi.org>
date Fri, 02 Jun 2023 16:49:28 +0200
parents libervia/server/proxy.py@fc91b78b71db
children
comparison
equal deleted inserted replaced
1517:b8ed9726525b 1518:eb00d593801d
1 #!/usr/bin/env python3
2
3 # Libervia: a Salut à Toi frontend
4 # Copyright (C) 2011-2021 Jérôme Poisson <goffi@goffi.org>
5
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU Affero General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU Affero General Public License for more details.
15
16 # You should have received a copy of the GNU Affero General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 from twisted.web import proxy
19 from twisted.python.compat import urlquote
20 from twisted.internet import address
21 from libervia.backend.core.log import getLogger
22 from libervia.web.server.constants import Const as C
23
24 log = getLogger(__name__)
25
26
27
28 class SatProxyClient(proxy.ProxyClient):
29
30 def handleHeader(self, key, value):
31 if key.lower() == b"x-frame-options":
32 value = b"sameorigin"
33 elif key.lower() == b"content-security-policy":
34 value = value.replace(b"frame-ancestors 'none'", b"frame-ancestors 'self'")
35
36 super().handleHeader(key, value)
37
38
39 class SatProxyClientFactory(proxy.ProxyClientFactory):
40 protocol = SatProxyClient
41
42
43 class SatReverseProxyResource(proxy.ReverseProxyResource):
44 """Resource Proxy rewritting headers to allow embedding in iframe on same domain"""
45 proxyClientFactoryClass = SatProxyClientFactory
46
47 def getChild(self, path, request):
48 return SatReverseProxyResource(
49 self.host, self.port,
50 self.path + b'/' + urlquote(path, safe=b"").encode('utf-8'),
51 self.reactor
52 )
53
54 def render(self, request):
55 # Forwarded and X-Forwarded-xxx headers can be set
56 # if we have behind an other proxy
57 if ((not request.getHeader(C.H_FORWARDED)
58 and not request.getHeader(C.H_X_FORWARDED_HOST))):
59 forwarded_data = []
60 addr = request.getClientAddress()
61 if ((isinstance(addr, address.IPv4Address)
62 or isinstance(addr, address.IPv6Address))):
63 request.requestHeaders.setRawHeaders(C.H_X_FORWARDED_FOR, [addr.host])
64 forwarded_data.append(f"for={addr.host}")
65 host = request.getHeader("host")
66 if host is None:
67 port = request.getHost().port
68 hostname = request.getRequestHostname()
69 host = hostname if port in (80, 443) else f"{hostname}:{port}"
70 request.requestHeaders.setRawHeaders(C.H_X_FORWARDED_HOST, [host])
71 forwarded_data.append(f"host={host}")
72 proto = "https" if request.isSecure() else "http"
73 request.requestHeaders.setRawHeaders(C.H_X_FORWARDED_PROTO, [proto])
74 forwarded_data.append(f"proto={proto}")
75 request.requestHeaders.setRawHeaders(
76 C.H_FORWARDED, [";".join(forwarded_data)]
77 )
78
79 return super().render(request)