PHP Mod Rewrite - php

I have a .htaccess which does a basic rewrite which looks like the following:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php?url=$1 [L,QSA]
The next condition is to remove www. from the URL and looks like this:
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
The problem is, when I call a link such as:
http://somesite.com/category/subcategory/?id=123
and add the www. manually, it rewrites the URL to this:
http://www.somesite.com?url=category/subcategory/?123
The page stills load but, I've been told that's terrible for SEO. Any thoughts of how to fix this?

Your current issue is that you have your WWW redirect after your main SEO rules, this is what happens behind the scenes:
You access http://somesite.com/category/subcategory/?id=123
Your rules internally redirect it to index.php?url=category/subcategory/?id=123
Your last rule to redirect without the www will also take place and will ended up redirecting it to:
http://somesite.com/?url=category/subcategory/?id=123
In order to fix that you would need your rules as follow:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
RewriteRule ^index.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php?url=$1 [L,QSA]
Which leads us to your second issue, you've been using 301 redirects so your browser have cached some redirects and you will need to use a different browser temporarily to test your changes, preferable one you haven't used yet to access that site, while you clear the cache of that browser and wait for it to completely clear out.
Once the cache of your default browser has cleared you can use it as usual and you should get the same response.

Related

Conditional htaccess

I just want some help with my .htaccess configuration. Before I have this problem where I need to redirect the page to
a specific url. Like if the user type http://mydomain/test it will be redirected to http://mydomain/app/r/test. I
achieved the redirection using .htaccess. The code is below
RewriteEngine on
RewriteRule (.*) http://mydomain/app/r/$1 [R=301,L]
But I have this new specification. As follows:
If user visit http://mydomain/ or http://domain/index.php, he will be
redirected to http://mydomain/mymanager
If user visit
http://mydomain/{any_segment}, he will be redirected to
http://mydomain/app/r/{any_segment}
Here is my current htaccess. Basically in the url, any characters will be redirected to /app/r/{} except index.php. But what about the http://domain/? How can I achieve this.
RewriteEngine on
RewriteCond %{HTTP_HOST} ^mydomain$ [OR]
RewriteCond %{HTTP_HOST} ^www.mydomain$
RewriteCond %{REQUEST_URI} !^/index.php
RewriteRule ^(.*)$ http://mydomain/app/r/$1 [R=301,L]
I've been playing around my htaccess and any pointers will be of great help to me.
These are your rules :
RewriteEngine on
RewriteCond %{HTTP_HOST} ^mydomain$ [OR]
RewriteCond %{HTTP_HOST} ^www.mydomain$
RewriteCond %{REQUEST_URI} !^/index.php
RewriteRule ^(.*)$ http://mydomain/app/r/$1 [R=301,L]
It looks like , any request should redirect to /app/r/ except A URI start with /index.php but still not doing that , in normal cases , so you should exclude the target directory from being redirect again and again by this rule RewriteRule ^(.*)$ http://mydomain/app/r/$1 [R=301,L] , ^(.*)$ means any URI start with any thing and the server will look, if there is a condition , and actually there is only one condition to exclude index.php, otherwise redirect .
So , you should exclude this target directory along with index.php like this :
RewriteCond %{REQUEST_URI} !^(/index\.php|/app/r/)
But still you want to match a request that target HOST only so,you should add that as well :
RewriteCond %{REQUEST_URI} !^(/index\.php|/app/r/|/?$)
Then you could match host with www or non-www like this :
RewriteCond %{HTTP_HOST} ^(www\.)?mydomain$
Your rules should look like this :
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.)?mydomain$
RewriteCond %{REQUEST_URI} !^(/index\.php|/app/r/|/?$)
RewriteRule ^(.*)$ http://mydomain/app/r/$1 [R=301,L]
Also you could summarize that more by utilizing %{REQUEST_URI} like this :
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.)?mydomain$
RewriteRule !^(index\.php|app/r/|/?$) http://mydomain/app/r%{REQUEST_URI} [R=301,L]
NOTE: Clear browser cache then test

