RewriteCond not working to remove www. from subdomain URL - apache

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.new.domain.com [NC]
RewriteRule ^(.*)$ http://new.domain.com/$1 [L,R=301]
why when i enter http://www.new.domain.com is not redirected to http://new.domain.com?
The .htaccess file is in the right folder (it has more rewritecond's and they work)

The regexp syntax in your RewriteCond is slightly broken: the correct way to test for strict equality with www.new.domain.com (up to differences in case) is either
RewriteCond %{HTTP_HOST} ^www\.new\.domain\.com$ [NC]
or
RewriteCond %{HTTP_HOST} =www.new.domain.com [NC]
That said, those errors should not stop your rewrite rule from working: you original RewriteCond will match www.new.domain.com just fine, it just matches some other strings too (like wwwXnewYdomainZcomFOOBAR). In fact, I have a very similar set of rules in my own .htaccess file, and they work just fine:
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} !^vyznev\.net$
RewriteCond %{HTTP_HOST} ^(www\.)?vyznev\.net$ [NC]
RewriteRule ^(.*) http://vyznev.net/$1 [NS,L,R=permanent]
Most of the differences between your code and mine are purely cosmetic. The only potentially significant issue I can see if that you don't have a RewriteBase directive; you should definitely add one, if only to avoid potential problems later. Still, as far as I can tell, not having one shouldn't stop you from getting at least some redirect, even if it might not be to the URL you expect.

Related

three conditions and one rule to use any domain name in htaccess file

I have these conditions and rule in my htaccess file, and it works and does what it's supposed to do.
RewriteCond %{REQUEST_URI} !^/index/parser.php?(.*)?$
RewriteCond %{HTTP_HOST} ^(.*)\.mydomain\.extension$ [NC]
RewriteCond %{HTTP_HOST} ^(www\.)?([a-z0-9-.]+)\.mydomain\.extension [NC]
RewriteRule ^(.*)$ http://mydomain.extension/index/parser.php?%2&domain_name=mydomain.extension [QSA,L]
I want to rewrite it so it can work with any domain name pointed at the server, but don't know how. I tried this but it failed. It should only activate on subdomains, not root domains. Also, I am not versed on the whole dollar sign and percentage usage in htaccess files. $1, $2, %1, %2, etc. Never know when dollar or percent should be used, or what number to use after it.
RewriteCond %{REQUEST_URI} !^/index/parser.php?(.*)?$
RewriteCond %{HTTP_HOST} ^(.*)\.(.*)$ [NC]
RewriteCond %{HTTP_HOST} ^(www\.)?([a-z0-9-.]+)\.(.*) [NC]
RewriteRule ^(.*)$ /index/parser.php?%2&domain_name=%1 [QSA,L]
Edit
Tried this on last line. Still didn't work.
RewriteRule ^(.*)$ http://%1/index/parser.php?%2&domain_name=%1 [QSA,L]
Edit
Tried suggestion and it made this:
something.tld
Go to this:
http://tld/index/parser.php?something&domain_name=tld
Should be:
http://something.tld/index/parser.php?something&domain_name=something.tld
Edit
The next version didn't work either. Showed an internal server error page. Same error whether domain.tld was used or subdomain.domain.tld was used.
How about:
RewriteCond %{REQUEST_URI} !^/index/parser.php
RewriteCond %{HTTP_HOST} ^(?:www\.|)([a-z0-9-]+)\.(.+\.(?:[a-z]{2}\.[a-z]{2}|[a-z]+))$ [NC]
RewriteRule ^(.*)$ http://%2/index/parser.php?%1&domain_name=%2 [QSA,L]
So this will take a request for:
http://www.foo.some-domain.tld/anything
and redirect to:
http://some-domain.tld/index/parser.php?foo&domain_name=some-domain.tld
As far as the backreferences go, the $ ones backreference groupings made in the rewrite rule, while the % ones backrefernce groupings from a rewrite condition.
See: http://httpd.apache.org/docs/trunk/rewrite/intro.html#regex

Issue in execution order with RewriteRules

