Url Rewriting with IIS 6/7 - Rewriting Host Name {HTTP_HOST} - asp.net

I need to rewrite the "Host Name" {HTTP_HOST} for an incoming request. Is it possible to do this using IIS 7 Rewrite Module?
I want to rewrite http://abc.xyz.com/* to http://xyz.com/sites/abc/*. This is being done for a SharePoint site which uses the {HTTP_HOST} internally.
Are there any Url Rewriters out there which let me change the {HTTP_HOST} variable of IIS?
Kind regards,

You can use IIS 7 URL Rewrite Module 2.0 to change the HTTP_HOST server variable. More information on how to do it is available in Setting HTTP request headers and IIS server variables.

IIRF is free, and lets you rewrite headers, including HTTP_HOST.
I want to rewrite http://abc.xyz.com/* to http://xyz.com/sites/abc/*. This is being done for a SharePoint site which uses the {HTTP_HOST} internally.
You need to rewrite both the Host and the Url. This makes it a little complicated. In this ruleset, I do it in steps, and use a new header to store state between the steps:
# detect whether we're using the abc host
RewriteCond %{HTTP_HOST} ^abc\.xyz\.com$
RewriteHeader Host-Needs-Rewrite: ^$ YaHuh
# rewrite the Host: header to the alt host name if necessary
RewriteCond %{HTTP_HOST_NEEDS_REWRITE} ^YaHuh$
RewriteCond %{HTTP_HOST} ^(?!xyz\.com)(.+)$
RewriteHeader Host: .* xyz.com
# rewrite the Url to the appropriate place
RewriteCond %{HTTP_HOST_NEEDS_REWRITE} ^YaHuh$
RewriteCond %{HTTP_HOST} ^xyz\.com$
RewriteRule /(.*)$ /sites/abc/$1 [L]
You could wildcard the abc part, too. Like this:
# detect whether we're using the abc host
RewriteCond %{HTTP_HOST} ^([^.]+)\.xyz\.com$
RewriteHeader Host-Needs-Rewrite: ^$ %1
# rewrite the Host: header to the alt host name if necessary
RewriteCond %{HTTP_HOST_NEEDS_REWRITE} ^.+$
RewriteCond %{HTTP_HOST} ^(?!xyz\.com)(.+)$
RewriteHeader Host: .* xyz.com
# rewrite the Url to the appropriate place
RewriteCond %{HTTP_HOST_NEEDS_REWRITE} ^(.+)$
RewriteCond %{HTTP_HOST} ^xyz\.com$
RewriteRule /(.*)$ /sites/%1/$1 [L]

I'm not familiar with the IIS 7 Rewrite Module, but ISAPI_Rewrite can change pretty much any HTTP header you want. There's a free version which is enough for our site and may well be enough for yours.

Yes, it is possible to use the IIS 7 Rewrite Module. You can use the GUI to setup a redirect in IIS7 per this blog post.

If you're wanting to avoid a redirect (per your comment to Evgeny) the only other option is a server.transfer. With server.transfer the processing is sent to a different page on the server and the client has no idea (there's no round trip back to the client between pages).
Aside from server.transfer actual redirects are quite typical ISAPI_Rewrite is a popular tool and works really well as Evgeny mentioned.

UPDATE: This will do a redirect, not reset the variable. I won't delete this answer as I think it's neat but it doesn't answer exactly what you want
I do this in a very simple way for Economist.com
You have two IIS sites for one site, they share the same webroot. The master IIS web site stays as is listening on the current host header e.g.
216.35.68.215 economist.com
and the other IIS site listens on the ip address with the other host headers entered.
i.e.
216.35.68.215 economist.co.uk
The second web slave in the "Home Directory" has a redirect set which will correct whatever host name people arrive at your site on
Set "The exact URL entered above" and "A permanent redirection for this resource"
and enter your fully qualified host name entry as follows
http://www.economist.com$S$Q
The $S$Q will maintain all URLs on your other host names that enter.
Feel free to test this
http://www.economist.co.uk/world/americas/
will just push you to
http://www.economist.com/world/americas/
This means you don't have to run, at least for this reason, the fairly expensive IIS rewrite module

Related

Editing htaccess file to redirect only content + Wordpress

