comparison src/server/server.py @ 1006:d0b27d1e2d50

server: moved code to retrieve external server from legacy blog to server.py, and use it to find websocket URL
author Goffi <goffi@goffi.org>
date Sat, 06 Jan 2018 12:37:56 +0100
parents 05cc33d8e328
children 1593e00078d2
comparison
equal deleted inserted replaced
1005:b6dc6cf76473 1006:d0b27d1e2d50
1784 def putChild(self, path, resource): 1784 def putChild(self, path, resource):
1785 """Add a child to the root resource""" 1785 """Add a child to the root resource"""
1786 # FIXME: check that no information is leaked (c.f. https://twistedmatrix.com/documents/current/web/howto/using-twistedweb.html#request-encoders) 1786 # FIXME: check that no information is leaked (c.f. https://twistedmatrix.com/documents/current/web/howto/using-twistedweb.html#request-encoders)
1787 self.root.putChild(path, web_resource.EncodingResourceWrapper(resource, [server.GzipEncoderFactory()])) 1787 self.root.putChild(path, web_resource.EncodingResourceWrapper(resource, [server.GzipEncoderFactory()]))
1788 1788
1789 def getExtBaseURLData(self, request):
1790 """Retrieve external base URL Data
1791
1792 this method tried to retrieve the base URL found by external user
1793 It does by checking in this order:
1794 - base_url_ext option from configuration
1795 - proxy x-forwarder-host headers
1796 - URL of the request
1797 @return (urlparse.SplitResult): SplitResult instance with only scheme and netloc filled
1798 """
1799 ext_data = self.base_url_ext_data
1800 url_path = request.URLPath()
1801 if not ext_data.scheme or not ext_data.netloc:
1802 # ext_data is not specified, we check headers
1803 if request.requestHeaders.hasHeader('x-forwarded-host'):
1804 # we are behing a proxy
1805 # we fill proxy_scheme and proxy_netloc value
1806 proxy_host = request.requestHeaders.getRawHeaders('x-forwarded-host')[0]
1807 try:
1808 proxy_server = request.requestHeaders.getRawHeaders('x-forwarded-server')[0]
1809 except TypeError:
1810 # no x-forwarded-server found, we use proxy_host
1811 proxy_netloc = proxy_host
1812 else:
1813 # if the proxy host has a port, we use it with server name
1814 proxy_port = urlparse.urlsplit(u'//{}'.format(proxy_host)).port
1815 proxy_netloc = u'{}:{}'.format(proxy_server, proxy_port) if proxy_port is not None else proxy_server
1816 proxy_netloc = proxy_netloc.decode('utf-8')
1817 try:
1818 proxy_scheme = request.requestHeaders.getRawHeaders('x-forwarded-proto')[0].decode('utf-8')
1819 except TypeError:
1820 proxy_scheme = None
1821 else:
1822 proxy_scheme, proxy_netloc = None, None
1823 else:
1824 proxy_scheme, proxy_netloc = None, None
1825
1826 return urlparse.SplitResult(
1827 ext_data.scheme or proxy_scheme or url_path.scheme.decode('utf-8'),
1828 ext_data.netloc or proxy_netloc or url_path.netloc.decode('utf-8'),
1829 ext_data.path or u'/',
1830 '', '')
1831
1832 def getExtBaseURL(self, request, path='', query='', fragment='', scheme=None):
1833 """Get external URL according to given elements
1834
1835 external URL is the URL seen by external user
1836 @param path(unicode): same as for urlsplit.urlsplit
1837 path will be prefixed to follow found external URL if suitable
1838 @param params(unicode): same as for urlsplit.urlsplit
1839 @param query(unicode): same as for urlsplit.urlsplit
1840 @param fragment(unicode): same as for urlsplit.urlsplit
1841 @param scheme(unicode, None): if not None, will override scheme from base URL
1842 @return (unicode): external URL
1843 """
1844 split_result = self.getExtBaseURLData(request)
1845 return urlparse.urlunsplit((
1846 split_result.scheme.decode('utf-8') if scheme is None else scheme,
1847 split_result.netloc.decode('utf-8'),
1848 os.path.join(split_result.path, path),
1849 query, fragment))
1850
1851
1789 ## Sessions ## 1852 ## Sessions ##
1790 1853
1791 def purgeSession(self, request): 1854 def purgeSession(self, request):
1792 """helper method to purge a session during request handling""" 1855 """helper method to purge a session during request handling"""
1793 session = request.session 1856 session = request.session
1812 return (iface(session) for iface in args) 1875 return (iface(session) for iface in args)
1813 1876
1814 ## Websocket (dynamic pages) ## 1877 ## Websocket (dynamic pages) ##
1815 1878
1816 def getWebsocketURL(self, request): 1879 def getWebsocketURL(self, request):
1817 if request.isSecure(): 1880 base_url_split = self.getExtBaseURLData(request)
1818 ws = 'wss' 1881 if base_url_split.scheme.endswith('s'):
1882 scheme = u'wss'
1819 else: 1883 else:
1820 ws = 'ws' 1884 scheme = u'ws'
1821 1885
1822 if self.base_url_ext: 1886 return self.getExtBaseURL(request, path=scheme, scheme=scheme)
1823 base_url = self.base_url_ext
1824 else:
1825 o = self.options
1826 if request.isSecure():
1827 port = o['port_https_ext'] or o['port_https']
1828 else:
1829 port = o['port']
1830 base_url = request.getRequestHostname().decode('utf-8') + u':' + unicode(port)+ u'/'
1831
1832 return u'{ws}://{base_url}{ws}'.format(
1833 ws = ws,
1834 base_url = base_url)
1835 1887
1836 def registerWSToken(self, token, page, request): 1888 def registerWSToken(self, token, page, request):
1837 websockets.LiberviaPageWSProtocol.registerToken(token, page, request) 1889 websockets.LiberviaPageWSProtocol.registerToken(token, page, request)
1838 1890
1839 ## TLS related methods ## 1891 ## TLS related methods ##