Rewrite rules conflicting with existent files - .htaccess

I came across some htaccess url rewrite rules which are conflicting to existing url.
To write my category pages to www.mydomain.com/categoryname.html
I'm using following rule which is working fine but all my other pages like www.mydomain.com/about.html shows 404 not found
RewriteRule ^([^/]*)\.html$ /category_parent.php?ctg=$1 [L]
To write my product pages like www.mydomain.com/25/productname.html
I'm using following code which is also working fine
RewriteRule ^([^/]*)/([^/]*)\.html$ /product.php?id=$1&url=$2 [L]
but the above rewrite rule conflicting with sub category pages for which I'm using following code:
RewriteRule ^([^/]*)/([^/]*)\.html$ /category_child.php?pctg=$1&ctg=$2 [L]
In brief, I want to write to,
www.mydomain.com/categoryname.html
www.mydomain.com/categoryname/subcategoryname.html
www.mydomain.com/25/productname.html
But Some rules messing with each other. I'll appreciate if you can provide me little clue on this.

If your files are colliding the non-existent to existent ones, you should use a condition to verify if a file, directory or symbolic link exists.
For files:
RewriteCond %{REQUEST_FILENAME} !-f
For folders:
RewriteCond %{REQUEST_FILENAME} !-d
For symbolic links:
RewriteCond %{REQUEST_FILENAME} !-l
The exclamation mark ! is used to negate their meaning !-f means if the file does not exist then apply rule if it exists then do not apply rule.
Keep in mind that a RewriteCond should be followed by a RewriteRule and you can have one or more conditions per RewriteRule, for example:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^([^/]*)\.html$ /category_parent.php?ctg=$1 [L]
In this case it means if directory does not exist and file does not exist and symbolic link does not exist then we redirect but if any of the previous condition exist then we don't redirect.

Related

Difficulty with .htaccess determining which file to use based on final page backslash '/'

I have two types of pages in a section of my website.
One is for a categories, for example:
example.com/section/fruit/
example.com/section/vegetables/
The other for page details, for example:
example.com/section/fruit/apple
example.com/section/fruit/orange
example.com/section/fruit/grape
I am using .htaccess to grab the urlslug and talk to the database to display the right information and use the right template file.
RewriteCond %{REQUEST_URI} /section/(.*)/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule section/(.*)/ /template/category.php?urlslug=$1 [L]
RewriteCond %{REQUEST_URI} /section/(.*)/(.*)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule section/(.*)/(.*) /template/detail.php?category=$1&urlslug=$2 [L]
Unfortunately, because I have two url display methods the above .htaccess does not work. For categories they end in a ‘/‘ and the page detail are open (no slash) and .htaccess file cannot work out which one to grab.
I guess the question here is two fold.
From a best practice point of view. Is it better to have one consistent convention for URLs (all of them having an end slash or no end slash)? My current reasoning is that pages without a slash are the end page and the ones with a slash are categories but am not sure my logic is awesome on this one.
Assuming what I am doing is okay from a URL structure point of view. What would be the best approach to get the .htaccess to behave?
You may use these rules:
# skip below rules for files or directories
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^section/([\w-]+)/?$ template/category.php?urlslug=$1 [L,NC,QSA]
RewriteRule ^section/([\w-]+)/([\w-]+)/?$ template/detail.php?category=$1&urlslug=$2 [L,QSA,NC]
Note that .* matches everything. Using anchors in regex patterns allows you to match only one path component after /section/.

How to mod_write query param to path for arbitrarily long path?

I'm building a simple API with apache and I want to map /really/long/path/api/captions.php?caption_id=blah to /really/long/path/api/captions/blah. It's important to NOT have to specify a full path in the rewrite rule because I want this to work no matter where I deploy this code to. However, I can't find/figure out a working example of .htaccess rewrite rules that enable me to match based upon only the final part of the extension.
So, assuming that I have, say, captions.php in a dir called api, what .htaccess file do I need to include in api to accomplish this transform without having /really/long/path/ anywhere therein?
(I also want to be able to map /really/long/path/api/captions.php to /really/long/path/api/captions/ and /really/long/path/api/captions.)
I've tried all sorts of wildcard-like syntax; here's one of those non-working attempts:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*?)/?captions/(.*?)/?$ /captions.php?caption_id=$1 [L]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /captions\.php\?caption_id=([^\&\ ]+)
RewriteRule ^(.*?)/?captions\.php$ /captions/%1? [L,R=301]
Thanks!
Got there in the end. This is all that was needed:
RewriteEngine On # Turn on the rewriting engine
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^captions/?$ captions.php [NC,L]
RewriteRule ^captions/(.*)/?$ captions.php?caption_id=$1 [NC,L]