I have created a subfolder in my webserver and installed wordpress there, it's working ok. And now i have created several subdomains. I need to show pages made in the wordpress installation in those subdomains but without changing the addess shown in the web browser address bar.
Options +FollowSymLinks
RewriteEngine on
RewriteOptions inherit
RewriteBase /
RewriteCond %{HTTP_HOST} ^sub.example.com$ [NC]
RewriteRule ^(.*)$ https://example.com/WPweb/index.php/pagetobeshown [R=301,NC,L,QSA]
with this i am being redirected and content is shown ok, but the address bar is changed.
is it possible to fix this so that address is not changed?
thanks in advance
To do this in .htaccess you would need to configure your server as a reverse proxy and proxy the request from the subdomain to the URL on the main domain. WordPress will then see this as a request for the main domain.
However, this does require some configuration in your server config to ensure the appropriate modules are loaded (mod_proxy, mod_proxy_http, etc.) and optionally to set ProxyPassReverse if WordPress should issue any redirects.
You can then use the P flag with mod_rewrite's RewriteRule to send the request through mod_proxy. For example:
RewriteCond %{HTTP_HOST} ^sub\.example\.com
RewriteRule ^$ https://example.com/WPweb/index.php/pagetobeshown [P]
This sends requests for https://sub.example.com/ only (ie. the document root of the subdomain) to the URL as stated. The NC, QSA and L flags are not required.
If you want to send any URL-path (as implied by your RewriteRule directive) to the URL on the target site then change the RewriteRule pattern from ^$ to ^ (simply remove the $). However, this many-to-one relationship is not necessarily good for SEO.
You will still need to modify the rel="canonical" link elements in the page to the appropriate URL in WordPress itself.
However, I'm sure there is a better, more WordPress-specific way to solve this. But WordPress would need to be configured to accept requests to the subdomain and the alternative URL-path.

Redirecting URLs to new domain using htaccess

I want to redirect some URLS on the old site to specific destination on the new site and the rest of the URLS to the home page. So far I have tried the following:
Use Redirect 301 /permalink https://newsite.com/permalink1/ for all the links that need to go to a specific page on the new site
For the rest, I added a generic rule
RewriteCond %{HTTP_HOST} ^oldsite\.com$ [NC]
RewriteRule ^(.*)$ https://newsite.com [R=301,L]
but this redirects all the pages to the home page of the new site.
Then I tried to replace point 2 above with RedirectMatch
RedirectMatch 301 .* https://newsite.com
but this tries to find an exact match on the new site. oldsite.com/xyz goes to https://newsite.com/xyz
Also, some of the old site URLs have parameters, oldsite.com/a=?b=123 how can I redirect such parameters to the new site homepage.
This probably is a straight forward approach:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^oldsite\.com$
RewriteRule ^/?permalink1old(/.*)$ https://newsite.com/permalink1new$1 [R=301,QSA]
RewriteCond %{HTTP_HOST} ^oldsite\.com$
RewriteRule ^/?permalink2old(/.*)$ https://newsite.com/permalink2new$1 [R=301,QSA]
RewriteCond %{HTTP_HOST} ^oldsite\.com$
RewriteRule ^ https://newsite.com/ [R=301]
So you redirect the old permalinks on the old host name to their new counterpart on the new host name, appending anything that might follow in the path of the initial old permalink and you append the query string to preserve arguments.
If the permalinks never contain anything additional in their paths then you can simplify those redirections, obviously:
RewriteCond %{HTTP_HOST} ^oldsite\.com$
RewriteRule ^/?permalink1old/?$ https://newsite.com/permalink1new [R=301,QSA]
It is a good idea to start out with a 302 temporary redirection and only change that to a 301 permanent redirection later, once you are certain everything is correctly set up. That prevents caching issues while trying things out...
This implementation will work likewise in the http servers host configuration or inside a dynamic configuration file (".htaccess" file). Obviously the rewriting module needs to be loaded inside the http server and enabled in the http host. In case you use a dynamic configuration file you need to take care that it's interpretation is enabled at all in the host configuration and that it is located in the host's DOCUMENT_ROOT folder.
And a general remark: you should always prefer to place such rules in the http servers host configuration instead of using dynamic configuration files (".htaccess"). Those dynamic configuration files add complexity, are often a cause of unexpected behavior, hard to debug and they really slow down the http server. They are only provided as a last option for situations where you do not have access to the real http servers host configuration (read: really cheap service providers) or for applications insisting on writing their own rules (which is an obvious security nightmare).

Redirecting Dynamic URLs with Multiple IDs using .htaccess (Wordpress)

