htaccess 3 parameters rewrite rule - .htaccess

I know this problem is asked before, but i don't find anything
i try to pass 3 variable in htaccess the url change normaly but i cant't get the third variable
this is my htaccess file
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-z]+)\/?$ index.php?r=$1 [NC]
RewriteRule ^([a-z]+)/([a-z]+) index.php?r=$1&s=$2 [L]
RewriteRule ^([a-z]+)/([0-9]+) index.php?r=$1&id=$2 [L]
RewriteRule ^([a-z]+)/([0-9]+)/([a-z]+) index.php?r=$1&id=$2&s=$3 [L]

RewriteRule ^([a-z]+)/([0-9]+) index.php?r=$1&id=$2 [L]
RewriteRule ^([a-z]+)/([0-9]+)/([a-z]+) index.php?r=$1&id=$2&s=$3 [L]
These 2 rules conflict. A URL of the form /abc/123/def is also matched by the first rule, so the second rule is never processed.
You could either:
Include an end-of-string anchor ($) on the first rule pattern, so that it only matches /abc/123 and not /abc/123/def. For example:
RewriteRule ^([a-z]+)/([0-9]+)$ index.php?r=$1&id=$2 [L]
OR, reverse these two directives, so the rule for 3 parameters takes priority:
RewriteRule ^([a-z]+)/([0-9]+)/([a-z]+) index.php?r=$1&id=$2&s=$3 [L]
RewriteRule ^([a-z]+)/([0-9]+) index.php?r=$1&id=$2 [L]
You should probably include end-of-string anchors on all your patterns, otherwise, they are likely to match too much. eg. /abc/123/def/for/bar/baz.jpg is matched by the 3rd and 4th rule without an end-of-string anchor. If you add end-of-string anchors then the filesystem conditions could probably be removed altogether.
As #IMSoP noted in comments, those two conditions (ie. RewriteCond directives) only apply to the first RewriteRule that follows. The first rule is unlikely to match a real file anyway, so the conditions aren't really doing anything currently.

Related

.htaccess question - the [L] flag any way to simplify

I usually use MVC routing but I have to work on a site with non MVC and need to add a new feature.
Here is my commnads which works:
RewriteRule ^blog/why-am-using-htaccess/$ viewBlog.php?blogHook=$1 [L]
RewriteRule ^blog/(.*) blogs.php [L]
RewriteRule ^(.*)/$ page.php?hookName=$1
My issue is I have to put the [L] flag on everything above for it to work. I want to basically issue a flag to
RewriteRule ^(.*)/$ page.php?hookName=$1
That basically says do everything above but the last one is the fallback.
Is there any way to do that?
You have to use
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
before your last rule. The first rules rewrote the requested url to a valid (php) file which can be accessed, so the conditions will turn to false. If no rules matched before, but the requested url is a valid file yet (such as an image), this rule isn't processed too.
You should also omit the slash in the last rule: ^(.*)/$, because otherwise this rule only rewrites urls with an ending slash.

Need Assistance for this Htaccess Rewrite Rule

I have a problem with my .htaccess, a short explanation I would like to set http://example.com/newest on my website. However, it always redirects to http://example.com/postname. Where I just need the exact "newest" page. Here is my code:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteBase /
RewriteRule ^[^/]+$ %{REQUEST_URI}/ [L,R=301]
RewriteRule ^/category/(.*)$ page.php?f=$1
RewriteRule ^/search/(.*)$ search.php?f=$1
RewriteRule ^(.*)/$ post.php?f=$1 <- If this is removed, my post htaccess will not work
RewriteRule ^newest/$ index.php?f=newest <- I want to execute this code
I really don't know what this is called, I have been looking for the whole stackoverflow but I did not get any answer. Please remain me if this is a duplicate question.
As Mohammed implied in comments, your directives are in the wrong order. The line above your "newest" rewrite is a catch-all and rewrites all requests, so the last line will never match.
http://example.com/newest
Note that your rules imply that your URLs should end in a trailing slash. So, you should be linking to http://example.com/newest/ (with a trailing slash), not http://example.com/newest, otherwise your users will get a lot of unnecessary redirects.
However, you appear to be under the belief that the RewriteCond directive applies to all the directives that follow. This is not the case. It only applies to the first RewriteCond directive. You also need some L flags to prevent further processing.
You also have a slash prefix on the "category" and "search" rewrite patterns, so these would never match in a .htaccess context.
Try something like the following instead:
RewriteEngine On
RewriteBase /
# Don't process the request further if it maps to an existing file
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
# Append trailing if omitted
# Although strictly speaking this only redirects if there are no slashes at all in the URL
RewriteRule ^[^/]+$ %{REQUEST_URI}/ [L,R=301]
RewriteRule ^category/(.*)$ page.php?f=$1 [L]
RewriteRule ^search/(.*)$ search.php?f=$1 [L]
RewriteRule ^newest/$ index.php?f=newest [L]
RewriteRule ^(.*)/$ post.php?f=$1 [L]