Multiple rewrite conditions for multiple parameters

There is an issue with the htaccess rewrite conditions in my setup.
Currently I have the following code.
Options +FollowSymLinks
RewriteEngine on
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ http://mydom.com/$1.php
This works fine for any base page making them look like this.
http://mydom.com/page
What I want to also be able to do is add parameters from the url if they exist. I have some pages that will be like this.
http://mydom.com/page?param=1&secondParam=2
What I've tried to do is add this.
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/(.*)/(.*)$ http://mydom/$1/$2/$3 [L]
RewriteRule ^(.*)/(.*)$ http://mydom/$1/$2 [L]
This made sense to me, because I thought if the condition didn't match, it would move on, but this gave me an internal server error.
What I ended up doing was setting up a separate rule for each page that could have multiple parameters like this.
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^page/(.)/(.)$ http://mydom.com/page.php?param=$1&secondParam=$2 [L]
RewriteRule ^page/(.*)$ http://mydom.com/page.php?param=$1 [L]
RewriteRule ^(.*)$ http://mydom.com/$1.php
This works, however you need to keep in mind relative links you may have in your site such as style sheets and javascript files. In my case, I had to replace all relative paths with full site paths, depending on the way you set up your site, it could take a while to replace.

Rewrite URL with .htaccess for multiple parameters

This question might be a duplicate. But I did not find any solution worked for me.
I want to rewrite URL, where I have one and two level parameters. first parameter is p and second is sp
www.domain.com/home should point to www.domain.com/index.php?p=home
and
www.domain.com/projects/99 should point to www.domain.com/index.php?p=projects&sp=99
How do I do in .htaccess?
Currently My htaccess is as followes,
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?p=$1
RewriteRule ^([^/]*)/([^/]*)\$ index.php?p=$1&sp=$2 [L]
The problem with this htaccess is that it correctly points one level url. ie., www.domain.com/home. But not the two level url. ie. www.domain.com/projects/99
You have to treat the rules separately. All Conditions preceding rules only apply to a single, immediately following rule. You tried to 'chain' two rules. The second rule never could have matched, since the first one was a catch-all that changed the syntax. Apart from that you have to make sure that the first rule does not catch unwanted requests. Also think about whether you want to use the * or the + operator in the patterns. I suggest you use the + operator, so that you have a clear error message when empty values are requested for a 'page' or a 'subpage'.
So this might come closer to what you are looking for:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ index.php?p=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)$ index.php?p=$1&sp=$2 [L]

htaccess does not work rewrite rule

I've been struggling with my .htaccess file for weeks now, I changed it many times but it just won't work.
I have this in my .htaccess file:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^/([^./]+)\.html$ category.php?id=$1
RewriteRule ^/([^./]+)\.html$ tag.php?id=$1
RewriteRule ^/([^./]+)\.html$ play.php?id=$1
but it does not work.
Are you sure that mod_rewrite is turned on in Apache? Do you have access to httpd.conf? It would be better to do redirects there instead of with a .htaccess file.
Your conditions are only being applied to the first rule. Each set of RewriteCond's only get applied to the immediately following RewriteRule. So the conditions only get applied to RewriteRule ^/([^./]+)\.html$ category.php?id=$1 and the last 2 rules have no conditions at all.
Your conditions is to rewrite something that exists to something else, which will cause a rewrite loop. You probably wanted:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
Your 2nd and 3rd rules will never be applied because if someone requests /some-page.html the first rule's regex will match it and rewrite the URI to /category.php?id=some-page, then the next to rules will never match because the first rule already rewrote the URI to category.php.
Your regular expressions match a leading slash, URI's being applied in rewrite rules that are inside an htaccess file has the leading slash stripped out, so you want this instead:
RewriteRule ^([^./]+)\.html$ category.php?id=$1
1, 2 and 4 is easy. 3, not so much. You're going to have to figure out a unique way to represent an html page as a category, tag, or play. You can't have all 3 look identical, there's no way to tell which one you want. Take:
/something.html
Is that supposed to be a category? A tag? or a Play? Who knows, your rewrite rules surely don't. But if you preface each with a keyword, then you can differentiate:
/category/something.html
/tag/something.html
/play/something.html
And your rules would look like:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^category/([^./]+)\.html$ category.php?id=$1
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^tag/([^./]+)\.html$ tag.php?id=$1
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^play/([^./]+)\.html$ play.php?id=$1

Resources