I'm setting up my .htaccess files with some RewriteRules, but unfortunatly I got stuck. I've found a lot of topics on this, but none mentioning my specific issue.
I have this:
RewriteEngine On
RewriteBase /
RewriteRule ^en/contact /contact.php?lang=en&slug=ok [L,NC]
RewriteRule ^contact /en/contact [L,R=301]
Purpose is to force the lang as a first parameter in the url if not set.
So: www.example.com/contact should be redirected (301) to www.example.com/en/contact which then again loads the content from /contact.php?lang=en&slug=ok
The problem I have is that I end up in a loop as /contact.php?lang=en&slug=ok gets loaded and is parsed by RewriteRule ^contact /en/contact [L,R=301] again.
How can I adapt this rule so it is only triggered for /contact and not for /contact.php or /en/contact or /contactme or any other url that contains contact
Thanks!
Your 301 redirect rule is causing the infinite loop as it matches the destination path of your first rule. What is happening is that when you request /en/contact your first rule rewrites it to /contact.php?lang=en&slug=ok and then ,your second rule matches the same uri and redirects it to /en/contact .
To fix this, You can either use END flag in your RewriteRule or use THE_REQUEST condition .
RewriteEngine On
RewriteBase /
RewriteRule ^en/contact /contact.php?lang=en&slug=ok [L,NC,END]
RewriteRule ^contact /en/contact [L,R=301]
Note : END flag works only on apache versions above 2.4 if your server version is less then 2.4 you could use a % {THE_REQUEST} condition to terminate the redirect loop
RewriteEngine On
RewriteBase /
RewriteRule ^en/contact /contact.php?lang=en&slug=ok [L,NC]
RewriteCond %{THE_REQUEST} /contact
RewriteRule ^contact /en/contact [L,R=301]
Make sure to clear your browser cache before testing these redirects.
Related
I have the following rules:
RewriteRule ^error$ 404.php
RewriteRule ^home$ index.php
Now I want, that everything behind domain.com<> (in the <>) redirects to test.php.
I did
RewriteRule ^([^/]+)$ test.php
and that works but when I enter "error" or "home" it also redirects to test.php instead of to 404.php and index.php
You can REDIRECT_STATUS like this:
RewriteEngine On
RewriteBase /
RewriteRule ^error/?$ 404.php [L,NC]
RewriteRule ^home/?$ index.php [L,NC]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^ test.php
REDIRECT_STATUS gets set to non-zero value (200) after execution of some rewrite rules.
Try this :
RewriteEngine On
RewriteRule ^error$ 404.php
RewriteRule ^home$ index.php
RewriteCond %{REQUEST_URI} !/(error|home|index|404)
RewriteRule ^([^/]+)$ test.php
The problem is that , you have already captured error and home but when they redirected to 404 or index they being captured again by the last rule so you should exclude them from last rule.
You can tell the rewrite that it has completed when a matching condition is found and therefore not to continue when the condition is met so your rewrites could be something like this:
RewriteEngine On
RewriteBase /
RewriteRule ^error$ 404.php [L,NC]
RewriteRule ^home$ index.php [L,NC]
RewriteRule ^(.*)$ test.php
The 'L' rewrite flag tells the redirect that this is the last condition (i.e. look no further). The 'NC' flag make the rule case insensitive. You can decide if this you also want to include need a R=301 flag or not.
However, I can see a potential issue in the above because once the rules have been processed, the rewritten request is handed back to the URL parsing engine and the rewritten request is handled again by the .htaccess file. This will cause the second last rule to be accepted on the second pass.
The alternative [END] flag, can be used to terminate not only the current round of rewrite processing but prevent any subsequent rewrite processing from occurring in the htaccess context. I will be interested if this works.
Hope this helps.
How can I change my url from /images/hold/... to /hold/...
I have this but it doesnt work:
RewriteRule ^/images/hold/(.*) /hold/$1 [R=301,NC,L]
RewriteRule ^/images/hold/(.*) /hold/$1 [R=301,NC,L]
In per-directory .htaccess files the URL-path that is matched by the RewriteRule directive never starts with a slash. So, try the following instead:
RewriteRule ^images/hold/(.*) /hold/$1 [R=301,NC,L]
Or, to cut out some repetition:
RewriteRule ^images/(hold/.*) /$1 [R=301,NC,L]
If you've been experimenting with 301 redirects then you may need to clear your browser cache, as these get cached hard by the browser.
I'm trying to create clean URL with .htacces rewrite. I have two types of urls:
site.com/page.php?page=something
site.com/something.php
I need them both to be just site.com/something, with redirect from ugly to pretty url. So now I have the following rules, which don't work together, and I totally stuck with the redirect.
Options -Multiviews
RewriteEngine On
RewriteBase /
# page.php?page=about to about
RewriteRule ^([^/.]+)?$ /page.php?page=$1 [NC,L]
# something.php to something
RewriteRule ^([^/.]+)?$ $1.php [NC,L]
Will appreciate any help. Thanks in advance.
There are a few things that are incorrect in your example:
You cannot inspect the query string in a RewriteRule, only in a RewriteCond
Your RewriteRule lines are backwards - the first part is a regular expression match of the URL and the second is what you want it to be.
You will need to have an [R] rule as part of the rewrite to perform a redirect, otherwise it will just "rewrite" the URL the server sees and not change the actual URL.
Here is an example of your first rewrite, redirecting /page.php?page=foo to /foo. You first need a RewriteCond to inspect the %{QUERY_STRING} variable to see if it has page=... in it. We can use the character match ([^&]*) to grab all of the characters that are not an ampersand and store in a matching group. Next we perform a RewriteRule for page.php (note that we don't need the leading / because of the RewriteBase and that the . is escaped). If there is a match here, you want to redirect to the matching group from the RewriteCond - it is referred to with a %1 rather than a $1 like it would if it were from the RewriteRule. You will also want to append a ? to the end of your redirect which tells Apache to drop the query string so you don't end up with /foo?page=foo. Finally you will need [R=301] to perform a redirect with an HTTP status code of 301. The [L] indicates that that this is the Last rule you want to process if there is a match.
RewriteEngine On
RewriteBase /
# page.php?page=about to about
RewriteCond %{QUERY_STRING} page=([^&]*) [NC]
RewriteRule page\.php /%1? [R=301,L]
Your second rewrite is closer, but as in the first the logic is backwards. You want the first part to match *.php and then the second to indicate the redirect to /$1. Again you will need the [R-301] for the redirect.
# something.php to something
RewriteRule (.*)\.php$ $1 [R=301,L]
You can test this out on http://htaccess.madewithlove.be/.
Using http://example.com/page.php?page=foo, redirects to http://example.com/foo
1 RewriteEngine On
2 RewriteBase /
3 # page.php?page=about to about
4 RewriteCond %{QUERY_STRING} page=([^&]*) [NC]
This condition was met
5 RewriteRule page\.php /%1? [R=301,L]
This rule was met, the new url is http://example.com/foo
Test are stopped, because of the R in your RewriteRule options.
A redirect will be made with status code 301
Using http://example.com/foo.php redirect to http://example.com/foo
1 RewriteEngine On
2 RewriteBase /
3 # page.php?page=about to about
4 RewriteCond %{QUERY_STRING} page=([^&]*) [NC]
This condition was not met
5 RewriteRule page\.php /%1? [R=301,L]
This rule was not met because one of the conditions was not met
6 # something.php to something
7 RewriteRule (.*)\.php$ /$1 [R=301,L]
This rule was met, the new url is http://example.com/foo
Test are stopped, because of the R in your RewriteRule options.
A redirect will be made with status code 301
My .htaccess file in my public_html has:
RewriteEngine on
RewriteRule ^testfolder/(.*)$ /$1 [R=301,L,NC]
RewriteRule ^(.*)$ testfolder/$1
According to http://htaccess.madewithlove.be/ which I am using to test output
when I enter http://www.mydomain.com/testfolder/aaa/bbb I get:
This rule was met, the new url is http://www.mydomain.com/aaa/bbb
Test are stopped, because of the R in your RewriteRule options. A redirect will be made with status code 301
Is there a way to perform the 301 redirect to make the url in the browser bar 'prettier'
while continuing to attempt to match patterns further down in the htacess file?
I have my codeigniter project in www.mydomain.com/testfolder. My first rule:
RewriteRule ^testfolder/(.*)$ /$1 [R=301,L,NC]
is to rewrite any navbar requests for a contoller which come in the form : www.mydomain.com/testfolder/controller/method to
www.mydomain.com/testfolder/controller/method. The second ruleis so that anyone www.mydomain.com/controller/method will use it turned internally into www.mydomain.com/testfolder/controller/method
Thank you in advance,
Bill
Addendum - my current .htaccess file:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+b1/(.*)\s [NC]
RewriteRule ^ /$1 [R=302,L]
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteRule ^(.*)$ /b1/$1 [L]
First of all your rules are flawed and will definitely cause infinite loop.
Reason being that 1st rule is externally redirecting /testfolder/aaa/bbb to /aaa/bbb.
Now after redirect 2nd rule will also kick in since you're just matching .* there and that will be internally forwarded to /testfolder/aaa/bbb/ and that rule will cause 1st rule to kick in once again and this will cause infinite loop.
Don't know your intent but you can use this code to avoid looping:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+b1/([^\s]+)\s [NC]
RewriteRule ^ /$1 [R=302,L]
RewriteRule ^(.*)$ /b1/$1 [L,P]
Once you verify it is working fine, replace R=302 to R=301. Avoid using R=301 (Permanent Redirect) while testing your mod_rewrite rules.
No. Once the client has been redirected a new request occurs and rewriting begins anew with the new URL.
Preface
I'm trying to re-write a URL for a profile page. All of my application pages have a .html extension, so I'm trying to match just letters, numbers, -, and ..
So these would be valid
site.com/steve
site.com/steve-robbins
site.com/steve.robbins
But these wouldn't be
site.com/steve.html
site.com/steve-robbins.php
Assume I have a check in place so that custom URLs don't have .html or .php on the end.
Problem
I'm currently using this but it's not working
RewriteRule ^([a-zA-Z0-9\.-]+)$ profile.php?url=$1 [L]
It should set url to steve, but it's setting it to profile.php
What am I doing wrong?
My complete .htaccess
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^[^.]+\.[^.]+$
RewriteRule ^(.*) http://www.%{HTTP_HOST}/$1 [R=301]
#
# LOGIN
#
RewriteRule ^([a-z0-9]{255})/activate\.html$ login.php?activate=$1 [L]
RewriteRule ^logout\.html$ login.php?logout [L]
#
# SETTINGS
#
RewriteRule ^change-([a-z]+)\.html$ account-settings.php?$1 [L]
RewriteRule ^([a-zA-Z0-9\.-]+)$ profile.php?url=$1 [L]
# SEO friendly URLs
RewriteRule ^([a-zA-Z0-9-_.]+)\.html$ $1.php [L]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /([a-zA-Z0-9-_.]+)\.php
RewriteRule ^([a-zA-Z0-9-_.]+)\.php$ $1.html [R=301]
Add this to the top of your rules (under the RewriteBase / directive):
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]
That should stop it from looping. The rewrite engine will keep re-applying all the rules until the URI going in (sans query string) is the same as the URI that comes out of the rules. That's why the value of url is profile.php.
I'm kind of a beginner in interpreting mod_rewrite rules but if I understand it correctly your rule is matched and than matched again, either add something to the url matching scheme like /profile/user or add a condition to not redirect if already redirected
Try adding a leading slash to the redirect like this:
RewriteRule ^([a-zA-Z0-9.-]+)$ /profile.php?url=$1 [L]
The reason you're getting a url value of profile.php is because the [L] flag is kinda misleading when it comes to the .htaccess file. In the server config files it does exactly what you'd think, but in the .htaccess file it stops reading rules at that rule, but then goes through the rules again until path is unchanged by any of the rules. By adding the leading /, your rule will not match the second time around as you exclude / from the regex. I spent a while struggling with this feature myself.