Skip to content

[Hotfix] search redirect loop - #788

Open
mikeyarce wants to merge 3 commits into
amnestywebsite:developfrom
mikeyarce:hotfix/search-redirect-loop
Open

[Hotfix] search redirect loop #788
mikeyarce wants to merge 3 commits into
amnestywebsite:developfrom
mikeyarce:hotfix/search-redirect-loop

Conversation

@mikeyarce

@mikeyarce mikeyarce commented Jul 15, 2026

Copy link
Copy Markdown

Ref: #785

Hi! first time contributor here 😄

Fixes the endless redirect loop when searching on a non-multisite install, plus two more single-site search bugs that were hiding behind it.

What's going on

amnesty_maybe_override_search_uri() is hooked into home_url and rewrites any /search/<term>/ path to the bare search page URL. On single-site, current_url() goes through home_url(), so on /search/foo/ it reported /search/ which never matches the target URL prettify_search() wants you on, so it 302s you to the page you're already on, forever. Multisite doesn't loop because current_url() builds from the network siteurl option and never touches home_url() on that path.

I looked at dropping the non-multisite branch in current_url() as suggested in the issue, but building from the siteurl option would break single-site installs where WordPress lives in its own directory (like a Bedrock setup) they would loop again. Suspending the override while current_url() builds its result feels like the safest fix: the current URL should always be the literal request URL. I left the home_url filter itself alone, since form actions and get_pagenum_link() and derived URLs depend on its rewriting.

With the loop fixed, two more single-site problems surfaced:

  1. The search results pattern fatals — it calls switch_to_blog() / get_blog_permalink() unconditionally, and those don't exist outside multisite. Added a get_blog_post_term() helper (modelled on the existing get_blog_post_meta()) that only switches when a result actually comes from another site.
  2. The title filters (title_tag() / results_title()) never applied on plain-http sites: current_url() forces https while amnesty_search_url() follows the site scheme, so their strpos() guards couldn't match. Normalised both sides with set_url_scheme(), as prettify_search() already does.

Steps to test:

  1. Fresh single-site install, pretty permalinks enabled, no search page configured
  2. Run a search via /?s=foo or /search/foo/ ( before this PR the browser dies in a redirect loop and after, there's a single 302 to /search/foo/ and results render)
  3. Check result title links, term links, and the "N results for …" heading
  4. On multisite, verify search works like usual

Considerations:

  • Multisite: current_url()'s multisite branch is untouched. The results pattern still switches sites when a result comes from another site on the network, it now just skips the switch when the result is already from the current site, which previously did nothing anyway.
  • The home_url override is intentionally kept
  • No user-facing strings or markup changed, so no localisation/a11y impact
  • I branched from develop instead of main because main has some commits that were not merged back into develop.

Video
humanity-theme-785-search-fix-before-after.webm

On single-site installs, every search request entered an infinite 302
loop. The amnesty_maybe_override_search_uri filter on home_url rewrites
any /search/<term>/ path to the bare search page URL, and current_url()
routes through home_url() when not on multisite. The reported current
URL therefore never matched the redirect target computed by
Search_Filters::prettify_search(), so the page redirected to itself.

Suspend the override while current_url() builds its result: the current
URL must always be the literal request URL. Only re-add the filter when
it was actually registered, so intentional removals of the override by
child themes or plugins are not silently undone.

Multisite is unaffected: current_url() builds from the network siteurl
option on that path and never calls home_url().
The search results pattern called switch_to_blog(),
restore_current_blog(), and get_blog_permalink() unconditionally. None
of these functions exist on single-site installs, so rendering search
results caused a fatal error. This was previously masked by the search
redirect loop, which made the results page unreachable.

Add a get_blog_post_term() helper, following the existing
get_blog_post_meta() convention, which only switches site context when
running on multisite and the result belongs to a different site. Use it
in the pattern, and fall back to get_permalink() for result links when
no cross-site switch is needed.

Behaviour on multisite is preserved: previously the pattern switched to
the current site (a no-op) when a result carried no blog_id; now it
skips the switch entirely in that case.
current_url() forces the https scheme, while amnesty_search_url()
follows the site's configured scheme. On plain-http sites the strpos()
guards in title_tag() and results_title() could therefore never match,
so the search results title and the month/year suffixes silently
stopped applying.

Normalise both sides with set_url_scheme() before comparing, as
prettify_search() already does.
@mikeyarce

Copy link
Copy Markdown
Author

cc @jaymcp

@jaymcp

jaymcp commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Hi @mikeyarce

Thank you for submitting your first PR, and apologies for the delayed response.

I'll endeavour to get this reviewed today :)

Best
Jay

@AmnestyAM

Copy link
Copy Markdown
Contributor

Hi @mikeyarce
Thanks for the PR, sorry it has taken so long to get back to you, our lead engineer was away for a bit. We were working on updating our contributor guidelines to factor in the changes since the adoption of AI tools etc so we need to get that resolved and updated.

We will be inotuch soon with some feedback on this PR, thanks again for contrubuting, we really apereciate it!

:-)

@mikeyarce

Copy link
Copy Markdown
Author

@AmnestyAM no problem! Let me know if I can help in any other way, happy to jump in to help more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants