htaccess rewriterule being ignored - .htaccess

I have an .htaccess file that is not working properly. And it used to.
Here is the file:
RewriteEngine On
# Category
#Edit
RewriteRule ^edit/([^/]+)/?$ /edit_solutions/index.php?category=$1 [L]
RewriteRule ^edit/?$ /edit_solutions/choose.php [L]
#Report
RewriteRule ^reports/([^/]+)/?$ /report/report.php?project=$1 [L]
RewriteRule ^reports/?$ /report/index.php
#View
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/?$ /view/index.php?category=$1
RewriteRule ^$ /view/choose.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
For some reason, links like mydomain.com/edit/butler/ are going to the view condition, not the edit condition. So the view is picking up the category as edit/butler/. Any ideas why the first condition isn't picking up that url correctly?
Edit: I just checked the $_GET contents, and the category is being set to error.html.

I found out the problem wasn't in fact the htaccess file. There was a file called edit.old.php that was somehow being called. I renamed it to old.edit.old.php (good name, I know), and the site works fine now. Leaving this up for reference

Related

Htaccess rewrite for dynamic file name and rewrite path

I'm trying to do a rewrite, where if the page doesnt exist, it rewrites to a category page. Its a bit different to the normal RewriteCond %{REQUEST_FILENAME} -f as the page name is dynamic based on the URL.
If somebody visits a dynamic path name such as "/contacts"
I first want it to check if the following folder/file exists based on the path name:
/[dynamicpath]/[dynamicpath].php
example:
/contacts/contacts.php
If that doesnt exist, rewrite to the following page
/categories/category/category.php?cat_url=[dynamicpath]
example:
/categories/category/category.php?cat_url=contacts
I've tried the below, but it fails with the first RewriteRule triggering when the file exists and goes straight to the category rewrite.
RewriteCond %{SCRIPT_URL} ^(.+)
RewriteCond %{DOCUMENT_ROOT}/%1/%1.php !-f
RewriteRule (.+)/?$ $1/$1.php [QSA,L]
RewriteRule ^([\w-]+)/?$ /categories/category/category.php?cat_url=$1 [QSA,L]
You may use these rules in your site root .htaccess:
RewriteEngine On
# attempt rewrite to /[dynamicpath]/[dynamicpath].php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1/$1.php -f
RewriteRule ^(.+?)/?$ $1/$1.php [L]
# else rewrite to categories/category/category.php?cat_url=...
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+?)/?$ categories/category/category.php?cat_url=$1 [QSA,L]
I found the answer by checking the server variables being passed and discovered %{REQUEST_FILENAME} included the full file path (document_root+filename).
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}%{REQUEST_URI}.php -f
RewriteRule ^(.+)/?$ $1/$1.php [L]
RewriteRule ^(.+)/?$ categories/category/category.php?cat_url=%{REQUEST_URI} [QSA,L]

Separate .htaccess for folder, ignoring previous one

I have this .htaccess in my root folder:
root:
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?page=$1&%{QUERY_STRING} [NC,L]
So that incoming GET requests come through http://www.example.com/somethingsomething instead of ?page=somethingsomething. That's all fine.
However, in the root folder I have another folder named /i. Id like this one to handle another type of request, which looks like this: http://www.example.com/i/somethingsomething with the ending actually meaning http://www.example.com/i/index.php?img=somethingsomething. Problem is that the .htaccess in the root folder is still in use. What I need is the following:
/i:
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?img=$1&%{QUERY_STRING} [NC,L]
, but somehow exclude the .htaccess in the root folder.
Is this possible?
EDIT:
Tried what I found on this site, for instance using RewriteCond %{REQUEST_URI} !^/(i) and similar in the root .htaccess.
Yes, you can do it like this, using a single rule in the root .htaccess. The root .htaccess is always going to get processed, so you might as well do it there with one rule. Otherwise it would be more complicated and the root would need modifying with an exception for /i anyway.
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/(?:i/)?index\.php$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(i/)?(.*)$ /$1index.php?img=$2 [QSA,NC,L]
Using the [QSA] flag which is a better way to pass on any existing query string. RewriteBase is not needed. You perhaps don't need the directory check and it would be better for performance without it. The index.php check is there to improve performance by avoiding another file-system check after a successful rewrite.
Update
Sorry, I hadn't noticed that the parameter you are passing to index.php has a different name in the second case. These rules in root should work for you:
RewriteEngine on
RewriteCond %{REQUEST_URI} !=/index.php
RewriteCond %{REQUEST_URI} !^/i/ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?page=$1 [QSA,NC,L]
RewriteCond %{REQUEST_URI} !^/(?:i/)?index\.php$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^i/(.*)$ /i/index.php?img=$1 [QSA,NC,L]

Remove duplicate content issue using htaccess

