HTaccess - Trailing slash + .php + anchors (ExpressionEngine) - .htaccess

I just started a project from another webmaster work (i hate patching other's stuff ::sad::) and i have some issues. First we are on expression engine 1.x .
My problem: There is a trailing slash redirection in the .HTACCESS, but my users need to have access to only one .php page (www.mydomain.com/mobile/index.php) but the link is redirected to /index.php/, another problem is the anchors are changed to the same way (www.mydomain.com/somepage/#anchor1) to /#anchor1/
So my question is... there is a way to put exception into trailing slash redirection code? I mean i just have to fix it in few pages. Take note that our expression engine remove all the index.php to have links like www.mydomaine/contact/, www.mydomaine/about/, www.mydomaine/infos/ , ect.
Currently the htaccess trailling code is :
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule ^(.*)$ $1/ [L,R=301]
P-S: we have a code that remove index.php too:
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5})$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} ^/(members|P[0-9]{2,8}) [NC]
RewriteRule ^(.*)$ /index.php/$1 [L]
Thx for help!

Is there a valid reason trailing slashes in URLs need to be enforced? If not, I would just remove the rewrite rule and your problem is solved :)
Most ExpressionEngine URLs will work with or without trailing slashes.
The easiest fix to this problem would be remove the overzealous trailing slash redirection, and replace it with a more relaxed version:
<IfModule mod_rewrite.c>
# Enable Apache's RewriteEngine
RewriteEngine On
# Add Trailing Slashes to URLs
RewriteCond %{REQUEST_METHOD} !=POST
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+[^/])$ /$1/ [R=301,L]
# ExpressionEngine Remove index.php from URLs
RewriteCond %{REQUEST_METHOD} !=POST
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
</IfModule>
Using the above code, example.com/mobile/index.php will not get rewritten to example.com/mobile/index.php/, nor will pages with anchors example.com/page/#anchor1.
EE doesn't know the difference between URIs like /mobile versus /mobile/, web analytics apps and search engines may consider these separate web pages. If you're developing a static website, this isn't a big deal, because if you attempt to go to the former URI (sans trailing slash), Apache will automatically redirect the client to the latter (with trailing slash).
But for a web application like EE, where everything in the URI after index.php is handled by the application rather than Apache, this redirection is left up to you. Just like the decision to use or not use a www subdomain, it doesn't matter whether you choose to force a trailing slash or vise-versa; it just matters that you enforce one or the other.
Sidenote: in EE1, trailing slashes are generated in URLs produced by
ExpressionEngine; in EE2, trailing slashes are not generated. The exception
is the Structure Module, which outputs URLs with trailing slashes
in both EE1 and EE2.

Related

How to clean url to accept ending slash or not with .htaccess

How do I clean URL
http://localhost/mysitedirectory/contacts.php
to look like both:
http://localhost/mysitedirectory/contacts
http://localhost/mysitedirectory/contacts/
I want this because a user may add the ending trailing slash or leave it so I want .htaccess to configure such that it works both ways.
I noticed when I add the / at the end of the contacts it says "OBJECT NOT FOUND"...Error 404
How do I make it work even if I add the slash or not?
this is what I tried:
RewriteEngine On
Options -Indexes
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^contacts$ contacts.php [L,QSA,NC]
RewriteRule ^home$ index.php [L,QSA,NC]
CBroe answered in a comment section:
^contacts/?$ - slash at the end, made optional by the following quantifier question mark.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^contacts$ contacts.php [L,QSA,NC]
RewriteRule ^home$ index.php [L,QSA,NC]
The two RewriteCond directives (filesystem checks) are entirely superfluous and should be removed. (As are the QSA flags on the RewriteRule directives.)
However, instead of allowing both /contacts and /contacts/ (strictly speaking two different URLs) resolve to the same content (which would necessitate the need for a rel="canonical" tag) you should externally redirect from one to the other (canonical) URL.
By the look of it, the URL without the trailing slash is canonical, so remove the trailing slash with an external redirect. The only thing to be careful of is that you should not remove the trailing slash from physical directories (which would ordinarily cause a redirect loop).
For example:
Options -Indexes -MultiViews
RewriteEngine On
# Canonical redirect to remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.+)/$ /$1 [R=301,L]
# Internal rewrites
RewriteRule ^contacts$ contacts.php [L,NC]
RewriteRule ^home$ index.php [L,NC]
The NC flag on the RewriteRule directives makes contacts, CONTACTS and CoNtAcTs all resolve to the same content. (So the rel="canonical" tag is still required to resolve this ambiguity.)