How to redirect if the url have index.php/somefileOrsomedirectory

What do i want to do is if the url have www.example.com/index.php/anything then it should throw the user to www.example.com/error-404
Here is my current expressions in my htaccess file.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?$1 [L,QSA]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s(.*)/index\.php [NC]
RewriteRule ^ %1 [R=301,L]
RewriteCond %{HTTP_HOST} !^www.example.com$ [NC]
RewriteRule (.*)$ http://www.example.com/$1 [L,R=301]
Redirect 301 /online-features/key-anywhere-web-based-system http://www.example.com/online-features
Redirect 301 /home http://www.example.com/
Thanks in advance.
Please suggest/edit my question if i have not asked the question in correct way.
EDIT
I don't want to loose the /index.php to / redirection.
www.example.com/index.php/anything
/anything here is additional path information (after the name of a physical file). You can use the AcceptPathInfo directive to specifically disable this "feature":
AcceptPathInfo Off
In which case all URLs containing additional path info will automatically trigger a 404. However, the URLs can still be routed using mod_rewrite, which is probably what's happening here.
You will still need to implement a mod_rewrite redirect as mentioned in the datascript's answer. Or try something like the following, before your existing directives:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^index\.php/ /error-404 [R=302,L]
The check against REDIRECT_STATUS is to avoid a rewrite loop, since your front controller appears to use path info to route the request.
Change this to a 301 if this is intended to be permanent, once you have confirmed it's working OK.
However, it would be preferable if this was implemented as a proper Apache error document. For example:
ErrorDocument /error-404.php
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^index\.php/ - [R=404,L]
I think the following should do what you require. The dot is any character and the + means one or more times.
This would require the forward slash to be there
RewriteRule ^index\.php/(.+)$ error-404 [L]
EDIT: Thanks #DocRoot, updated accordingly

Passing a query string through redirect for maintenance mode

I am looking for some guidance when working with a maintenance mode system, utilised within a .htaccess file, via mod_rewrite and passing a $_GET along with it.
Passing a $_GET in mod_rewrite is perfectly fine under normal circumstances for me, but in this instance I am experiencing issues..
The code I have for the maintenance system is as follows:
RewriteCond %{REMOTE_HOST} !^XX\.XXX\.XXX\.XXX
RewriteCond %{REQUEST_URI} !/maintenance.php$
RewriteCond %{REQUEST_URI} !^/css/.*$
RewriteCond %{REQUEST_URI} !^/assets/.*$
RewriteRule ^$ maintenance.php [R=302,L]
So what I need is the ability to pass a $_GET along with the rewriteRule, thus when the site is viewed as normal by anyone using the allowed IP, I can define that the site is being viewed in maintenance mode.
Of course people not on the allowed IP get redirected to maintenance.php file and don't need this reminder anyway, as the page does that already.
Thank you in advance anyone that can help me in this issue.
EDIT::
# Start the mod re-write conditions #
RewriteRule ^([^/]+)\/$ ?cat=generic&page=$1 [L]
RewriteRule ^products\/([^/]+)\/([^/]+)\/$ ?cat=product&page=$2 [L]
RewriteRule ^theteam\/([^/]+)\/$ ?cat=staff&page=$1 [L]
Thats how I deal with the other links on my page, I hope that is all you needed to see.
Dan.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !maintenance.php
RewriteCond %{REQUEST_URI} !(css|assets).*$
RewriteCond %{REMOTE_ADDR} !^XX\.XXX\.XXX\.XXX$
RewriteRule (.*) /maintenance.php [R=302,L]
RewriteCond %{REMOTE_ADDR} ^XX\.XXX\.XXX\.XXX$
RewriteRule (.*) $1?mode=maintenance [L,QSA]
This works for me, first you have the negation redirect so whoever tries to access without the allowed IP will go to maintenance.php.
Then you have the append internal redirect, the GET mode=maintenance will not be visible but will be there.
And you can retrieve it with $_GET['mode'].
If you want it to visually append to the query string and only to php files you can use:
RewriteCond %{REMOTE_ADDR} ^XX\.XXX\.XXX\.XXX$
RewriteCond %{REQUEST_FILENAME} \.php$
RewriteCond %{QUERY_STRING} !^mode=maintenance.*$
RewriteRule (.*) $1?mode=maintenance [R,L,QSA]
Update of visible rule for your sub directories format this rule should be placed before it like this:
RewriteCond %{REMOTE_ADDR} ^XX\.XXX\.XXX\.XXX$
RewriteCond %{QUERY_STRING} !.*mode=maintenance.*$
# for visible query string uncomment the below line and comment the next rule
#RewriteRule (.*) $1?mode=maintenance [R,L,QSA]
# for invisible query string
RewriteRule (.*) $1?mode=maintenance [L,QSA]
# Start the mod re-write conditions #
RewriteRule ^([^/]+)\/$ ?cat=generic&page=$1 [L,QSA]
RewriteRule ^products\/([^/]+)\/([^/]+)\/$ ?cat=product&page=$2 [L,QSA]
RewriteRule ^theteam\/([^/]+)\/$ ?cat=staff&page=$1 [L,QSA]