My .htaccess file looks likes this:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php?pg=$1 [L]
When a non-file or non-dir url is requested, it works fine.
But if index.php?pg=(pagename) is requested, it also works which can possibly lead to duplicate content issue.
Is there a way to prevent this?
You're right, this can lead to duplicate content.
And, yes, it is possible to avoid it.
This solution redirects old url to new url equivalent, for instance http://website.com/index.php?pg=get/my/page/please.html to http://website.com/get/my/page/please.html.
RewriteEngine On
RewriteBase /
RewriteCond %{THE_REQUEST} \s/index\.php\?pg=([^&\s]*)\s [NC]
RewriteRule ^ %1? [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?pg=$1 [L]

.htaccess do something else if file not exist

We are using an .htaccess in combination with anchor tags to serve files and conceal the server directory structure.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /_docu/clients/$1/$2/$3.pdf [NC,L]
For example, all files are stored under /public_html/_docu/clients/ and inside that folder are listed all the clients, and then under each client their projects. However, an anchor tag for a file would read only:
http://mydomain.com/client-name/proj-name/docname.pdf
(the /_docu/clients/ being omitted - there is a good reason for this). The above .htaccess grabs the client-name, proj-name and docname and serves it from the correct folder:
http://mydomain.com/_docu/clients/client-name/proj-name/docname.pdf
whilst preserving in the address bar the incorrect (concealed) directory structure.
I wish to handle the error condition of a document not existing. This should never happen, but it could. Can anyone suggest a way of dealing with this? Can something functionally akin to "if fileexist($1/$2/%3.pdf)" be somehow constructed in an .htaccess file?
EDIT:
Delayed response as JL's answer below required research and experimentation. Thanks, Jon, for the gentle push in the right direction but I haven't got it to work just yet. Here's what I tried:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# check if the requested file exists in the "_docu/clients" directory
RewriteCond %{DOCUMENT_ROOT}/_docu/clients/$1/$2/$3.pdf -f
RewriteRule ^([a-z0-9])/([a-z0-9])/([a-z0-9]*).pdf$ /_docu/clients/$1/$2/$3.pdf [NC,L]
RewriteRule ^(.*)$ /errors/404.php [L]
I thought that what that should do is:
If http://mydomain.com/_docu/clients/$1/$2/$3.pdf does not exist,
GoTo page http://mydomain.com/errors/404.php
Actual outcome is an "internal server error" message.
EDIT TWO:
Latest changes:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^/([a-z0-9])/([a-z0-9])/([a-z0-9]*).pdf$
RewriteCond %{DOCUMENT_ROOT}/_data/cli/%1/%2/%3.pdf -f
RewriteRule ^([a-z0-9])/([a-z0-9])/([a-z0-9]*).pdf$ /_data/cli/$1/$2/$3.pdf [NC,L]
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteRule ^(.*)$ /metshare/404.php [L]
The problem with this one is that legitimate pages also are directed to 404.php
MESSAGE TO FUTURE READERS:
All of the above concerns were addressed in Jon Lin's final answer. As issues were detected, he modified his answer until it was a perfect, working solution. I am leaving the above as it is because there are some good ULOs within (unscheduled learning opportunities) for those who want to compare versions.
You need to use a condition like this:
RewriteCond %{DOCUMENT_ROOT}/_docu/clients%{REQUEST_URI} -f
So that your rules looks ssomething like:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# check if the requested file exists in the "_docu/clients" directory
RewriteCond %{DOCUMENT_ROOT}/_docu/clients%{REQUEST_URI} -f
RewriteRule ^ /_docu/clients%{REQUEST_URI} [L]
EDIT: Response to edit in question
You can't do this:
RewriteCond %{DOCUMENT_ROOT}/_docu/clients/$1/$2/$3.pdf -f
Because the backreferences for $1/$2/$3 don't exist yet, they are matched in the groupings in your RewriteRule, which hasn't happened yet at this point. But you can try something like this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# check if the requested file exists in the "_docu/clients" directory
RewriteCond %{REQUEST_URI} ^/([a-z0-9])/([a-z0-9])/([a-z0-9]*).pdf$
RewriteCond %{DOCUMENT_ROOT}/_docu/clients/%1/%2/%3.pdf -f
RewriteRule ^([a-z0-9])/([a-z0-9])/([a-z0-9]*).pdf$ /_docu/clients/$1/$2/$3.pdf [NC,L]
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /errors/404.php [L]
Essentially creating a match against %{REQUEST_URI} in a previous RewriteCond then using the %N backreferences in the following RewriteCond.

Code Igniter SubDirectory Question

I am trying to let the "trac" directory and all of it's subdirectories be accessible through the url http://www.domain.com/trac/
I am working with the codeginiter framework and my directory structure looks like
.htaccess
index.php
system
trac
I can access the abov url fine, but the problem is the scripts and other files contained in trac subdirectories ie: trac/chrome/common/css/trac.css are not accessible and 404. Here is my .htaccess code. Please help.
RewriteEngine On
RewriteRule ^$ index.php [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]
RewriteCond $1 !^trac/
RewriteRule ^trac/(.*) /trac/$1
You don't even need to mention /trac/ in your .htaccess. That's EXACTLY the point of
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
You're setting two "Rewrite Conditions." The first one says, "As long as the request isn't a file." The second one says "OR As long as the request isn't a directory."
Then
RewriteRule ^(.*)$ index.php?/$1 [L]
Sends everything else to index.php, where CI takes over. And just for the record, my full .htaccess that I use on every project:
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^system.*
RewriteRule ^(.*)$ /index.php?/$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]
If you're confused about the RewriteCond %{REQUEST_URL} ^system.* line, it only exists so that any browser requests to the /system/ folder is always routed to index.php, and therefor ignored.
rewrite rules are executed in order... so try this
RewriteCond %{REQUEST_URI} !^/trac/
RewriteCond $1 !(index\.php/)
RewriteRule ^(.*)$ index.php?/$1 [L]
Explanation:
if the uri DOES NOT start with trac
if the uri IS NOT index.php
rewrite url as index.php?/{rest of the url}
If you remove the last two lines, it should work.
RewriteCond %{REQUEST_FILENAME} !-f checks to ensure that you're not requesting a file. If you are, this condition fails and the rule RewriteRule ^(.*)$ index.php?/$1 [L] is never executed.

Resources