.htaccess redirect all subdirectories to root (Kinda)

This is not as straight forward as the title might imply. I'll try to explain.
I'm currently working on a video website based on rewritten urls.
I'm using this rule currently:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond
%{REQUEST_FILENAME} !-d
RewriteRule ^(.*) index.php?url=$1 [L,QSA]
This is used to let users access videos with good looking urls like this:
domain.com/kJbSGe5X instead of domain.com/?v=kJbSGe5X or domain.com/index.php?v=kJbSGe5X for example.
Now the problem is that whenever a trailing slash is added, the css breaks.
I've tried solutions like adding a slash in front of the css url, like this:
<link href="/css/bootstrap.css" rel="stylesheet">
... but it's not working.
Could a solution be to rewrite all urlstrings after a trailing slash (including the trailing slash) to the same url, without the trailing string? Like this:
domain.com/kJbSGe5X/ or domain.com/kJbSGe5X/randomchars to this:
domain.com/kJbSGe5X - and how would I go about doing so?
I guess there probably is much better solutions to this problem, but I'm rather new at this.
Any help is appreciated.
Thanks in advance!
--EDIT--
I would prefer a solution where everything after a trailing slash gets redirected to the same url without the trailing slash + any string after the trailing. (If there is no content in said url)
I might have put to much emphasis on the css issue - A rule like this would work great with how my website is setup.
Insert this rule before your existing rule to remove any trailing slash:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{THE_REQUEST} \s/+([^/]+)/.*?\sHTTP/ [NC]
RewriteRule ^ /%1? [R=301,L]
You could try ignoring the css directory in your rewrite rule:
RewriteCond %{REQUEST_URI} !^/css/
This isn't exactly what you asked for but if you excluded specific directories from your rewrite rule (probably /css, /js and so on) then you would not have to worry about formatting your nice/short view URLs to remove anything after the slash or whatever else.
Here is my complete solution. With a little help from anubhava!
Remove trailing slash from all urls:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{THE_REQUEST} \s(.+?)/+[?\s]
RewriteRule ^ %1? [R=301,L]
Constrain the "create goodlooking" urls thingy to only work when it's 8 characters (which is the length of each shortlink for videos):
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.{8})$ index.php?url=$1 [QSA,L]

Getting the trailing slash back in ExpressionEngine 2?

I have just upgraded from EE 1 to EE 2 and I am struggling with some of the changes. For example, the fact that EE no longer outputs a trailing slash on its urls is making a mess of a lot of my links where I had depended on constructions like EE generated url + additional segment. Finding and editing all places where I have done that would be a small nightmare considering the size and setup of my site. Is there any way to hack EE to get back the old behaviour?
For some the trailing slash addition mentioned might cause conflicts with some forms. Adding the following to check if the request is a GET might be safer.
# Add a trailing slash to paths without an extension
RewriteCond %{THE_REQUEST} ^GET
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule ^(.*)$ $1/ [L,R=301]
There is an .htaccess solution to this, which I've used in my older EE sites because of this issue exactly.
Add trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule ^(.*)$ $1/ [L,R=301]
Source: http://devot-ee.com/articles/item/simple-htaccess-for-expressionengine-sites
However, since it's there by default in EE2, you might want to do the OPPOSITE and remove the trailing slash via .htaccess so you don't have to manually add/delete/whatever. If you decide on that, here's the code:
Remove Trailing Slash
RewriteCond %{HTTP_HOST} !^\.yoursite\.com$ [NC]
RewriteRule ^(.+)/$ http://%{HTTP_HOST}/$1 [R=301,L]
Source: http://ee-spotlight.com/tips/a_standard_htaccess_file_with_expressionengine

mod rewrite to remove file extension, add trailing slash, remove www and redirect to 404 if no file/directory is available

