htaccess - cut out the question mark if there is one at the end

Viewed 41

There is such a code

<IfModule mod_rewrite.c>
RewriteCond %{QUERY_STRING} !^$
RewriteCond %{QUERY_STRING} !(^|&)srp=
RewriteCond %{QUERY_STRING} !(^|&)q=
RewriteRule ^(.+?)\.html$ https://%{HTTP_HOST}/$1.html? [L,R=301]
</IfModule>

<IfModule mod_rewrite.c>
RewriteRule ^(.+?)\.html(?!/amp/).+$ https://%{HTTP_HOST}/$1.html? [L,R=301]
</IfModule>

It works perfectly, but if the link is like this:

website.com/post.html?

In this case, the question mark remains. How can I delete it in this case?

1 Answers

You can't simply check for an empty query string since the QUERY_STRING server variable is defined and empty regardless of whether the trailing ? is present or not.

To remove a stray ? at the end of the URL-path (essentially an empty query string) you can check against THE_REQUEST server variable. For example:

RewriteCond %{THE_REQUEST} \s[^?]*\?\s
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [QSD,L,R=301]

The QSD (Query String Discard) flag removes the query string. This is the preferred way to remove the query string on Apache 2.4, as opposed to appending a ? to the substitution string.

THE_REQUEST contains the first line of the HTTP request headers and contains a string of the form:

GET /post.html? HTTP/1.1

So, the regex \s[^?]*\?\s matches a literal ? followed by a space at the end of the URL-path (avoiding a ? that could occur at the end of a non-empty query string). For example:

  • /post.html? redirected to /post.html
  • /post.html?foo=1? - no redirect, since the final ? is part of the foo URL parameter value.

Aside: You shouldn't surround each block in <IfModule mod_rewrite.c> wrapper unless the directives are optional. (And even then the directives should be grouped together.)

Related