I've just moved my site onto Wordpress, which means the URL structure has now changed. I'd like to use a Rewrite Rule in the .htaccess file to redirect dynamic URLs with multiple IDs in one single statement, but am not having any success. An example is:
OLD URL: example.co.uk/seasons/season.php?ID=1819
NEW URL: example.co.uk/seasons/1819
The statements I have tried in .htaccess are:
RedirectMatch 301 ^/seasons/season.php?ID=(.*).htm$ example.co.uk/seasons/$1
and
RewriteCond %{QUERY_STRING} ^?ID=1$
RewriteRule ^/seasons/season.php$ example.co.uk/seasons/? [R=301,L]
In neither case, the redirect fires. Is there something about a Wordpress .htaccess file that I'm not considering, or is the error with the statements I'm attempting. I'm using .htaccess 301 redirects for http to https and non-www to www without issue.
This is the fixed version of the approach you chose, to make an external redirection:
RewriteEngine on
RewriteCond %{QUERY_STRING} (?:^|&)ID=(\d+)(?:&|$)
RewriteRule ^/?seasons/season\.php$ https://example.co.uk/seasons/$1 [R=301,QSD]
Since both, the old and new URLs use the same host name you can simplify that:
RewriteEngine on
RewriteCond %{QUERY_STRING} (?:^|&)ID=(\d+)(?:&|$)
RewriteRule ^/?seasons/season\.php$ /seasons/$1 [R=301,QSD]
It is a good idea to start out with a 302 temporary redirection and only change that to a 301 permanent redirection later, once you are certain everything is correctly set up. That prevents caching issues while trying things out...
These rules will work likewise in the http servers host configuration or inside a dynamic configuration file (".htaccess" file). Obviously the rewriting module needs to be loaded inside the http server and enabled in the http host. In case you use a dynamic configuration file you need to take care that it's interpretation is enabled at all in the host configuration and that it is located in the host's DOCUMENT_ROOT folder.
And a general remark: you should always prefer to place such rules in the http servers host configuration instead of using dynamic configuration files (".htaccess"). Those dynamic configuration files add complexity, are often a cause of unexpected behavior, hard to debug and they really slow down the http server. They are only provided as a last option for situations where you do not have access to the real http servers host configuration (read: really cheap service providers) or for applications insisting on writing their own rules (which is an obvious security nightmare).

How to configure a mod_rewrite to check both direct IP and proxy IP?

I am trying to configure our wordpress .htaccess file so that it blocks access to the wordpress wp-login.php and admin pages unless the client originates from within our networks.
The dev environment is directly accessible, but production is behind a proxy, so to keep things simple I wanted to configure one set of rules that would apply in either case.
I have configured the below set of rules, which based on my research, should be working:
#only allow use of wp-login or wp-admin from users inside
RewriteCond %{REQUEST_URI} ^(.*)?wp-login\.php(.*)$ [OR]
RewriteCond %{REQUEST_URI} ^(.*)?wp-admin$
RewriteCond %{REMOTE_ADDR} !^192\.168\.(1|2|3|4)\.[0-9]{1,3}$ [OR]
RewriteCond %{HTTP:X-FORWARDED-FOR} !^192\.168\.(1|2|3|4)\.[0-9]{1,3}$
RewriteRule ^(.*)$ - [R=403,L]
However, for some reason the [OR] between the REMOTE_ADDR and the X-FORWARDED-FOR appears to be ignored, causing the pages to be blocked in all cases.
Am I missing something?
Edit: I shouldn't have had the OR condition to begin with. Apparently my brain had insufficient coffee to compute basic binary operations.
I suppose that your clients go through a proxy or through a direct connection. Since you will block them if EITHER isn't matching, you'll most likely block them all. Someone coming via a local proxy should be getting through. I wouldn't do the XFF-stuff in the .htacces, use mod_remoteip if possible, and only trust your own proxies, because that header can be easily spoofed by the client.
Additionally, the $ in the wp-admin line means it won't match wp-admin/edit.php. Consider aswell that WP ajax requests go through wp-admin/admin-ajax.php, and you might need those.

Apache redirect to another server keeping browser address

A have a custom website based on apache/php. I also have a wordpress blog and I would like it to be hosted in a different server.
I have tried to create a sub-domine like http://blog.mydomine.com but i would like to keep the old address (http://www.mydomine.com/corp/blog) for SEO purposes. I added the following configuration tu my .htaccess file.
RewriteCond %{REQUEST_URI} ^/corp/blog
RewriteRule ^(.*)$ http://blog.mydomine.com/$1 [L]
I would like to know if I can tell apache not to change the browser address after redirect the request. I know that I could do a 301 redirection but i would prefer to keep the old address.
Any ideas? Thanks in advance!! :)
Use the P flag
http://httpd.apache.org/docs/current/rewrite/flags.html#flag_p
RewriteRule ^(.*)$ http://blog.mydomine.com/$1 [P]
You could try a reverse proxy...
ProxyRequests Off
ProxyPreserveHost on
ProxyPass /corp/blog http://blog.mydomine.com/
ProxyPassReverse /corp/blog http://blog.mydomine.com/
ProxyPassReverseCookiePath /corp/blog /
This requires mod_proxy be installed and enabled.
Note that this will only work in the following contexts per the apache doc: server config, virtual host, directory - this means that putting it in a htaccess file won't work.
What you're wanting isn't really possible. It's not Apache that's displaying the address, it's the web browser, and there's no way (thankfully) to tell a web browser "go to site A, but tell the user it's site B."
You could fake this behavior using a frame page on your main site, but since you're wanting this for SEO I don't think that would help.

Resources