Due to marketing reasons, I'm using some vanity URL's for friendlier access, and to track some campaigns. Unfortunately, I'm stuck on a managed dedicated server, with cPanel, and these were the steps I took to write my rules:
First, I added xyz.com and efg.com to parked domains in my cPanel
Then I wrote all the RewriteRules that I needed
.htaccess
RewriteCond %{HTTP_HOST} ^xyz\.com$ [OR]
RewriteCond %{HTTP_HOST} ^www\.xyz\.com$
RewriteRule ^signdirections$ "http\:\/\/xyz\.abc\.com\/en?utm_source=signdirections&utm_medium=advert&utm_campaign=xyz" [R=301,L]
RewriteCond %{HTTP_HOST} ^efg\.com$ [OR]
RewriteCond %{HTTP_HOST} ^www\.efg\.com$
RewriteRule ^signdirections$ "http\:\/\/efg\.abc\.com\/en?utm_source=signdirections&utm_medium=advert&utm_campaign=efg" [R=301,L]
Now, the problem is that if I try to access www.efg.com/signdirections, I will get redirected to the www.xyz.com/signredirections version, instead of efg's one.
Any idea, why that is happening? My intuition, is that it detects the same hostname (HTTP_HOST), but I can't understand why.
Most likely it is happening due to your other rules. Better to use THE_REQUEST variable that doesn't change after application of other rules.
You can also combine both your rules into one:
RewriteCond %{HTTP_HOST} ^(?:www\.)?(xyz|efg)\.com$ [NC]
RewriteCond %{THE_REQUEST} /signdirections [NC]
RewriteRule . http://%1.abc.com/en?utm_source=signdirections&utm_medium=advert&utm_campaign=%1 [R=301,L,NE,QSA]
Make sure this is your first rule below RewriteEngine On line.
Make sure to test it in a new browser to avoid old browser cache.
I don't know, if that can be a cache error after a bad test:
How long do browsers cache HTTP 301s?
Just a simplified version:
RewriteCond %{HTTP_HOST} ^(?:www\.)?xyz\.com$
RewriteRule ^signdirections$ http://xyz.abc.com/en?utm_source=signdirections&utm_medium=advert&utm_campaign=xyz [R=302,L]
RewriteCond %{HTTP_HOST} ^(?:www\.)?efg\.com$
RewriteRule ^signdirections$ http://efg.abc.com/en?utm_source=signdirections&utm_medium=advert&utm_campaign=efg [R=302,L]
Try with R=302, and when everything works, change for R=301

making smart domain general 301 redirects for moved pages using .htaccess