How does this mod_rewrite code resolve properly?

My .htaccess file is as follows:
Options -Multiviews
RewriteEngine On
RewriteCond %{HTTP_HOST} ^example.com
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ $1.php
It works, but I'm wondering how it works. For example, if I type in example.com/main, I get the file at www.example.com/main.php. How do I get the .php extension if the code tells the rewriting to stop after adding the www. to the beginning of example.com?
Edit: Or should I create a unique ID only for the purpose of logging in the remembered user?
The particular behavior you're asking about comes about because the rule
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]
is a 301 redirect; it instructs the browser to initiate a completely new HTTP request. The L only causes (can only cause) it to be the last rule executed for that request; the new request comes in with the correct hostname and proceeds onward.

Forcing a trailing slash to a URL after a subdomain rewrite

I'm re-writing a subdomain to a 'folder' - actually a page in wordpress, and this all seems to be working correctly. I don't want the address in the URL bar to change though.
Everything works fine unless the user does not put a trailing slash after the page name, then the page is still redirected to the correct URL but the URL in the address bar changes
For example: foo.example.com/bar
Becomes: public.example.com/foo/bar
Where : foo.example.com/bar/ stays at the correct URL in the address bar but shows the redirected page (this is correct)
What rule do i need to add to add in a trailing slash if its not sent?
The code i have so far is:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
Options +FollowSymlinks
RewriteCond %{HTTP_HOST} ^foo\.example\.com$ [NC]
RewriteRule ^(.*)$ http://public.example.com/foo/$1 [P]
# rules for WordPress ...
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
#####
</IfModule>
Any help would be fantastic, I'm pretty new to htaccess. Thanks!
Phew, after a bit of playing around i seem to have got it working:
RewriteCond %{HTTP_HOST} ^foo\.example\.com$ [NC]
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ http://foo.example.com/$1/ [L,R=301]
RewriteCond %{HTTP_HOST} ^foo\.example\.com$ [NC]
RewriteRule ^(.*)$ http://public.example.com/foo/$1 [P]
Basically, the first block adds a trailing slash to the URL is it's not there in the first place, then the second block does the proxy redirect for the URL.
As far as i can see this catches all cases, but let me know if there are any gaping holes!
This rule should do it:
RewriteRule .*[^/]$ %{REQUEST_URI}/
Put this rule in front of your other rules. You also may want to add a condition to exclude existing files:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .*[^/]$ %{REQUEST_URI}/

Categories