I would like to create rewrite rules in my .htaccess file to do the following:
When accessed via domain.com/abc.php: remove the file extension, append a trailing slash and load the abc.php file. url should look like this after rewrite: domain.com/abc/
When accessed via domain.com/abc/: leave the url as is and load abc.php
When accessed via domain.com/abc: append trailing slash and load abc.php. url should look like this after rewrite: domain.com/abc/
Remove www
Redirect to 404 page (404.php) when accessed url doesn't resolve to folder or file, e.g. when accessing either domain.com/nothingthere.php or domain.com/nothingthere/ or domain.com/nothingthere
Make some permanent 301 redirects from old urls to new ones (e.g. domain.com/abc.html to domain.com/abc/)
All php files sit in the document root directory, but if there is a solution that would make urls such as domain.com/abc/def/ (would load domain.com/abc/def.php) also work it would be great as well, but not necessary
So here is what I have at the moment (thrown together from various sources and samples from around the web
<IfModule mod_rewrite.c>
RewriteCond %{HTTPS} !=on
# redirect from www to non-www
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
# remove php file extension
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{THE_REQUEST} ^GET\ /[^?\s]+\.php
RewriteRule (.*)\.php$ /$1/ [L,R=301]
# add trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.*[^/]$ /$0/ [L,R=301]
# resolve urls to matching php files
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*)/$ $1.php [L]
With this the first four requirements seem to work, whether I enter domain.com/abc.php, domain.com/abc/ or domain.com/abc, the final url always ends up being domain.com/abc/ and domain.com/abc.php is loaded.
When I enter a url that resolves to a file that doesn't exists I'm getting an error 310 (redirect loop), when really a 404 page should be loaded. Additionally I haven't tried if subfolders work, but as I said, that's low priority. I'm pretty sure I can just slap the permanent 301 redirects for legacy urls on top of that without any issues as well, just wanted to mention it. So the real issue is really the non working 404 page.
I've had problems with getting ErrorDocument to work reliably with rewrite errors, so I tend to prefer to handle invalid pages correctly in my rewrite cascade. I've tried to cover a fully range of test vectors with this. Didn't find any gaps.
Some general points:
You need to use the DOCUMENT_ROOT environment variable in this. Unfortunately if you use a shared hosting service then this isn't set up correctly during rewrite execution, so hosting providers set up a shadow variable to do the same job. Mine uses DOCUMENT_ROOT_REAL, but I've also come across PHP_DOCUMENT_ROOT. Do a phpinfo to find out what to use for your service.
There's a debug info rule that you can trim as long as you replace DOCROOT appropriately
You can't always use %{REQUEST_FILENAME} where you'd expect to. This is because if the URI maps to DOCROOT/somePathThatExists/name/theRest then the %{REQUEST_FILENAME} is set to DOCROOT/somePathThatExists/name rather than the full pattern equivalent to the rule match string.
This is "Per Directory" so no leading slashes and we need to realise that the rewrite engine will loop on the .htaccess file until a no-match stop occurs.
This processes all valid combinations and at the very end redirects to the 404.php which I assume sets the 404 Status as well as displaying the error page.
It will currently decode someValidScript.php/otherRubbish in the SEO fashion, but extra logic can pick this one up as well.
So here is the .htaccess fragment:
Options -Indexes -MultiViews
AcceptPathInfo Off
RewriteEngine On
RewriteBase /
## Looping stop. Not needed in Apache 2.3 as this introduces the [END] flag
RewriteCond %{ENV:REDIRECT_END} =1
RewriteRule ^ - [L,NS]
## 302 redirections ##
RewriteRule ^ - [E=DOCROOT:%{ENV:DOCUMENT_ROOT_REAL},E=URI:%{REQUEST_URI},E=REQFN:%{REQUEST_FILENAME},E=FILENAME:%{SCRIPT_FILENAME}]
# redirect from HTTP://www to non-www
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
# remove php file extension on GETs (no point in /[^?\s]+\.php as rule pattern requires this)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_METHOD} =GET
RewriteRule (.*)\.php$ $1/ [L,R=301]
# add trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.*[^/]$ $0/ [L,R=301]
# terminate if file exists. Note this match may be after internal redirect.
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L,E=END:1]
# terminate if directory index.php exists. Note this match may be after internal redirect.
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{ENV:DOCROOT}/$1/index.php -f
RewriteRule ^(.*)(/?)$ $1/index.php [L,NS,E=END:1]
# resolve urls to matching php files
RewriteCond %{ENV:DOCROOT}/$1.php -f
RewriteRule ^(.*?)/?$ $1.php [L,NS,E=END:1]
# Anything else redirect to the 404 script. This one does have the leading /
RewriteRule ^ /404.php [L,NS,E=END:1]
Enjoy :-)
You'll probably want to check if the php file exists before adding the tailing slash.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^.*[^/]$ /$0/ [L,R=301]
or if you really want a tailing slash for all 404 pages (so /image/error.jpg will become /images/error.jpg/, which I think is weird):
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.*[^/]$ /$0/ [L,R=301]
I came up with this:
DirectorySlash Off
RewriteEngine on
Options +FollowSymlinks
ErrorDocument 404 /404.php
#if it's www
# redirect to non-www.
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ http://%1%{REQUEST_URI} [L,R=301,QSA]
#else if it has slash at the end, and it's not a directory
# serve the appropriate php
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1.php [L,QSA]
#else if it's an existing file, and it's not php or html
# serve the content without rewrite
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_URI} !(\.php)|(\.html?)$
RewriteRule ^ - [L,QSA]
#else
# strip php/html extension, force slash
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.*?)((\.php)|(\.html?))?/?$ /$1/ [L,NC,R=301,QSA]
Certainly not very elegant (env:redirect_status is quite a hack), but it passes my modest tests. Unfortunately I can't test the www redirection, as I'm on localhost, and has no real access to a server, but that part should work too.
You see, I used the ErrorDocument directive to specify the error page, and used the DirectorySlash Off request to make sure Apache doesn't interfere with the slash-appending fun. I also used the QSA (Query String Append) flag that, well, appends the query string to the request so that it's not lost. It looks kind of silly after the trailing slash, but anyhow.
Otherwise it's pretty straightforward, and I think the comments explain it pretty well. Let me know if you run into any trouble with it.
Create a folder under the root of the domain
Place a .htaccess in the above folder as RewriteRule ^$ index.php
Parse the URL
With PHP coding you can now strip the URL or file extension as required

