I use the following rules to rewrite a subdomain call to a page in the root of the website:
RewriteCond %{HTTP_HOST} !^www\.domain\.com$ [NC]
RewriteCond %{HTTP_HOST} ^([a-zA-Z0-9/_.-]+)\.domain\.com$ [NC]
RewriteRule .? headlines.php?url=%1 [L,QSA]
This works fine. I use this for a rss - news related website. For example: http://economy.headlines.com will internally look at http://www.headlines.com/headlines.php?url=economy
I also want to link to the news items in the following way:
economy.headlines.com/news/title/id
How do i do this ? Because every time the first rules are "fired". Even if i make other rules with the [L] flag the other rules are fired and nothing happened.
How can i combine the rules above with new rules which also look at files in the root of the site but with parameters in the url ?
You should be able to combine both if you evaluate the path component of the request you rewrite:
Rewriteengine on
RewriteCond %{HTTP_HOST} !^www.domain.com$ [NC]
RewriteCond %{HTTP_HOST} ^([a-zA-Z0-9/_.-]+).domain.com$ [NC]
RewriteRule ^([^/]+)/([^/]+)/([^/]+)$ headlines.php?url=%1&category=$1&title=$2&id=$3 [L,QSA]
Probably you have to do some fine tuning, but I think you get the idea: the first argument of the RewriteRule is a regular expression that splits the request path into its components. Those can be referred to using the $1 and $2 notation you can see towards the end of the rule.
Edit: added the category parameter to the RewriteRule as discussed in the comments below.
Related
BEFORE I installed SSL things were working perfectly!! Here is the code I have in my root webserver .htaccess file:
Options +MultiViews
RewriteEngine On
RewriteCond %{HTTP_HOST} andrea\.com [NC]
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://andrea.com/$1 [R,L]
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule (.*) $1.php [L]
It works and it does exactly what I want it to do. So if I go to for example:
www.andrea.com/account
it accesses "www.andrea.com/account.php". Which is what I want.
I do however have a folder in root called "products". There is another ".htaccess" file in that folder and I don't know which of these 2 must be changed to make the following thing below work.
When you go to this url:
http:____/products/view/Hello/Goodbye
I want it to access "view.php" in the 'products' folder and in that php file I could do this:
$id = $_GET["id"]; // This would have "Hello"
$cat = $_GET["cat"]; // This would have "Goodbye"
And this works well when I use this htaccess in the "products" folder:
RewriteEngine on
RewriteCond %{HTTP_HOST} !^$
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]*)/?(.*)$ /products/view.php?id=$1&cat=$2
The problem with this code above is, if I go to:
http:____/products/Hello/Goodbye
I want it to access the "index.php" that is in "products" folder. But instead it goes to "view.php" instead!! It's like the htaccess code above forced all to go to view.php (which should only be done if I have the "view/____" in the url.
I want the url above to go to "index.php" in the "products" folder and in that file I should be able to access ID and CAT variables.
Any ideas of what to change in my .htaccess file? Sorry I spent over 2 hours I don't understand a single line at the bottom of my code but it doesn't work :/
Options +MultiViews
First off, you should disable MultiViews. In my answer to your earlier question, my suggestion to use MultiViews was strictly an "alternative" method in the context of your question. You cannot use both methods (mod_rewrite and MultiViews) to work with extensionless URLs. And since you are now wanting to do more things and pass parameters, MultiViews will only create conflicts. (MultiViews will likely "win" and no parameters get passed.)
Also, do you specifically need the additional .htaccess file in the /products subdirectory? It will be (arguably) easier to have a single .htaccess file in the document root. This will avoid having to repeat the HTTP to HTTPS redirect (although you've not actually included an HTTP to HTTPS redirect in the subdirectory .htaccess file?).
# /products/.htaccess
RewriteRule ^([^/]*)/?(.*)$ /products/view.php?id=$1&cat=$2
This directive matches both view/Hello/Goodbye and Hello/Goodbye, which explains why everything is being written to your view.php script. However, it's not actually doing what you say either - which is puzzling. If you request /products/view/Hello/Goodbye then it will rewrite the request to /products/view.php?id=view&cat=Hello/Goodbye - which is not the intention (unless MutliViews is enabled, in which case no parameters will be passed at all).
You need to actually check for views in the requested URL-path before attempting to rewrite to views.php. And if views is not present then rewrite to index.php instead. This "conditional branching" can be achieved by simply arranging the directives in the order of "more specific" rules first.
For example, in your root .htaccess file try the following. (And remove the /products/.htaccess file altogether.)
# Ensure that MultiViews is disabled
Options -MultiViews
RewriteEngine On
# HTTP to HTTPS canonical redirect
RewriteCond %{HTTP_HOST} example\.com [NC]
RewriteCond %{SERVER_PORT} 80
RewriteRule (.*) https://example.com/$1 [R=301,L]
# Abort early if the request already maps to (or looks like) a file or directory
RewriteCond %{REQUEST_URI} \.\w{2,4}$ [OR]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# 1. Rewrite "/products/view/<id>/<cat>" to "/products/view.php?id=<id>&cat=<cat>
RewriteRule ^(products/view)/([^/]*)/?(.*) $1.php?id=$2&cat=$3 [L]
# 2. Rewrite "/products/<id>/<cat>" to "/products/index.php?id=<id>&cat=<cat>
RewriteRule ^(products)/([^/]*)/?(.*) $1/index.php?id=$2&cat=$3 [L]
# 3. Extensionless URLs for other requests
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule (.*) $1.php [L]
The order of the 3 rules above is important. The most specific rule is first. Including the L flag to prevent further (unnecessary) processing.
Note that, as per your original directives, for a request of the form /products/view/Hello/Goodbye (or /products/Hello/Goodbye), the Hello/Goodbye part is entirely optional and will naturally result in the id and cat URL parameters being set, but empty.
Also, as per your original directives, a request of the form /products/view/Hello/Goodbye/foo/bar/baz will result in the cat URL parameter being set to Goodbye/foo/bar/baz (anything that follows the initial path segment).
You do not necessarily need to check that a request maps to a file or directory (which is relatively expensive) if you make your regex more specific and only match what you need to match. For example, your regex /([^/]*)/?(.*) currently match pretty much anything. But if your <id> and <cat> variables can only consist of lowercase letters (for example) then this could avoid the need for the filesystem checks.
Other notes:
Do you need to check the hostname in the HTTP to HTTPS redirect? Do you host multiple domains? Otherwise the condition that checks against the HTTP_HOST server variable is not required.
You can use the following rule to rewrite /products/Hello/Goodbye to /products/index.php .
RewriteRule ^Hello/GoodBye/?$ /product/index.php?id=hello&cat=Goodbye [L,NC]
Here is your complete /product/.htaccess .
RewriteEngine on
RewriteCond %{HTTP_HOST} !^$
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
#rewrite /products/Hello/GoodBye to /products/index.php
RewriteRule ^Hello/GoodBye/?$ /products/index.php?id=Hello&cat=Goodbye [L,NC]
###################
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]*)/?(.*)$ /products/view.php?id=$1&cat=$2
I'm trying to say:
For all IP Addresses that are not within the 110.140 or 110.10 ranges. If they are trying to access a URL that begins with "stage." then redirect them to the same URL but remove the "stage." portion of the string from the url.
RewriteCond %{REMOTE_ADDR} !^(110\.(140|10)) [NC]
RewriteCond %{HTTP_HOST} ^stage\. [NC]
RewriteRule stage\.(.*) https://$1 [R=301,L]
When using just the last two lines in made with love htaccess tester the last line fails (is not met). I haven't tested the code on a server.
Update:
After reading the Apache RewriteRule Directive details, I realized that the RewriteRule Directive does not search the HTTP_HOST, only the things after that. Therefore this approach will not work. Does anyone have an approach that will work?
Looks like your hostname starts with stage. not the URI. You may use this rule:
RewriteCond %{REMOTE_ADDR} !^110\.(140|10)
RewriteCond %{HTTP_HOST} ^stage\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L,NE]
I'm trying to redirect two kind of urls to a subdomain and all the others to my main domain.
A concrete example :
"my account" pages starting by /my-account/* and subscription page must be redirected to https://my-account.domaim.com. The uri must be kept.
all others like /news or the homepage must be seen on www.domain.com only
Here is what I have tried until now :
# All urls except my-account/* and subscription are redirected to the main domain
RewriteCond %{HTTP_HOST} ^my-account\.domain\.(.+)$
RewriteCond %{REQUEST_URI} !^my-account/
RewriteCond %{REQUEST_URI} !^subscription$
RewriteRule ^(.*)$ http://www.domain.%1/$1 [L,QSA,R=301]
# subscription page is redirected to my-account subdomain
RewriteCond %{HTTP_HOST} ^www\.domain\.(.+)$
RewriteRule ^subscription$ https://my-account.domain.%1/subscription[L,QSA,R=301]
# All my-account/* pages are redirected to my-account subdomain
RewriteCond %{HTTP_HOST} ^www\.domain\.(.+)$
RewriteRule ^my-account/(.*)$ https://my-account.domain.%1/my-account/$1 [L,QSA,R=301]
Each rules work independently but if i try all of them together i'm stuck in an infinite loop.
Is anyone have an idea how to prevent it ?
The rules look fine, but you have a missing space in your 2nd rule:
RewriteRule ^subscription$ https://my-account.domain.%1/subscription[L,QSA,R=301]
# -----------------------------------------------------------------^
But you can probably combine them into a single rule:
RewriteCond %{HTTP_HOST} ^www\.domain\.(.+)$
RewriteRule ^(subscription|my-account/.*)$ https://my-account.domain.%1/$1 [L,QSA,R=301]
Also make sure you're clearing your cache when you test, as 301 redirects are permanent and the browser will cache them.
Thanks for your answer !
The typos was from my copy/paste and the combination works but doesn't change anything to the problem with the other rules. I keep it for later ;)
I tried a reversed rules like this :
#RewriteCond %{HTTP_HOST} !^my-account\.domain\.(.+)$ [NC]
#RewriteCond %{REQUEST_URI} ^/subscription$ [OR]
#RewriteCond %{REQUEST_URI} ^/my-account/ [NC]
#RewriteRule ^(.*)$ https://my-account.domain.%1/$1 [L,R=301]
It also works but not in combination with the other. it doesn't loop anymore but if i try something like http/www.domain.com/subscription i'm redirected to www.domain.com with the url truncated. It seems that the Rewrite conditions aren't correctly recognized but still can't find why ...
I found myself with this problem, which is driving me a little bit crazy. I use apache's mod_rewrite for pretty URLs and I need to use dynamic subdomains in the site. Everything is great and all the server has de wildcards. I use the next code on my .htacess:
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www.mysite.com
RewriteCond %{HTTP_HOST} ([^.]+).mysite.com [NC]
RewriteRule ^(.*)$ http://www.mysite.com/%1 [L]
The only problem is, even if I use the [L] flag the url of the site change to http://mysite.com/subdomain. What i want is the url to be like http://subdomain.mysite.com
The link mysite.com/subdomain is a dynamic url and is solved with another rule with the following code:
RewriteRule ^([A-Za-z]+)$ filter.php?type=subdomain&subdomain=$1
Any help would be appreciated
If you specify an external URL (which changing the subdomain does), a header redirect will take place. I don't think you can prevent that. But why not skip that step altogether, and use the second RewriteRule straight away?
I can't test this right now, but something like
RewriteCond %{HTTP_HOST} !^www.mysite.com
RewriteCond %{HTTP_HOST} ([^.]+).mysite.com [NC]
RewriteRule ^(.*)$ filter.php?type=subdomain&subdomain=$1
should work.
I am trying to create a mod_rewrite rule to direct people to a sub-folder. Currently the code looks as follows:
RewriteEngine On
RewriteCond %{HTTP_HOST} abcsite.com$ [OR,NC]
RewriteCond %{HTTP_HOST} ^!www\.abcsite\.*$
RewriteCond %{REQUEST_URI} !^/abc/.*$
RewriteRule (.*)$ /abc/$1 [L]
The redirect works if the user types www.abcsite.com, but not if they type abc.com. Is there something that I am missing or should do differently to make sure the user goes to the correct folder (regardless of how they type the URL)?
Side note: The htaccess file that I am dealing with is a Joomla file, so all contents of it deal with another Joomla site. I appreciate the help.
Because you have conditions for that.
RewriteCond %{HTTP_HOST} abcsite.com$ [OR,NC]
RewriteCond %{HTTP_HOST} ^!www\.abcsite\.*$
RewriteCond %{REQUEST_URI} !^/abc/.*$
All above rules will pass only its abcsite.com
You add following rules also then it work for abc.com too.
RewriteCond %{HTTP_HOST} abc.com$ [OR,NC]
RewriteCond %{HTTP_HOST} ^!www\.abc\.*$
RewriteCond %{REQUEST_URI} !^/abc/.*$
RewriteRule (.*)$ /abc/$1 [L]
There's a stray ! in your second condition. A ! in front of the pattern means that the condition is true when the regex doesn't match (like in the third condition). A ! inside the pattern is just a literal symbol.
The host conditions should be something like:
RewriteCond %{HTTP_HOST} ^abcsite\.com$ [OR,NC]
RewriteCond %{HTTP_HOST} ^www\.abcsite\.com$ [NC]
And in fact, they can be joined into a single condition (note, no [OR] here):
RewriteCond %{HTTP_HOST} ^(www\.)?abcsite\.com$ [NC]
Your third condition is intended to prevent redirect loops (/foo → /abc/foo → /abc/abc/foo → …). What it says is that the rule isn't applied if the request URL starts with /abc/. However, your actual redirect is an internal redirect: if a user accesses abcsite.com/foo, the server internally rewrites this to /webroot/abc/foo, but REQUEST_URI stays the same, /foo.
The reason this doesn't cause a redirect loop as it is is likely rewrite rules in abc/.htaccess which override this one once the redirect is done.
What should be checked instead in the third condition is the path matched by the rewrite rule:
RewriteCond $1 !^abc/
RewriteRule (.*) /abc/$1 [L]