treat symlinks as redirects

closes #7
This commit is contained in:
Brian S. Stephan 2021-04-15 21:43:29 -05:00
parent 71ead20f3f
commit c90f0a3a42
5 changed files with 44 additions and 1 deletions

View File

@ -22,7 +22,8 @@ def display_page(path):
"""Get the file contents of the requested path and render the file."""
try:
resolved_path, render_type = request_path_to_instance_resource_path(path)
logger.debug("received request for path '%s', resolved to '%s'", path, resolved_path)
logger.debug("received request for path '%s', resolved to '%s', type '%s'",
path, resolved_path, render_type)
except PermissionError:
abort(400)
except IsADirectoryError:
@ -32,6 +33,8 @@ def display_page(path):
if render_type == 'file':
return send_from_directory(app.instance_path, resolved_path)
elif render_type == 'symlink':
return redirect(instance_resource_path_to_request_path(resolved_path), code=301)
elif render_type == 'markdown':
try:
with app.open_instance_resource(resolved_path, 'r') as entry_file:
@ -77,6 +80,15 @@ def request_path_to_instance_resource_path(path):
logger.warning("client tried to request a path '%s' outside of the base_dir!", path)
raise PermissionError
# if this is a (valid) symlink, find what it's pointed to and redirect the user
if os.path.islink(os.path.join(base_dir, path)):
logger.info("client requested a path '%s' that is actually a symlink to file '%s'", path, resolved_path)
return resolved_path.replace(f'{app.instance_path}{os.path.sep}', ''), 'symlink'
elif os.path.islink(os.path.join(base_dir, f'{path}.md')):
resolved_path = os.path.realpath(os.path.join(base_dir, f'{path}.md'))
logger.info("client requested a path '%s' that is actually a symlink to file '%s'", path, resolved_path)
return resolved_path.replace(f'{app.instance_path}{os.path.sep}', ''), 'symlink'
# if this is a file-like requset but actually a directory, redirect the user
if os.path.isdir(resolved_path) and not path.endswith('/'):
logger.info("client requested a path '%s' that is actually a directory", path)

View File

@ -108,6 +108,21 @@ def test_that_page_request_redirects_to_directory(client):
"""
response = client.get('/subdir')
assert response.status_code == 301
assert response.location == 'http://localhost/subdir/'
def test_that_request_to_symlink_redirects_markdown(client):
"""Test that a request to /foo redirects to /what-foo-points-at."""
response = client.get('/symlink-to-no-title')
assert response.status_code == 301
assert response.location == 'http://localhost/no-title'
def test_that_request_to_symlink_redirects_file(client):
"""Test that a request to /foo.txt redirects to /what-foo-points-at.txt."""
response = client.get('/symlink-to-foo.txt')
assert response.status_code == 301
assert response.location == 'http://localhost/foo.txt'
def test_that_dir_request_does_not_redirect(client):

View File

@ -0,0 +1 @@
foo.txt

View File

@ -0,0 +1 @@
no-title.md

View File

@ -132,6 +132,20 @@ def test_request_path_to_instance_resource_path_actual_file(app):
('pages/bss-square-no-bg.png', 'file'))
def test_request_path_to_instance_resource_path_markdown_symlink(app):
"""Test that a request for e.g. '/foo' when foo.md is a symlink to another .md file redirects."""
with app.test_request_context():
assert (request_path_to_instance_resource_path('symlink-to-no-title') ==
('pages/no-title.md', 'symlink'))
def test_request_path_to_instance_resource_path_file_symlink(app):
"""Test that a request for e.g. '/foo' when foo.txt is a symlink to another .txt file redirects."""
with app.test_request_context():
assert (request_path_to_instance_resource_path('symlink-to-foo.txt') ==
('pages/foo.txt', 'symlink'))
def test_request_path_to_instance_resource_path_nonexistant_file_errors(app):
"""Test that a request for something not on disk errors."""
with app.test_request_context():