bpurcell.org - Multi-tiered clustering with ISAPI Rewrite and CGI variable issues
Calendar
SunMonTueWedThuFriSat
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30            

Subject Archives
Amazon EC2 (15)
ColdFusionMX (155)
Corvette (3)
Flash Lite (4)
Flash Media Server (5)
Flash Player (3)
Flex (39)
General Web Dev (14)
HDTV (3)
Jboss (1)
Jquery (2)
JRun (59)
Max 2003 (3)
Other (33)
PC Hardware (16)
Software (17)
SpatialKey (7)
Wireless (8)
Working Out (1)

RSS Feed
Feed Listing

Site Contents
Home
My Blog
ColdFusion
JRun
Flex
Wireless & Networking
Hardware & Gadgets
HDTV
Software Picks
Pictures
Contact Me
Search


My Articles & Papers
Flex Performance
Server/Client
mm.com Under the Hood
Multiple Instances of CFMX
Multiple Instance Config
NLB with ColdFusion
Clustering CFMX for J2EE
Multi-Tier Hardware LB w CFMX
Cisco CSS & Coldfusion MX
JRun 4 Jini based Clustering
WiFi Growth

2ID Tacweb

Other Hobbys
Body-For-Life Challenge

Personal Projects
Family Pool
Deck Gate

username:
password:
 

 
Viewing Individual Entry / Main
September 1, 2008

This was something that I meant to write about a while ago but never got around to it. I recieved a question recently by email and wanted to provide some tips and tricks when using ISAPI Rewrite in a multi-tiered load balanced environment. I wrote an article with Frank DeRienzo several years ago about using a multi-tiered load balanced enviroment. I followed this up later with a blog entry on my site for Using ISAPI Rewrite with ColdFusion.

If you are using ISAPI Rewrite to proxy requests from your webserver (IIS) to you ColdFusion server or through a load balancer you will run into issues when accessing various CGI variables. When proxying the ColdFusion server sees the web server as the end client and therefore variables like CGI.HTTP_HOST are set to the IP or hostname of the webserver. To get around this I inject custom headers with ISAPI rewrite, parse them in CF and then stored them in the request scope.

First I start by adding the headers to the main httpd.ini Start->All Programs->Helicon->ISAPI_Rewrite->httpd.ini (you may need to change the read only flag in order to save the file)

#Due to the proxy we add these headers to use in cf through
#GetHttpRequestData().headers.HEADERNAME
RewriteCond %REMOTE_ADDR (.*)
RewriteHeader CLIENT_REMOTE_ADDR: ^$ $1

RewriteCond %SCRIPT_NAME (.*)
RewriteHeader CLIENT_SCRIPT_NAME: ^$ $1

RewriteCond %SERVER_NAME (.*)
RewriteHeader CLIENT_SERVER_NAME: ^$ $1

RewriteCond %SERVER_PORT (.*)
RewriteHeader CLIENT_SERVER_PORT: ^$ $1

RewriteCond %HTTP_HOST (.*)
RewriteHeader CLIENT_HTTP_HOST: ^$ $1

RewriteCond %SERVER_PROTOCOL (.*)
RewriteHeader CLIENT_SERVER_PROTOCOL: ^$ $1

#stores the original URL before any rewriting in a custom header
RewriteCond URL (.*)
RewriteHeader x_rewrite_url_original: ^$ $1

RewriteCond X-Rewrite-Proxy (.*)
RewriteHeader x_rewrite_proxy: ^$ $1

I then create a page in CF called httpheaders.cfm and include it early on in my CF code within Appplication.cfm or within onRequest of Application.cfc

<cfsilent>
<!--- this page is added to handle the custom headers we write with 
ISAPI Rewrite due to the issues we see with proxying requests.
 --->
<cfset httpheaders=GetHttpRequestData().headers>
<cfset REQUEST.proxyheaders=structNew()>
<cfif isdefined("httpheaders.CLIENT_REMOTE_ADDR")>
    <cfset REQUEST.proxyheaders.REMOTE_ADDR=httpheaders.CLIENT_REMOTE_ADDR>
<cfelse>
    <cfset REQUEST.proxyheaders.REMOTE_ADDR=CGI.REMOTE_ADDR>
</cfif>
<!--- I need to find a way to handle SCRIPT_NAME better, with ISAPI 
Rewrite and JRun ones are different --->
<cfif isdefined("httpheaders.CLIENT_SCRIPT_NAME")>
    <!--- <cfset 
REQUEST.proxyheaders.SCRIPT_NAME=httpheaders.CLIENT_SCRIPT_NAME> --->
    <cfset REQUEST.proxyheaders.SCRIPT_NAME=CGI.SCRIPT_NAME>
