add the ability to redirect a file-looking request to a dir
if the client has requested /foo, and foo is actually a directory, this redirects the client to /foo/
This commit is contained in:
parent
cf8f0325a2
commit
0f7495bf2b
@ -6,7 +6,7 @@ import os
|
|||||||
import markdown
|
import markdown
|
||||||
from flask import Blueprint, Markup, abort
|
from flask import Blueprint, Markup, abort
|
||||||
from flask import current_app as app
|
from flask import current_app as app
|
||||||
from flask import render_template
|
from flask import redirect, render_template
|
||||||
from tzlocal import get_localzone
|
from tzlocal import get_localzone
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -19,6 +19,9 @@ md = markdown.Markdown(extensions=['meta', 'tables'])
|
|||||||
@bp.route('/<path:path>')
|
@bp.route('/<path:path>')
|
||||||
def display_page(path):
|
def display_page(path):
|
||||||
"""Get the file contents of the requested path and render the file."""
|
"""Get the file contents of the requested path and render the file."""
|
||||||
|
if is_file_path_actually_dir_path(path):
|
||||||
|
return redirect(f'{path}/', code=301)
|
||||||
|
|
||||||
resolved_path = resolve_page_file(path)
|
resolved_path = resolve_page_file(path)
|
||||||
logger.debug("received request for path '%s', resolved to '%s'", path, resolved_path)
|
logger.debug("received request for path '%s', resolved to '%s'", path, resolved_path)
|
||||||
try:
|
try:
|
||||||
@ -52,6 +55,22 @@ def resolve_page_file(path):
|
|||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def is_file_path_actually_dir_path(path):
|
||||||
|
"""Check if requested path which looks like a file is actually a directory.
|
||||||
|
|
||||||
|
If, for example, /foo used to be a file (foo.md) which later became a directory,
|
||||||
|
foo/, this returns True. Useful for when I make my structure more complicated
|
||||||
|
than it originally was, or if users are just weird.
|
||||||
|
"""
|
||||||
|
if not path.endswith('/'):
|
||||||
|
logger.debug("requested path '%s' looks like a file", path)
|
||||||
|
if os.path.isdir(f'{app.instance_path}/pages/{path}'):
|
||||||
|
logger.debug("...and it's actually a dir")
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def generate_parent_navs(path):
|
def generate_parent_navs(path):
|
||||||
"""Create a series of paths/links to navigate up from the given path."""
|
"""Create a series of paths/links to navigate up from the given path."""
|
||||||
# derive additional path/location stuff based on path
|
# derive additional path/location stuff based on path
|
||||||
|
@ -35,3 +35,20 @@ def test_page_has_modified_timestamp(client):
|
|||||||
response = client.get('/')
|
response = client.get('/')
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert re.search(r'Last modified: ....-..-.. ..:..:.. ...', response.data.decode()) is not None
|
assert re.search(r'Last modified: ....-..-.. ..:..:.. ...', response.data.decode()) is not None
|
||||||
|
|
||||||
|
|
||||||
|
def test_that_page_request_redirects_to_directory(client):
|
||||||
|
"""Test that a request to /foo reirects to /foo/, if foo is a directory.
|
||||||
|
|
||||||
|
This might be useful in cases where a formerly page-only page has been
|
||||||
|
converted to a directory with subpages.
|
||||||
|
"""
|
||||||
|
response = client.get('/subdir')
|
||||||
|
assert response.status_code == 301
|
||||||
|
|
||||||
|
|
||||||
|
def test_that_dir_request_does_not_redirect(client):
|
||||||
|
"""Test that a request to /foo/ serves the index page, if foo is a directory."""
|
||||||
|
response = client.get('/subdir/')
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert b'another page' in response.data
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""Unit test helper methods."""
|
"""Unit test helper methods."""
|
||||||
from incorporealcms.pages import generate_parent_navs, resolve_page_file
|
from incorporealcms.pages import generate_parent_navs, is_file_path_actually_dir_path, resolve_page_file
|
||||||
|
|
||||||
|
|
||||||
def test_resolve_page_file_dir_to_index():
|
def test_resolve_page_file_dir_to_index():
|
||||||
@ -50,3 +50,27 @@ def test_generate_page_navs_subdir_with_title_parsing_real_page(app):
|
|||||||
('SUB!', '/subdir-with-title/'),
|
('SUB!', '/subdir-with-title/'),
|
||||||
('/subdir-with-title/page', '/subdir-with-title/page')
|
('/subdir-with-title/page', '/subdir-with-title/page')
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_is_file_path_actually_dir_path_valid_file_is_yes(app):
|
||||||
|
"""Test that a file request for what's actually a directory is detected as such."""
|
||||||
|
with app.app_context():
|
||||||
|
assert is_file_path_actually_dir_path('/subdir')
|
||||||
|
|
||||||
|
|
||||||
|
def test_is_file_path_actually_dir_path_valid_dir_is_no(app):
|
||||||
|
"""Test that a directory request is still a directory request."""
|
||||||
|
with app.app_context():
|
||||||
|
assert not is_file_path_actually_dir_path('/subdir/')
|
||||||
|
|
||||||
|
|
||||||
|
def test_is_file_path_actually_dir_path_nonsense_file_is_no(app):
|
||||||
|
"""Test that requests to nonsense file-looking paths aren't treated as dirs."""
|
||||||
|
with app.app_context():
|
||||||
|
assert not is_file_path_actually_dir_path('/antphnathpnthapnthsnthax')
|
||||||
|
|
||||||
|
|
||||||
|
def test_is_file_path_actually_dir_path_nonsense_dir_is_no(app):
|
||||||
|
"""Test that a directory request is a directory request even if the dir doesn't exist."""
|
||||||
|
with app.app_context():
|
||||||
|
assert not is_file_path_actually_dir_path('/antphnathpnthapnthsnthax/')
|
||||||
|
Loading…
Reference in New Issue
Block a user