.htaccess conflicting rewrite rules

I'm trying to change a website to multi-language, so I have URL's like this:
www.company.com/en/about
www.company.com/fr/about
which should point to index.php?lang=en&what=about
so I defined the following rewrite rule (which works)
RewriteRule ^en/(.*)$ ?lang=en&what=$1 [NC,L]
RewriteRule ^fr/(.*)$ ?lang=fr&what=$2 [NC,L]
but I also need the homepage url as www.company.com/en (pointing to index.php?lang=en)
which does not work for this rule.
The best solution would be something like
RewriteRule ^(.*)/(.*)$ ?lang=$1&what=$2 [NC,L]
but it converts all the urls, like href='css.css' kind of references, so it messes up the whole page.
so how should I restrict the first GET variable to be two chars? or one of the defined languages?
Try:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-z]{2})(?:/(.*)|)$ /?lang=$1&what=$2 [L]
The first grouping, ([a-z]{2}), captures the 2 letter language. The second optional grouping captures the "what". If there's nothing there, then "what" will be blank.

htaccess redirection dynamic

I am trying to redirect /en/news/12345 to http://www.xyz.com/en/newsletters/12345
the only thing is that "en" and "12345" can change but "news" is always the same.
I have the following so far:
RewriteRule /^(.)/news/(.)$ http://www.xyz.com/$1/news/$2 [R=301,L]
but if i go to mydomain/wp-admin then i get an endless redirect?? Any ideas why this is happening?
Thanks
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^en/news/([0-9]) http://www.xyz.com/en/newsletters/$1 [NC]
Please try this, hope it will solve your problem
I think I found the problem in your .htaccess file. Initially you had two conditions that prevented RewriteRule . /swissfil3/index.php [L] (catch-all) from redirecting when the path pointed to an existing file or folder (ignore-on-file):
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond only applies to the rule directly followed by the condition.
When you added a new rule directly below these directives, the catch-all rule was not prevented from redirecting existing files or directories like /wp-admin. I.e. every request not matching any rules before catch-all would be redirected to /swissfin/3/index.php.
In additoin you used (.) to capture each part of the path. This would match one arbitrary character, but no more, so your redirect would be limited to /X/news/Y, instead of /XX/news/YYYY..., to fix this you can use (.+) which will match zero or more chars, or even better ([^/]*) which will match zero or more characters not equal to /.
You should be able to avoid these problems by using the following code (where the catch-all directive has been moved directly below ignore-on-file, and the rewrite rule matches zero or more chars not equal to /):
# ...
RewriteRule ^([^/]*)/news/([^/]*)$ http://www.xyz.com/$1/news/$2 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /swissfin3/index.php [L]
Here you match every URL that contains a char

.htaccess issues

I have a page that does two things:
When users click on this link:
http://www.example.com/whatever_200/index.html/?id=4 it is actually processed by
http://www.example.com/search/profile-condo.php?id=4
However, I also want to do the following for people in Brazil
www.example.com/br/whatever_200/index.html/?id=4
www.example.com/br/search/profile-condo.php?id=4
The following works great for the english version:
addhandler x-httpd-php5 .html
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/index.html$ /search/profile-condo.php?name=$1&%{QUERY_STRING} [L,QSA]
But when I add
RewriteRule ^(.*)/br/^(.*)/index.html$ /br/search/profile-condo.php?name=$1&%{QUERY_STRING} [L,QSA]
It doesn't work.
What am I doing wrong?
There are three problems with your rules.
First of all the rule order. The first rule will match anything ending with /index.html, and it will perform the redirect. It is (properly) flagged as the final rule (the L flag). Because of that, the second rule will never be executed. If you add add the br rule before the general rule, it will be tested first, and if it matches, the redirect will occur.
The second problem is the regular expression on your second rule. It contains a circumflex ^ halfway the expression. The circumflex means start of string, which obviously never occurs in the middle of the string. Removing the circumflex will fix that.
A third issue is that you're allowing characters before the /br/ part of your url (by having (.*) in your expression. According to your description, you do not actually need this.
Summarizing:
addhandler x-httpd-php5 .html
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/br/(.*)/index.html$ /br/search/profile-condo.php?name=$1&%{QUERY_STRING} [L,QSA]
RewriteRule ^(.*)/index.html$ /search/profile-condo.php?name=$1&%{QUERY_STRING} [L,QSA]

Resources