I found my server's c-panel produced code of the following form when I defined redirects using it's web gui. This works fine. However I'm concerned that I could write this much more efficiently, more generally and hopefully with less repetition.
RewriteCond %{HTTP_HOST} ^domain\.com$ [OR]
RewriteCond %{HTTP_HOST} ^www\.domain\.com$
RewriteRule ^some/unwanted/uri$ "http\:\/\/www\.domain\.com\/some/improved/uri" [R=301,L]
RewriteCond %{HTTP_HOST} ^domain\.com$ [OR]
RewriteCond %{HTTP_HOST} ^www\.domain\.com$
RewriteRule ^someother/unwanted/uri$ "http\:\/\/www\.domain\.com\/someother/improved/uri" [R=301,L]
repeat x20
I understand from Jon Lin's answer that repeating the following would usually be necessary.
RewriteCond %{HTTP_HOST} ^domain\.com$ [OR]
RewriteCond %{HTTP_HOST} ^www\.domain\.com$
However hjpotter92 has suggested shortening that to:
RewriteCond %{HTTP_HOST} ^(www\.)?domain\.com$
This is definitely an improvement but how can it be made domain general too. Could that be written as follows to apply to apply more generally to test.domain.com too?
e.g.:
RewriteCond %{HTTP_HOST} ^(*\.)?domain\.com$
I also understand from Jon Lin's answer that I could also replace the following in my code
"http\:\/\/www\.domain\.com\/some/improved/uri" [R=301,L]
with:
"/some/improved/uri" [R=301,L]
Which is gladly both shorter and more general.
Is there any need to keep repeating the following?
Yes, rewrite conditions only apply to the immediately following rule, so any following rules won't have those conditions be applied.
It's not really that inefficient to repeat the conditions, since the conditions aren't even checked unless the rule's pattern matches. That means given this rule:
RewriteCond %{HTTP_HOST} ^peterliddle\.com$ [OR]
RewriteCond %{HTTP_HOST} ^www\.peterliddle\.com$
RewriteRule ^work/cornwall/cornwall_early$ /redirect-target [L,R=301]
If the URL was /blahblah, the rewrite engine first tries to match that URL against the rule's pattern, and since it doesn't match ^work/cornwall/cornwall_early$, the whole rule is skipped, the conditions don't even need to be considered.
If it's a matter of being hard to read, you could have a rule at the very top that bypasses all rules in your htaccess file if those conditions are not met. For example:
RewriteCond %{HTTP_HOST} !^(www\.)?peterliddle\.com$ [NC]
RewriteRule ^ - [L]
RewriteRule ^work/cornwall/cornwall_early$ http://www.peterliddle.com/work/cornwall/cornwall_58-65 [R=301,L]
RewriteRule ^work/cornwall/cornwall$ http://www.peterliddle.com/work/cornwall/cornwall_66-69 [R=301,L]
RewriteRule ^work/whale_moor_a/a_first$ http://www.peterliddle.com/work/whale_moor/lakeland_hills [R=301,L]
So if the conditions for the HTTP HOST fails, the rules are completely bypassed. Problem with doing things this way is you'd have to add any new rules that you don't want the conditions to be applied above these rules.
You can also remove the http://www.peterliddle.com part from your rule's target, since you've already tested for the same domain in the HTTP_HOST.
Following kind advice on stack overflow, testing and some reading I settled on a list of rewrite rules following of the form:
RewriteCond %{HTTP_HOST} (^|\.)domain\.com$
RewriteRule ^some/unwanted/uri$ "/some/improved/uri" [R=301,L]
N.B. The following snippet does not work. It crashes the site and is not recommended.
RewriteCond %{HTTP_HOST} ^(*\.)?domain\.com$
The following seams to work across all subdomains. Therefore I can test in test.domain.com and then use the same .htaccess file in www.domain.com and have greater confidence it will work without having to make further changes to the code.
RewriteCond %{HTTP_HOST} (^|\.)domain\.com$

Mod ReWrite to remove component of URL

I must be an idiot because I just can't work this bit out.
I've got a URL:
www.site.com.au/products/product-name.html
I need to redirect these to:
www.site.com.au/product-name.html
All the links are dynamic, the folder doesn't exist. What ReWrite rule do I use to accomplish this?
This is what I've got so far:
RewriteCond %{HTTP_HOST} ^(www|test)\.site\.com\.au
RewriteCond %{REQUEST_URI} ^(/products/)
RewriteCond %{REQUEST_URI} [A-Z]
RewriteRule ^.+\.html$ ${lc:%{REQUEST_URI}} [NC,R=301,L]
Just need to add the bit to remote /products
Thanks.
RewriteRule ^products(/.*)$ http://www.site.com.au$1 [L, R=301]
This replaces everything you listed, except for the first RewriteCond (to match the domain, though if your VirtualHost only answers on those two domains, you can exclude that RewriteCond to simplify it).
RewriteRules are matched first before Apache looks at the RewriteConds, so if you can do the match in the RewriteRule itself it greatly simplifies things. Just for your future reference, if you did need to match in the RewriteCond, it would look something like this:
RewriteCond %{REQUEST_URI} ^/products(/.*)$
RewriteRule ^.*$ http://www.site.com.au%1 [L, R=301]
Note the %1 for matching what's in the parentheses in the RewriteCond vs. the $1 for matching what's in the RewriteRule.
EDIT: Per your comment, the following modification should force lowercase. I haven't had to do that myself, but per this Apache documentation it's an internal function via RewriteMap. Based on your original code it looks like maybe you already have the RewriteMap definition elsewhere. If not, I've included it here.
RewriteMap lc int:tolower
RewriteCond %{REQUEST_URI} ^/products(/.*)$ [NC]
RewriteRule ^.*$ http://www.site.com.au${lc:%1} [L, R=301]
OK, I really don't know enough about Apache Rewrite to figure out the exact formatting. But after much ado these are the results that worked:
# Lowercase all /products/
RewriteCond %{HTTP_HOST} ^(www)\.site\.com\.au
RewriteCond %{REQUEST_URI} ^/products/.+\.html
RewriteCond %{REQUEST_URI} [A-Z]
RewriteRule ^ ${lc:%{REQUEST_URI}} [R=301,L]
# Lowercase all /products/ and strip products/ subfolder
RewriteCond %{HTTP_HOST} ^(www)\.site2\.com\.au
RewriteCond %{REQUEST_URI} ^/products/.+\.html
RewriteCond %{REQUEST_URI} [A-Z]
RewriteRule ^products/(.+\.html)$ /${lc:$1} [R=301,L]
Thanks,
Dom

