Skip to content

fix: handle redirects for paths and files with terminating slashes 🌋#717

Merged
mcdurdin merged 1 commit intofix/search-jsonfrom
fix/redirects-for-paths
May 6, 2026
Merged

fix: handle redirects for paths and files with terminating slashes 🌋#717
mcdurdin merged 1 commit intofix/search-jsonfrom
fix/redirects-for-paths

Conversation

@mcdurdin
Copy link
Copy Markdown
Member

Remove the / from a path if it refers to a file, and add a / if the path refers to a folder (implicit index.md/index.php).

Clean up keyboard search which had some assumptions about not including the / but that doesn't make sense with this pattern.

Test-bot: skip

@keymanapp-test-bot
Copy link
Copy Markdown

User Test Results

Test specification and instructions

User tests are not required

@keymanapp-test-bot keymanapp-test-bot Bot changed the title fix: handle redirects for paths and files with terminating slashes fix: handle redirects for paths and files with terminating slashes 🌋 Apr 30, 2026
@keymanapp-test-bot keymanapp-test-bot Bot added this to the A19S28 milestone Apr 30, 2026
@github-actions github-actions Bot added the fix label Apr 30, 2026
@github-project-automation github-project-automation Bot moved this to Todo in Keyman Apr 30, 2026
@mcdurdin mcdurdin force-pushed the fix/redirects-for-paths branch 3 times, most recently from 95b97ef to 3471e04 Compare April 30, 2026 15:30
Comment thread .htaccess
@mcdurdin mcdurdin force-pushed the fix/redirects-for-paths branch 3 times, most recently from a60dbfd to c265b3c Compare May 5, 2026 14:07
@mcdurdin mcdurdin marked this pull request as ready for review May 5, 2026 14:41
@mcdurdin mcdurdin force-pushed the fix/redirects-for-paths branch from c265b3c to 6c2562b Compare May 5, 2026 14:45

<div class="download-cta-small iPhone" id="cta-iPhone">
<a href="../../../iphone/">
<a href="../../../iphone-and-ipad/">
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We keep /ipad and /iphone as top-level redirects, but we don't need those for e.g. /en/ipad as the content is all at /_content/iphone-and-ipad. This eliminates a rule in the .htaccess

<label for="search-q"><?= _m('keyboard_search') ?></label><input id="search-q" type="text" placeholder="<?= _m('enter_language') ?>" name="q"
<?php if($embed == 'none') echo 'autofocus'; ?>>
<input id="search-f" type="button" value="<?= _m('search') ?>">
<label id="search-new"><a href='/<?= $head_options['language']?>/keyboards<?=$session_query_q?>'><?= _m('new_search')?></a></label>
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line was broken (nested <?=), when I fixed it I decided to simplify all references

Comment thread .htaccess
Comment on lines -187 to -203
# ------------------------------------------------------------------
# top-level content without i18n - _control/, go/, _test/, cdn
# ------------------------------------------------------------------

# No i18n - won't go to _content

RewriteCond "%{DOCUMENT_ROOT}/$1/$2.php" -f
RewriteRule "^(_control|go|_test)/(.+)$" "/$1/$2.php" [END]

RewriteCond "%{DOCUMENT_ROOT}/$1/$2.md" -f
RewriteRule "^(_control|go|_test)/(.+)$" "/_includes/includes/md/mdhost.php?file=$1/$2.md" [END]

RewriteCond "%{DOCUMENT_ROOT}/$1/index.md" -f
RewriteRule "^(_control|go|_test)(/?)$" "/_includes/includes/md/mdhost.php?file=$1/index.md" [END]

RewriteCond "%{DOCUMENT_ROOT}/cdn/$1$2" -f
RewriteRule "^cdn/(.+\.)(gif|js|png|svg)$" "/cdn/$1$2" [END]
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section is now moved up

Comment thread .htaccess
Comment on lines -218 to +335
RewriteRule "^(([a-z]{2,3})(-([A-Za-z]{4}))?(-([a-z]{2}|[0-9]{3}))?)/keyboards/install/([^/]+)$" "/_content/keyboards/install.php?id=$7&lang=$1" [NC,END,QSA]
RewriteCond "$1" ^([a-z]{2,3})(-([A-Za-z]{4}))?(-([a-z]{2}|[0-9]{3}))?$ [NC] # BCP 47 match
RewriteRule "^([^/]+)/keyboards/install/([^/]+)$" "/_content/keyboards/install.php?id=$2&lang=$1" [END,QSA]
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, was going to put these into a separate PR ... but was working on them and pushed accidentally. Let's see how they go!

