skip to Main Content

I’m trying to add an anchor to an URL with a query string. The original URL is

https://example.com/foo?query=123

It should redirect to

https://example.com/foo?query=123#anchor

These are my Rules in the .htaccess file:

RewriteCond %{REQUEST_URI} ^/foo$
RewriteCond %{QUERY_STRING}  ^query=[a-zA-Z0-9s]*$
RewriteRule (.*) /foo?%{QUERY_STRING}#anchor [NC,NE,R=302,L,END]

Do you have an idea how to avoid the redirecting loop?

2

Answers


  1. With your shown samples, could you please try following.
    Please make sure to clear your browser cache before testing your URLs.

    RewriteEngine ON
    RewriteCond %{THE_REQUEST} s/([w-]+?query=d+)s [NC]
    RewriteRule ^ %1#anchor [L,R,NE]
    
    Login or Signup to reply.
  2. Do you have an idea how to avoid the redirecting loop?

    This is not possible with a server-side (Apache / .htaccess) redirect, without changing the URL-path or query string in some way.

    The #anchor (or fragment identifier) is not passed to the server in the redirected request, so the same URL matches your rule and triggers another redirect to append #anchor, again and again, etc.

    When you request /foo?query=123, the request is 302 redirected to /foo?query=123#anchor (the rule you’ve posted already does that). However, the browser only sends /foo?query=123 (no fragment identifier) back in the redirected request so the process starts over.

    The only way to prevent the redirect loop in your "server-side" redirect is to change other elements of the URL in someway that you can then detect in you rule. eg. redirect to /bar?query=123#anchor or /foo?query=123&noredirect=1#anchor etc.

    However, fragment identifiers (#anchors) are only used by the client-side script/HTML, so if #anchor is required on the URL then this should be added using JavaScript instead.


    Aside: Just a few notes about your existing rule:

    RewriteCond %{REQUEST_URI} ^/foo$
    RewriteCond %{QUERY_STRING}  ^query=[a-zA-Z0-9s]*$
    RewriteRule (.*) /foo?%{QUERY_STRING}#anchor [NC,NE,R=302,L,END]
    
    • There’s no need to use the L and END flags together. The L flag stops the current round of processing and the END flag stops all further processing by the rewrite engine. However, when used together with the R flag they behave exactly the same – all further processing is stopped regardless of whether you use L or END flag.

    • query=[a-zA-Z0-9s]*$ – You’ve used the s (whitespace) shorthand character class – this is superfluous as it will never match here. (Can your query string value actually contain spaces?) The QUERY_STRING server variable is %-encoded, so there is never a literal space. Any spaces in the requested query string will either be URL encoded as %20 or +.

    • The NC (nocase flag) on the RewriteRule directive is superfluous since you are matching "everything" anyway (ie. .*). I’d wager this is entirely superfluous anyway, since you are not using the NC flag on the preceding condition where it would be required – if at all.

    • (.*) – in the rule as posted there is no need for the parenthesised subpattern (capturing group), since the backreference is not being used anywhere.

    • RewriteCond %{REQUEST_URI} ^/foo$ – there’s no need for this condition as the URL-path can be performed more efficiently in the RewriteRule pattern.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search