Issue arrived with 2.70 redirect loop mystery

I have a test setup on a windows PC running Apache that I have not worked on for a while, so before starting I upgraded from CP v2.41 to v2.70 and immediately a rewrite loop appeared from some .htaccess rules I created as part of hiding admin and login and some rewriting when in admin.

The thing is all plugins are confirmed the same as before, .htaccess is 100% the same, and I’ve made no other changes.

I have also confirmed by restoring the CC core files to v2.41 and the problem immediately disappeared. On copying the v2.70 core files back the issue immediately reappeared.

So the question is has something changed since v2.41 that might account for such behavior?

I appreciate it might be helpful to post my .htaccess file, but there is so much there to secure my setup that would be ridiculous to publish online. But I’ve never had an issue with any of it with CC or previous use with WP, until I made this upgrade.

Any ideas would be appreciated.

I would try deactivating all your plugins, switching to a default theme, and removing everything custom in your .htaccess file to see if the problem goes away, as it should. Then you can start putting things back one by one to identify the culprit.

Thanks for the advice. Yes that’s pretty much the first thing I did. I had spent many hours on logical methodical processes of elimination to no avail before I posted here. Although I appreciate why you might assume otherwise.

The only conclusion so far is that the problem does not exist with the 2.41 core files in place and does exist with 2.7 in place. I am quite content that there is something I will have to change so I can run with 2.7 and beyond, but I need to identify the cause.

It’s one of those things that just shouldn’t be happening. But it’s pointing to some change to the way links are being handled in the admin area that is causing an issue with htaccess rewrite blocks that have always worked perfectly - and should continue to do so.

I have subsequently noticed that if I click on the ‘media’ link in admin the rewrite is perfect, if I click on pretty much any other link in the left menu the rewrite gets messed up - any clue there?

Meantime I will see if I can get an AI comparison of relevant files from the 2.41 and 2.70 release zips to look for any changes that might be relevant to this issue.

Fixed. The clue was in the “wp-admin-canonical” link in the source of rendered admin pages.

Which eventually lead to the source of the issue in misc.php:

v2.41:

$current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );

v2.70:

$current_url = admin_url( preg_replace( '#^[^?]*/wp-admin/#i', '', $_SERVER['REQUEST_URI'] ) );

I switched that one line back to the 2.41 version and the issue immediately vanished.

I checked with AI which confirmed the 2.70 line would have messed with rewrites in certain circumstances.

So nothing to do with my plugins or htaccess, or anything this side that I’ve wasted hours eliminating.

At least it’s a simple patch.

>I checked with AI which confirmed the 2.70 line would have messed with rewrites in certain circumstances.

Please paste what your AI said.

And does the following code work for you?

$current_url = admin_url( ltrim( preg_replace( '#^.*?/wp-admin/#i', '', $_SERVER['REQUEST_URI'] ), '/' ) );

I did not copy everything the AI said, I was content with the gist of it.

I tried the line of script you posted and the issue returned.

To be helpful I just asked the same AI model to provide the same analysis:

tell me why the second of these lines is likely to cause issues with htaccess rewrites on apache and why the first would not cause the same issues: $current_url = set_url_scheme( ‘http://’ . $_SERVER[‘HTTP_HOST’] . $_SERVER[‘REQUEST_URI’] ); and 2nd line: $current_url = admin_url( preg_replace( ‘#^[^?]*/wp-admin/#i’, ‘’, $_SERVER[‘REQUEST_URI’] ) );

The first line just rebuilds the current request URL from the request host plus the raw request path/query, then normalizes the scheme. It doesn’t assume anything about WordPress directory structure, and it doesn’t rewrite the path at all.

The second line is riskier because it:

  • Strips a /wp-admin/ prefix with a regex. If the incoming URL doesn’t match that exact pattern, or matches unexpectedly, the resulting path can be wrong.

  • Passes the result into admin_url(), which adds WordPress admin path logic on top of an already-manipulated REQUEST_URI. That can produce URLs that differ from the actual Apache request path.

  • Can interact badly with htaccess rewrite rules if Apache/WordPress are already rewriting requests to /wp-admin/, because the code is effectively reconstructing an admin URL from a rewritten URI rather than from the original request target.

  • Breaks more easily in subdirectory installs or custom admin paths, where wp-admin is not where the URI logic expects it to be.

Why the first avoids the same issue:

  • It uses $_SERVER['REQUEST_URI'] directly, so it preserves the exact path Apache received.

  • It doesn’t try to “correct” or reinterpret the path.

  • set_url_scheme() only changes the scheme (http/https); it doesn’t alter routing-relevant parts of the URL.

In short: the first line is passive and preserves the request; the second is active and rewrites the request path, which is where htaccess/Apache mismatches tend to happen.

If you want, I can also show a concrete example of how each line transforms the same request URL.

Could this in some cases lead to redirect loop issues and 500

Yes.

If the second line builds a URL that differs from what Apache/WordPress thinks the “correct” admin URL is, it can trigger repeated redirects between:

  • the rewritten request path,

  • the admin_url()-generated target,

  • and whatever .htaccess / WordPress rules are enforcing.

That can become a redirect loop, and if the loop hits rewrite recursion or repeated PHP-side redirects, it can surface as a 500 error.

Common ways this happens:

  • REQUEST_URI is already rewritten, but the code rewrites it again.

  • A proxy / SSL / subdirectory setup makes the generated URL slightly different from the incoming one.

  • The regex strips too much or too little, so each pass produces a new “corrected” URL.

The first line is much less likely to do that because it doesn’t change the path logic, only the scheme.

Since you haven’t said what your rewrite rules are (and that AI stuff is the same generic response I got before I posted my previous response), it’s not terribly helpful in enabling us to work out whether we can improve our current code.

The point is that the new URL works much better in many other scenarios, as you’ll also find that AI will tell you if you ask it. You’ll also find an open issue on WP asking for the URL that CP now has because it enables working with reverse proxies.

But, whether you like the change or not, since you’ve looked at the new code, you’ll probably also have seen that it’s followed by a filter. You can use that to get what you want without having to patch core (which will just get overwritten by the next update).