<cfelse>
    <cfset REQUEST.proxyheaders.SCRIPT_NAME=CGI.SCRIPT_NAME>
</cfif>
<cfif isdefined("httpheaders.CLIENT_SERVER_NAME")>
    <cfset REQUEST.proxyheaders.SERVER_NAME=httpheaders.CLIENT_SERVER_NAME>
<cfelse>
    <cfset REQUEST.proxyheaders.SERVER_NAME=CGI.SERVER_NAME>
</cfif>
<cfif isdefined("httpheaders.CLIENT_SERVER_PORT")>
    <cfset REQUEST.proxyheaders.SERVER_PORT=httpheaders.CLIENT_SERVER_PORT>
<cfelse>
    <cfset REQUEST.proxyheaders.SERVER_PORT=CGI.SERVER_PORT>
</cfif>
<cfif isdefined("httpheaders.CLIENT_SERVER_PROTOCOL")>
    <cfset 
REQUEST.proxyheaders.SERVER_PROTOCOL=httpheaders.CLIENT_SERVER_PROTOCOL>
<cfelse>
    <cfset REQUEST.proxyheaders.SERVER_PROTOCOL=CGI.SERVER_PROTOCOL>
</cfif>
<cfif isdefined("httpheaders.CLIENT_HTTP_HOST")>
    <cfset REQUEST.proxyheaders.HTTP_HOST=httpheaders.CLIENT_HTTP_HOST>
<cfelse>
    <cfset REQUEST.proxyheaders.HTTP_HOST=CGI.HTTP_HOST>
</cfif>
</cfsilent>

After including this code you can access the client's IP with "REQUEST.proxyheaders.REMOTE_ADDR".

One other challenge is detecting if a user is using HTTPS if you have front ended your site with a load balancer and use the SSL accelerator of BIG-IP or Cisco CSS. To the app it looks exactlyt he same. I will save that discussion for another blog posting. Let me know if you have any questions.

There should be a similar solution with mod_proxy in apache by adding headers I just have not researched it. If you have the information post your findings and I will add it to the blog.

Comments

Hi Brandon, Your articles have been very helpful. A couple of questions: 1. What is the issue with using the JRun connector with a BigIP hardware load balancer between the web server and the application servers? Is it still problematic using the latest version of ColdFusion? (We are having problems, so I assume it is, but I was wondering about the root of the issue) 2. We are using the multiple server install of ColdFusion MX 7 Enterprise (running on JRun) in distributed mode (separate machines for web and application servers) Can the ISAPI rewrite solution you recommend be used if we are using a multi-homed web server? Our sites do not use a context root, and different web sites point to different home directories. This works fine when we use the JRun connector to point to a single ColdFusion server (and we don't even have to have a web server installed on the application server box), but we run into issues when trying to load balance using the F5 BigIP solution. I have installed ISAPI rewrite, but it seems like this solution is going to require that the communication between the F5 and the CF server be in HTTP:, and I don't know that the site of origin on the multi-homed web server is passed. Even if it is, the administrative overhead of managing the sites on the application servers makes it an unattractive solution. Any suggestions you might have would be appreciated! -- Jim


<p> Sorry for the delay in responding. My email box is a mess of spam these days since I exposed it via my blog. I also fixed the issue with comments on the website. I have added this response to the blog posting as well. </p> <p> 1. It has been a while since I last worked with this but this is what I remember. JRun uses JRPP which is a proprietary protocol between the connector and JRun. It opens a pool of persistent connections and forwards requests through this pool. The hardware load balancers work best with HTTP although they do support many other protocols. I think the fact that the connection is persistent throws it off and requests keep getting sent to the main machine 2. Multi-homed sites do not work with this configuration unfortunately. Each one would need its own instance and unique webroot on the front end. </p> <p> Thanks Brandon </p>


In the post above you say: "One other challenge is detecting if a user is using HTTPS if you have front ended your site with a load balancer and use the SSL accelerator of BIG-IP or Cisco CSS. To the app it looks exactlyt he same. I will save that discussion for another blog posting.".

Can you give me some insight into how you handle this?


Great post about the ISAPI rewrite and CGI variable issues. We have our clients coming in through ssl and was wondering if you have anymore insights? CGI.HTTPS is listed as a cgi variable in CF as well, could this be mapped in a similar way?

Something like: RewriteCond %HTTPS (.*) RewriteHeader CLIENT_HTTPS: ^$ $1


Hey Brandon, did you get around to writing a post about the HTTPS issue? We're constantly struggling with this issue as well.

Tony


 
Page Render Time:203