.htaccess conflicting rewrite rules - .htaccess

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.

Related

htaccess 3 parameters rewrite rule

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.

.htaccess rewrite with multiple parameters

I had a rule in my .htaccess that makes URLs for articles more friendly looking for the purposes of SEO and the like.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(news-and-views)/(.+).php /$1/article.php?title=$2 [L]
Which converted this URL:
/news-and-views/going-for-brokering.php
To this within the application itself:
/news-and-views/article.php?title=going-for-brokering
Now I need a URL with an ID before the title like this:
/news-and-views/123456789/going-for-brokering.php
So I tried the following rule:
RewriteRule ^(news-and-views)/(.+)/(.+).php /$1/article.php?Id=$2&title=$3 [L]
However, this isn't working, am I misunderstanding the use of the brackets as I thought everything between them was acknowledged as a variable on the right-hand side?
I'm thinking it could even be that the less specific rule is above the more specific rule.
You need to be careful about the order of the rules, since your first rule will also match /news-and-views/123456789/going-for-brokering.php. Change your rules as follows:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(news-and-views)/([^/]+).php /$1/article.php?title=$2 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(news-and-views)/([0-9]+)/([^/]+).php /$1/article.php?Id=$2&title=$3 [L]

URL Rewrite behaving strange

Hi i have one of rewrite rules as below
RewriteRule ^([^/.]+)/?$ /cityres?city=$1 [L]
This makes URL like http://example.com/value-of-city and this works perfectly fine.
But here problem i am facing is that if user types
`http://example.com/anyrandomvalue`
then URL behave same as
`http://example.com/value-of-city`
and tries fetching results based on anyrandomvalue
How can i avoid same?
You can restrict your regex to some allowed characters like a word character and hyphen:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([\w-]+)/?$ /cityres?city=$1 [L,QSA]

.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]

.htaccess rewritecond match something except

I'm trying to get my .htaccess file to work. Well it already works, but something is a bit annoying right now.
I have modyfied my .htaccess to support multi-language website with the following:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/public/[a-z]{2}/ [NC]
RewriteRule ^(.*)$ index.php?url=$1 [PT,L]
# match those that DO have a language code
RewriteRule ^([a-z]{2})/(.*)$ index.php?lang=$1&url=$2 [PT,L]
This works like a charm. When a two-char language code is added to the beginning of the URL the ?lang is added to my index.php. However this is a problem because my javascript folder is called "js" which means this will treated as if it was a language code. I actually thought that the two first RewriteCond's would prevent this from happening, but apparently it isn't.
I must admit that the .htaccess isn't what I'm best at so I might have missed some sort of simple solution.
Option #1: Use this rule (instead of your last line):
RewriteRule ^(?!js)([a-z]{2})/(.*)$ index.php?lang=$1&url=$2 [PT,L]
This will do nothing for /js/hello but will rewrite if /en/hello (for example) requested.
Option #2: Add condition similar to what you have for previous rule (I assume /public/js/ is the actual folder for your JavaScript files -- if not, adjust the name accordignly):
RewriteCond %{REQUEST_URI} !^/public/js/
RewriteRule ^([a-z]{2})/(.*)$ index.php?lang=$1&url=$2 [PT,L]
I recommend #1 -- it's may be more difficult to understand .. but it's all in single line and a bit faster (single regex versus two in #2).

Resources