Trying to add trailing slash with htaccess, results in a absolute path

What I'm trying to achive is to have all urls on my page look like http://domain.com/page/, no extensions, but a trailing slash. If a user happends to write http://domain.com/page or http://domain.com/page.php it will redirect to the first url. After some googling i found this code, and it's close to working, but when you leave out the trailing slash in your request the url becomes something like http://domain.com/Users/"..."/page/ and therefor returns a 404.
My .htaccess looks like this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{THE_REQUEST} ^GET\ /[^?\s]+\.php
RewriteRule (.*)\.php$ /$1/ [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*)/$ $1.php [L]
RewriteCond %{REQUEST_FILENAME} !(.*)/$
RewriteRule (.*)/$ $1.php [L]
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule .*[^/]$ $0/ [L,R=301]
I've been trying to add an additional rule but I really don't get any of this and I haven't been able to find any answers.
For a scenario like this one, the .htaccess author has to consider both what the browser URL bar should display and what file the web server should return/execute. Note also that each external redirect starts the processing of the rewrite directives over.
With that in mind, start by taking care of which file is returned when the URL is in the correct format:
RewriteEngine on
RewriteRule ^/?$ /index.php [L]
RewriteRule ([^./]+)/$ /$1.php [L]
Then, deal with URLs with no trailing slash by redirecting them with [R=301]:
RewriteRule ^/(.*)\.[^.]*$ http://www.example.com/$1/ [R=301,L]
RewriteRule ^/(.*)$ http://www.example.com/$1/ [R=301,L]
Note that the first of these two rules should also take care of the case where there is a filename (like something.php) but also a trailing slash by eliminating the filename extension and re-adding the slash.
Keep in mind that, if your internal directory structure does not match what the web server is serving (as is often the case in shared hosting scenarios), you will likely need to add a RewriteBase directive immediately after the RewriteEngine directive. See the Apache docs for an explanation.

Resources