3
votes

Im having an issue with my joomla site. At first it would create duplicates of urls with and without trailing slash. So I implemented some htaccess code to force a trailing slash. Then it was causing soft 404s that is, if I entered a non existent page the status in my crawler was actually 200 for these non existing pages, but it was just a 404 page template. Not a hard 404. So I changed that in the "error.php" file.

However the issue is that when I enter any non-existent url like "domain.com/nonexistentpage" (without a trailing slash) it first redirects it via the 301 rule to the "domain.com/nonexistentpage/" and THEN returns a 404.

If I stop the redirecting of pages, than that same URL "domain.com/nonexistentpage" will return a hard 404 as expected, but the URLs wont redirect to the trailing slash version (which I need). However if I redirect it, it will 301 before 404ing.

I dont have any pages on my site that are not without a trailing slash, so I want all pages that dont exist to go straight to my "error.php" file and be excepted from the 301 rule. How would I do this? Here is my coded attempt

RewriteCond %{REQUEST_URI} !-d 
RewriteCond %{REQUEST_URI} !-f 
RewriteRule .? - [S=1] 
RewriteCond %{REQUEST_URI} !(.*)/$ 
RewriteRule ^(.*)$ http://www.domainxyz.com/$1/ 
RewriteRule .+ - [L]

Im very inexperienced with htaccess. the idea was that if the file is non existent that the slash rewrite rule should be ignored.

2
I'm not convinced you can daisy chain a skip onto a RewriteCond like that... - CD001
In this case the skip command works however, it picks up even the real files and folders as non-existent and they all skip the rewrite rule, so only the last rewrite rule is applied to all pages and they all return 404's. - Ahmed Gilani

2 Answers

0
votes

If you look at it another way, I think what you're saying is:

  1. If the REQUEST_FILENAME is a file or directory
  2. and REQUEST_URI doesn't have a trailing slash

Then 301 to the same URL with the trailing slash...

Which translates to:

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d 
RewriteCond %{REQUEST_URI} !.*/$
RewriteRule ^(.*)$ /$1/ [R=301,L]

Because [OR] takes precedence over the implicit [AND] the rewrite conditions are basically read as (#1 OR #2) AND #3


Though actually your original method works with a small tweak:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .? - [S=1]
RewriteRule ^(.*[^/])$ /$1/ [R=301,L]

Just ditch that final rewrite condition and change the rule slightly so that it only matches when there's not a trailing slash.

0
votes

Still have not been able to solve this. I did notice one thing. If I add .html extension to each page then these redirect rules work. AKA the existent and non existent files are correctly separated by htaccess and rules applied accordingly. But if I leave them as is ending with a forward slash, it does not matter whether I add a condition first to check of the file or directory is real or not. They ALL redirect and THEN it 404s the nonexistent urls, but not 404 right away.... Cant understand what the issue could be.