How to avoid chain redirections using mod_rewrite?

Basicly i'm working on my site to be SEO-friendly. I wanted to achieve following:
Rewrite urls to pretty ones
Remove multiple slashes (eg. example.com/////something/// to example.com/something/
Redirect www version to a non-www version.
Hide index.php file from all urls
Redirect from old (/?id=something/ to new urls /something/)
I came up with this .htaccess code:
RewriteCond %{THE_REQUEST} //
RewriteRule .* $0 [R=301]
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteCond %{QUERY_STRING} ^id=([a-z0-9\/-]+)
RewriteRule ^(.*)$ http://example.com/%1? [R=301]
RewriteRule ^index.php(.*)$ /$1 [R=301]
RewriteRule ^([a-z0-9\/-]+)$ /?id=$1 [L]
...and though it's working it has a side effect: chain redirects, eg. example.com/?id=something////// -> example.com/something////// -> example.com/something/
So is there a way to rewrite or modify this code so it'll be redirecting just once to the preferred version of the url?
Trying to interpret what you want, let's look at the rules in your question:
.1 Can't understand the purpose of this:
RewriteCond %{THE_REQUEST} //
RewriteRule .* $0 [R=301]
.2 This rule-set in your question removes www and converts the query string ?id=val to /val, but only when the incoming URI has www AND there is a query string as both conditions must be met:
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteCond %{QUERY_STRING} ^id=([a-z0-9\/-]+)
RewriteRule ^(.*)$ http://example.com/%1? [R=301]
.3 This rule
RewriteRule ^index.php(.*)$ /$1 [R=301]
Hides index.php, but only when it is in the root directory. Example:
http://www.example.com/index.php?id=val
Does not work when it is in a subdirectory. Example:
http://www.example.com/folder/index.php?id=val
.4 Can't understand the purpose of this:
RewriteRule ^([a-z0-9\/-]+)$ /?id=$1 [L]
I suggest this instead:
RewriteEngine On
RewriteBase /
#Redirects all www to non-www
RewriteCond %{HTTP_HOST} www\.example\.com$ [NC]
RewriteRule ^(.*)/?$ http://example.com/$1 [R=301,L]
#Hides "index.php" keeping the query if present
RewriteRule ^(.*)/index\.php$ $1/ [R=301,QSA,L]
#Converts query string `?id=val` to `/val`
RewriteCond %{QUERY_STRING} id=([^/]+)
RewriteRule .* /%1? [R=301,L]
Remember spiders will "adapt" to the correct new structure after a few months, and the problem may ultimately be a whole lot less severe than what it looks like initially. You can leave all the .htaccess code in place, knowing it always be there to correct any "old" references yet will in fact hardly ever actually be used.
I've never found an easy way to avoid multiple round trips back to the client when "fixing up" a URL to be in some sort of canonical form. mod_rewrite seems to be more focussed on the "local" redirect case where the client has no idea that the content it got back came out of a file structure that doesn't perfectly match that implied by the URL.
It is possible to save up all the URL mods locally, then provoke only one round trip to the client that delivers all the URL corrections all at once by setting everything in newly created "environment" variables then at the end asking basically "has anything changed?" However doing so is notably verbose and rather awkward and quite error-prone and has never become a "recommended technique".