mod_rewrite add trailing slash except for search/query URL's

I want this:
http://www.example.com/blog

to 301 redirect to:
http://www.example.com/blog/

I want this:
http://www.example.com/shop/?query=abc
to stay as-is.

I do not want the above to 301 redirect to:
http://www.example.com/shop/?query=abc/

Thanks.

champ,

Is blog a directory? If so, Apache will do that for you while being annoyed that someone would not provide the correct URI for the directory … AND specify the file in that directory (except via DirectoryIndex). IMHO, poor technique for a webmaster.

If not, are you using MultiViews?

Please explain your intent to make it easier to provide help.

Regards,

DK

Thanks for responding DK. blog is directory. MultiViews is disabled. I know how to redirect a directory from no-slash to slash. But I’m not sure how to have the add trailing slash mod_rewrite code ignore url’s containing a question mark. If it’s a question mark it’s a search query and I wouldn’t want a forward slash added to the end. So basically, add a trailing slash to every URL that’s 1) not a query url and 2) is missing a trailing slash.

Thanks.

Hi Champ,

I am just learning this so it may not make sense, but will this work for you? It worked when I test it.


RewriteEngine On
RewriteBase /
# Check if query string exists
RewriteCond %{QUERY_STRING} ^$ 
# When REQUEST_URI does not have a trailing slash
RewriteCond %{REQUEST_URI} !(.*)/$
#Does the 301 redirect to the url with the appended trailing slash (replace your domain). 
RewriteRule ^(.*)$ http://your_domain.com/$1/

@ServerStorm; how about regular files? :wink:

Also, your redirect is 302 (Apache default for RewriteRule) and not 301.
To make it a 301, add [R=301]

Ok going for it :slight_smile:


RewriteEngine On
RewriteBase /
# Check if query string exists
RewriteCond %{QUERY_STRING} ^$ [OR]
RewriteCond %{REQUEST_FILENAME} ^$
# When REQUEST_URI does not have a trailing slash
RewriteCond %{REQUEST_URI} !(.*)/$
#Does the 301 redirect to the url with the appended trailing slash (replace your domain). 
RewriteRule ^(.*)$ http://your_domain.com/$1/ [NC,L,R=301]

Unfortunately I did this post from my phone and didn’t have a way to test, but does this get it done?

Regards,
Steve

Not quite :wink:


RewriteEngine On

# Check if query string exists
RewriteCond %{QUERY_STRING} ^$

[COLOR="#FF0000"]# Check that the request is not for an existing file
RewriteCond %{REQUEST_FILENAME} !-f[/COLOR]

# When REQUEST_URI does not have a trailing slash
RewriteCond %{REQUEST_URI} !/$

#Does the 301 redirect to the url with the appended trailing slash (replace your domain). 
RewriteRule .? http://your_domain.com%{REQUEST_URI}/ [NC,L,R=301]

  1. I’ve removed the RewriteBase – not really needed
  2. The [OR] on the %{QUERY_STRING} wasn’t correct; all conditions need to hold for the RewriteRule to fire
  3. Use %{REQUEST_FILENAME} !-f to check that the request is not for an existing file
  4. If you’re not interested in part of the URL, don’t match it and don’t create a backreference. i.e., instead of RewriteCond %{REQUEST_URI} !(.*)/$ just use RewriteCond %{REQUEST_URI} !/$ – does exactly the same but is lighter since it only has to check the last character of the string
  5. Instead of (.*) … $1 use .? … %{REQUEST_URI} – faster as it doesn’t create new variables but just uses variables already available in mod_rewrite. Again, if you don’t really care about it, don’t match it :slight_smile:

But, really not bad for someone who’s learning. I’ve seen a LOT worse :slight_smile:

Wow! Thanks ScallioXTX!

Solved it for the OP, and taught me at the same time. Way to go.

I understand your recommendations and will try to think in this 'lets use “less hungry” regex to perform similar tasks to their greety cousins.

Regards,
Steve

Rémon,

Aw, you know to NEVER use the No Case flag in a RewriteRule because Apache is case sensitive. It won’t make any difference to your code, however, as and your .? already matched ANYTHING.

SS,

I could have modified your code like this:

RewriteEngine [COLOR="#0000FF"]o[/COLOR]n
[COLOR="#FF0000"]RewriteBase /[/COLOR]
# Check if query string exists
RewriteCond %{QUERY_STRING} !. [COLOR="#FF0000"][OR][/COLOR]
[COLOR="#FF0000"]RewriteCond %{REQUEST_FILENAME} ^$[/COLOR]
# When REQUEST_URI does not have a trailing slash
RewriteCond %{REQUEST_URI} ![COLOR="#FF0000"](.*)[/COLOR]/$
#Does the 301 redirect to the url with the appended trailing slash (replace your domain).
RewriteRule ^.? %{REQUEST_URI}/ [[COLOR="#FF0000"]NC,[/COLOR]L,R=301]

Of course, I MUST reiterate my constant admonition NOT to use a trailing / (except on a directory (-d)) as that will tell visitor browsers to look for relatively linked files in the wrong place (generating a lot of 404’s and broken web pages).

Others,

No Case is to be used with strings like {HTTP_HOST} which are case insensitive. Please reserve NC to those strings so you aren’t hit with unanticipated problems.

Regards,

DK