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
With your shown samples, could you please try following.
Please make sure to clear your browser cache before testing your URLs.
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:
There’s no need to use the
L
andEND
flags together. TheL
flag stops the current round of processing and theEND
flag stops all further processing by the rewrite engine. However, when used together with theR
flag they behave exactly the same – all further processing is stopped regardless of whether you useL
orEND
flag.query=[a-zA-Z0-9s]*$
– You’ve used thes
(whitespace) shorthand character class – this is superfluous as it will never match here. (Can your query string value actually contain spaces?) TheQUERY_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 theRewriteRule
directive is superfluous since you are matching "everything" anyway (ie..*
). I’d wager this is entirely superfluous anyway, since you are not using theNC
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 theRewriteRule
pattern.