1

I have a blog, the pages are suppose to redirect to 'pretty URLS' like the following:

https://www.example.org/blog-post-title

I am using this code:

RewriteEngine On

# SSL
RewriteCond %{HTTPS} off 
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# GENERAL
RewriteRule ^([a-z-0-9]+)$ post.php?blog_slug=$1
RewriteRule ^top-picks$ top.php
RewriteRule ^privacy-policy$ privacy.php
RewriteRule ^sitemap$ sitemap.php
RewriteRule ^([a-z-A-Z-0-9]{8})$ link.php?redirect=$1

I have used it many times before (in one variation or another) - but it is adding a trailing slash and not finding the page everytime like so:

https://www.example.org/blog-post-title/

Anyone have any idea what I am doing wrong?? The other pages work just fine - the code on the post.php page is calling the $_GET variable correctly, I can't seem to get rid of the trailing slash and it doesn't happen on any of my other sites?!

MrWhite
  • 43,179
  • 8
  • 60
  • 84
  • Welcome to SO, thanks for adding your efforts/htacces file. Do you have any other rules in this .htaccess file apart from shown ones? OR do you have any other .htacces file also in your environment? Please confirm once. – RavinderSingh13 Mar 08 '23 at 04:33
  • 1
    That is the whole of it - and no other .htaccess files – Josh Magness Mar 08 '23 at 04:43
  • So you mean you are hitting sample URL `https://www.example.org/blog-post-title/` and its not removing trailing slashes in it? OR it even adds slashes to the end of a URL which doesn't have them? – RavinderSingh13 Mar 08 '23 at 04:45
  • It is adding it, I don't have it in the link. When I hover over the link (and in the code) there is no trailing slash at the end – Josh Magness Mar 08 '23 at 04:47
  • Kindly do check link https://stackoverflow.com/questions/71212482/remove-trailing-slash-after-directory-with-htaccess once if this helps you, cheers. – RavinderSingh13 Mar 08 '23 at 04:55
  • Thanks, it does not - tried that one already. It creates a loop and then just a page error. – Josh Magness Mar 08 '23 at 04:58
  • ok sure, I have posted an answer now. We could discuss it there, cheers. – RavinderSingh13 Mar 08 '23 at 05:03
  • For starters, you are doing things in the wrong order. The pattern `^([a-z-0-9]+)$` matches on `top-picks`, `privacy-policy` or `sitemap` already - so it will never get to the specific rules for those. Put them _before_ the more generic stuff. – CBroe Mar 08 '23 at 07:13
  • What are the actual links in your HTML pointing to - is that `/blog-post-title`, or perhaps `/blog-post-title/` already? – CBroe Mar 08 '23 at 07:16

2 Answers2

0

With your shown samples and attempts please try following .htacess rules file. Please make sure to clear your browser cache before testing your URLs.

RewriteEngine On

# SSL
RewriteCond %{HTTPS} off 
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# GENERAL
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-z-0-9]+)$ post.php?blog_slug=$1 [NC,QSA,L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^top-picks$ top.php  [NC,QSA,L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^privacy-policy$ privacy.php  [NC,QSA,L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^sitemap$ sitemap.php  [NC,QSA,L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-z-A-Z-0-9]{8})$ link.php?redirect=$1  [NC,QSA,L]
RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93
  • Thanks for this - it didn't work though. It made all pages link to the post.php page, and the actual post STILL had a trailing slash at the end. – Josh Magness Mar 08 '23 at 05:12
  • Oddly enough if I add a slash at the start of the rewrite with a fake folder it works just fine. – Josh Magness Mar 08 '23 at 05:14
  • RewriteRule ^/post/([a-z-0-9]+)$ post.php?blog_slug=$1 – Josh Magness Mar 08 '23 at 05:14
  • @JoshMagness starting with `/post/` it would not match your `/blog-post-title` any more to begin with, plus when configured in .htaccess, the path a RewriteRule checks against _never_ starts with a trailing slash. So this rule simply does nothing any more, you might as well have commented it or removed it instead. – CBroe Mar 08 '23 at 07:15
0

There is nothing in your .htaccess file that appends a trailing slash. However, Apache (mod_dir) will append the trailing slash (with a 301 redirect) if /blog-post-title happens to exist as a physical directory on the filesystem. (You also state that "the other pages work just fine".)

In this case, attempting to remove the trailing slash (without first setting DirectorySlash Off) will result in a redirect loop.

If this is the case then you need to remove/rename the physical filesystem directory.

But note that this "permanent" redirect will have been cached persistently by the browser and any intermediary caches, so you will need to make sure any caches are cleared after resolving the cause of the redirect.

RewriteRule ^([a-z-0-9]+)$ post.php?blog_slug=$1
RewriteRule ^top-picks$ top.php
RewriteRule ^privacy-policy$ privacy.php
RewriteRule ^sitemap$ sitemap.php
RewriteRule ^([a-z-A-Z-0-9]{8})$ link.php?redirect=$1

However, there are other errors with your rules that will prevent them from working as intended...

  1. [a-z-0-9] - Hyphens (-) in a regex character class are a special meta character that indicates a range of characters, eg. a-z. To match a literal hyphen it should be at the start or end of the character class OR backslash-escaped. You have an unescaped hyphen in the middle of the character class. As it happens this does actually match a literal hyphen in this case, but it is arguably ambiguous (and you run the risk of inadvertently matching a range of characters). However, in the last rule you have two unescaped hyphens (you have interspersed every character with a hyphen), which makes me wonder what the true intention is here? Again, as it happens these two unescaped hyphens match a literal hyphen (although I have doubts whether that is intentional)?

  2. Coupled with point #1, these rules are in the wrong order. The first rule will match top-picks, privacy-policy and sitemap, rewriting all requests to post.php. Consequently, the last rule (that rewrites to link.php) will never be processed unless the requested URL contains an uppercase letter. The last rule should be before the first rule (but the first "generic" rule should be last).

  3. You are missing the L flag on all the rewrites. Not that this should cause a problem in this particular instance (since the rewritten URL contains a dot and none of the patterns match a dot), it could cause an issue in the future and the very least it results in additional (unnecessary) processing.

Your rules should be rewritten like this instead:

Options -MultiViews

RewriteEngine On

# SSL
RewriteCond %{HTTPS} off 
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# GENERAL
RewriteRule ^top-picks$ top.php [L]
RewriteRule ^privacy-policy$ privacy.php [L]
RewriteRule ^sitemap$ sitemap.php [L]
RewriteRule ^([a-zA-Z0-9]{8})$ link.php?redirect=$1 [L]
RewriteRule ^([a-z0-9-]+)$ post.php?blog_slug=$1 [L]

I've assumed that 8-character URLs that should be passed to link.php do not contain hyphens.

I've also disabled MultiViews (it may be disabled anyway - but to be sure) since you are also dealing with extensionless URLs (eg. sitemap to sitemap.php). If MultiViews is enabled then this will conflict with your mod_rewrite rules.

MrWhite
  • 43,179
  • 8
  • 60
  • 84