summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCalum Lind <calumlind+deluge@gmail.com>2023-03-02 21:53:27 +0000
committerCalum Lind <calumlind+deluge@gmail.com>2023-03-03 09:37:46 +0000
commit4b6ac1f4c4dd9c9965b78e58681ff3a9e5c0ff04 (patch)
tree48c331d9cb5a5ed9d2c24dae25f94904dad5796c
parent683a4f906ea79de45cacecd3ebb5019c909bdfd6 (diff)
downloaddeluge-4b6ac1f4c4dd9c9965b78e58681ff3a9e5c0ff04.tar.gz
deluge-4b6ac1f4c4dd9c9965b78e58681ff3a9e5c0ff04.tar.bz2
deluge-4b6ac1f4c4dd9c9965b78e58681ff3a9e5c0ff04.zip
[WebUI] Fix setting base path
Simplify the code for setting the base path, both via headers and config. Replaced putchild since it is not recommended for dynamic paths and overriding getChildWithDefault provides a proper solution. This also fixes recursive base path problem with previous code where appending base paths to URL would still return Deluge web e.g. http://localhost:8112/deluge/deluge/deluge Removed getChild override by consolidating empty path conditional to getChildWithDefault. This simplifies and combines the returning of TopLevel resource for root path or base path. Added workaround for test logfile error with forwardslash in filename
-rw-r--r--deluge/tests/common.py2
-rw-r--r--deluge/tests/test_webserver.py54
-rw-r--r--deluge/ui/web/server.py20
3 files changed, 64 insertions, 12 deletions
diff --git a/deluge/tests/common.py b/deluge/tests/common.py
index b5941568d..0e82bf12b 100644
--- a/deluge/tests/common.py
+++ b/deluge/tests/common.py
@@ -113,7 +113,7 @@ class ProcessOutputHandler(protocol.ProcessProtocol):
self.shutdown_func = shutdown_func
self.log_output = ''
self.stderr_out = ''
- self.logfile = logfile
+ self.logfile = logfile.replace('/', '_') if logfile else None
self.print_stdout = print_stdout
self.print_stderr = print_stderr
self.quit_d = None
diff --git a/deluge/tests/test_webserver.py b/deluge/tests/test_webserver.py
index 69a424e77..683ab97a1 100644
--- a/deluge/tests/test_webserver.py
+++ b/deluge/tests/test_webserver.py
@@ -9,6 +9,7 @@
import json as json_lib
from io import BytesIO
+import pytest
import pytest_twisted
import twisted.web.client
from twisted.internet import reactor
@@ -57,3 +58,56 @@ class TestWebServer(WebServerTestBase, WebServerMockBase):
print('aoeu')
assert json['error'] is None
assert 'torrent_filehash' == json['result']['name']
+
+ @pytest.mark.parametrize('base', ['', '/', 'deluge'])
+ @pytest_twisted.ensureDeferred
+ async def test_base_with_config(self, base):
+ agent = Agent(reactor)
+ root_url = f'http://127.0.0.1:{self.deluge_web.port}'
+ base_url = f'{root_url}/{base}'
+
+ self.deluge_web.base = base
+
+ response = await agent.request(b'GET', root_url.encode())
+ assert response.code == 200
+ body = await twisted.web.client.readBody(response)
+ assert 'Deluge WebUI' in body.decode()
+
+ response = await agent.request(b'GET', base_url.encode())
+ assert response.code == 200
+
+ @pytest.mark.parametrize('base', ['/', 'deluge'])
+ @pytest_twisted.ensureDeferred
+ async def test_base_with_config_recurring_basepath(self, base):
+ agent = Agent(reactor)
+ base_url = f'http://127.0.0.1:{self.deluge_web.port}/{base}'
+
+ self.deluge_web.base = base
+
+ response = await agent.request(b'GET', base_url.encode())
+ assert response.code == 200
+
+ recursive_url = f'{base_url}/{base}'
+ response = await agent.request(b'GET', recursive_url.encode())
+ assert response.code == 404 if base.strip('/') else 200
+
+ recursive_url = f'{recursive_url}/{base}'
+ response = await agent.request(b'GET', recursive_url.encode())
+ assert response.code == 404 if base.strip('/') else 200
+
+ @pytest_twisted.ensureDeferred
+ async def test_base_with_deluge_header(self):
+ """Ensure base path is set and HTML contains path"""
+ agent = Agent(reactor)
+ base = 'deluge'
+ url = f'http://127.0.0.1:{self.deluge_web.port}'
+ headers = Headers({'X-Deluge-Base': [base]})
+
+ response = await agent.request(b'GET', url.encode(), headers)
+ body = await twisted.web.client.readBody(response)
+ assert f'href="/{base}/' in body.decode()
+
+ # Header only changes HTML base path so ensure no resource at server path
+ url = f'{url}/{base}'
+ response = await agent.request(b'GET', url.encode(), headers)
+ assert response.code == 404
diff --git a/deluge/ui/web/server.py b/deluge/ui/web/server.py
index 06b25923b..fe563f130 100644
--- a/deluge/ui/web/server.py
+++ b/deluge/ui/web/server.py
@@ -569,18 +569,20 @@ class TopLevel(resource.Resource):
self.__scripts.remove(script)
self.__debug_scripts.remove(script)
- def getChild(self, path, request): # NOQA: N802
- if not path:
- return self
- else:
- return super().getChild(path, request)
-
def getChildWithDefault(self, path, request): # NOQA: N802
# Calculate the request base
header = request.getHeader('x-deluge-base')
- base = header if header else component.get('DelugeWeb').base
+ config_base = component.get('DelugeWeb').base
+ base = header if header else config_base
+
+ first_request = not hasattr(request, 'base')
request.base = absolute_base_url(base).encode()
+ base_resource = first_request and path.decode() == config_base.strip('/')
+
+ if not path or base_resource:
+ return self
+
return super().getChildWithDefault(path, request)
def render(self, request):
@@ -680,10 +682,6 @@ class DelugeWeb(component.Component):
elif options.no_ssl:
self.https = False
- if self.base != '/':
- # Strip away slashes and serve on the base path as well as root path
- self.top_level.putChild(self.base.strip('/').encode(), self.top_level)
-
setup_translation()
# Remove twisted version number from 'server' http-header for security reasons