Search code examples
apache.htaccesshttp-redirectmod-rewritemod-alias

htaccess redirect doesn't work: Too many redirects


How we can redirect an old URL with // to have only one /

From:

https://www.example.com/maincategory//subcategory/

To:

https://www.example.com/maincategory/subcategory/

This solution has too many redirects:

Redirect 301 /maincategory//subcategory/ /maincategory/subcategory/

Solution

  • You can use mod_rewrite to do this. Try the following, at the top of the root .htaccess file:

    RewriteEngine on
    
    RewriteCond %{THE_REQUEST} "^GET /maincategory//subcategory/"
    RewriteRule (.*) /$1 [R=302,L]
    

    This uses the "feature" that the URL-path matched by the RewriteRule pattern has already had multiple slashes reduced. We then redirect back to this same URL-path using the $1 backreference. The redirect loop is prevented by checking that the actual URL requested contains the double slash (as stored in the THE_REQUEST server variable).

    THE_REQUEST server variable contains the first line of the HTTP request headers. And, importantly, is not processed.

    Note that I've omitted the end-of-string anchor ($), so the above will match /maincategory//subcategory/<anything> and redirect accordingly. If you specifically want to only match /maincategory//subcategory/ then include a space (although space + "HTTP" is easier to read) at the end of the CondPattern. For example:

    RewriteCond %{THE_REQUEST} "^GET /maincategory//subcategory/ HTTP"
    

    Clear your browser cache before testing. Test with 302 (temporary) redirects to avoid caching issues.

    This solution has too many redirects:

    Redirect 301 /maincategory//subcategory/ /maincategory/subcategory/
    

    It would seem that Apache reduces multiple slashes in both the requested URL-path and the URL-path supplied to the Redirect directive before matching, so you end up with a redirect loop.