Copy link
Copy Markdown
Contributor

@darcywong00 darcywong00 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ahh, nice cleanup! thanks

Comment thread .htaccess Outdated
# TODO.md
#
RewriteRule "^(_common|_content|_includes|_scripts|.github|resources|tests)(/.*|$)" - [F,END]
RewriteRule "^(.editorconfig|.gitattributes|.gitignore|build.sh|composer.json|composer.lock|crowdin.yml|Dockerfile|package-lock.json|package.json|phpunit.xml|README.md|TODO.md)$" [F,END]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need - [F,END] like in the other lines?

Comment thread .htaccess Outdated
Comment on lines +97 to +116
RewriteCond "$1" ^(_control|_test|_ie_thunk|.well-known|go|cdn)$
RewriteRule "^([^/]+)$" "$1/" [R,L]

# .php rewrite
RewriteCond "$1" ^(_control|_test|_ie_thunk)$
RewriteCond "%{DOCUMENT_ROOT}/$1/$2.php" -f
RewriteRule "^([^/]+)/(.+)$" "/$1/$2.php" [END]

# .md rewrite
RewriteCond "$1" ^(_control|_test|_ie_thunk)$
RewriteCond "%{DOCUMENT_ROOT}/$1/$2.md" -f
RewriteRule "^([^/]+)/(.+)$" "/_includes/includes/md/mdhost.php?file=$1/$2.md" [END]

# .md rewrite for folder; no .php rewrite for folder
RewriteCond "$1" ^(_control|_test|_ie_thunk)$
RewriteCond "%{DOCUMENT_ROOT}/$1/index.md" -f
RewriteRule "^([^/]+)/$" "/_includes/includes/md/mdhost.php?file=$1/index.md" [END]

# Any existing file in any of those folders or sub folders
RewriteCond "$1" ^(_control|_ie_thunk|_test|.well-known|go|cdn)$
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To help me with future maintenance, can we have the RewriteConds in the same sort order as the commented folder listing (ll 80-88)?

e.g.

RewriteCond "$1" ^(_control|_ie_thunk|_test)$

and

RewriteCond "$1" ^(_control|_ie_thunk|_test|.well-known|cdn|go)$

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For sure, was aiming for alphabetical but moved some things around and missed those. Will cleanup

Comment thread .htaccess Outdated

# Redirect folder without / to include /
# ------------------------------------------------------------------
# Add and remove `/` for folders and files for consistency
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe wordsmithing something like

Suggested change
# Add and remove `/` for folders and files for consistency
# For trailing '/' consistency: Add '/' for folders and remove `/` for files

Comment thread _content/keyboards/index.php Outdated
Menu::render([]); // we'll be doing client-side os detection now
Body::render();

$keyboardsPage = '/' . $head_options['language'] . '/keyboards';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin asks if $keyboardPage missing a trailing slash causes unnecessary 302 redirects.

New .htaccess rules at lines 62-64 redirect /en/keyboards -> /en/keyboards/ because _content/keyboards is a directory containing index.php
...
When a user presses Enter in the search box, this causes an unnecessary redirect from /en/keyboards?q=... to /en/keyboards/?q=...

Comment thread cdn/dev/keyboard-search/search.mjs
Remove the `/` from a path if it refers to a file, and add a `/` if the
path refers to a folder (implicit index.md/index.php).

Clean up keyboard search which had some assumptions about not including
the `/` but that doesn't make sense with this pattern.

Test-bot: skip
@mcdurdin mcdurdin force-pushed the fix/redirects-for-paths branch from 6c2562b to dea9d6b Compare May 6, 2026 07:28
Copy link
Copy Markdown
Contributor

@darcywong00 darcywong00 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@mcdurdin mcdurdin merged commit de20356 into fix/search-json May 6, 2026
5 checks passed
@mcdurdin mcdurdin deleted the fix/redirects-for-paths branch May 6, 2026 07:51
@github-project-automation github-project-automation Bot moved this from Todo to Done in Keyman May 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants