Forum Discussion
delvinadm_21686
Nimbostratus
Feb 18, 2009URL Rewrite without Redirect
Hi everybody,
I've got a big problem, which I can't resolv.
The client types in the adressbar:
www.somesiteA.com/AAA
and the Loadbalancer should rewrite to this:
www.somesiteB.com:4444/AAA
But the important thing is, a HTTP::rewrite is not possible.
The client should see www.somesiteA.com/AAA, the Loadbalancer should act as an reverse Proxy.
I want the same result, as I would use the ProxyPass module on an apache httpd.
It would be very nice, to get a solution for this!
Thank you very much so far.
22 Replies
- hoolio
Cirrostratus
Hi,
There is a ProxyPass iRule in the Codeshare (Click here). Try reading through the configuration notes and reply here if you have any questions.
Aaron - delvinadm_21686
Nimbostratus
Hi Aaron,
thanks for this hint.
So I just created an iRule called ProxyPass and pasted the whole iRule from the link.
Then, I assigned this iRule for the virtual Host(webservice) and selected the default http profile. Afterwards, I created a Data Group called ProxyPasswebservice with an entry:
http://webservice.xxx.xx/WebService http://ihstestweb.xxx.xx:1234/Webservice
By typing http://webservice.xxx.xx/WebService, I just get an empty page. The pagesource is empty.
Considering the loadbalancer's logfile, I just see the following entries:
Rule ProxyPass CLIENT_ACCEPTED: ProxyPass webservice: 145.xxx.xxx.xxx:12466 - 145.xxx.xxx.xxx:80
tmm tmm[933] Rule ProxyPass HTTP_REQUEST: ProxyPasswebservice, Host=webservice.xxx.xx, URI=/WebService/: Removed Accept-Encoding header
tmm tmm[933] Rule ProxyPass HTTP_REQUEST: ProxyPasswebservice, Host=webservice.xxx.xx, URI=/WebService/: New HTTP request
tmm tmm[933] Rule ProxyPass HTTP_REQUEST: ProxyPasswebservice, Host=webservice.xxx.xx, URI=/WebService/: Checking class line: http://webservice.xxx.xx/WebService/ http://ihstestweb.xxx.xx:1234/WebService/
ihstestweb webservice.xxx.xx/WebService/ starts_with http://webservice.xxx.xx/WebService/
Rule ProxyPass HTTP_REQUEST: ProxyPasswebservice, Host=webservice.xxx.xx, URI=/WebService/: Checking class line: http://webservice.xxx.xx/WebService/ http://ihstestweb.xxx.xx:1234/WebService/ ihstestweb /WebService/ starts_with http://webservice.xxx.xx/WebService/
tmm tmm[933] Rule ProxyPass HTTP_REQUEST: ProxyPasswebservice, Host=webservice.xxx.xx, URI=/WebService/: No rule found. Using default pool from VIP: webservicepool
Can you give me another hint? Or does someone have an additional idea?
Thank you very much!
Simon - hoolio
Cirrostratus
Hi Simon,
If you remove the iRule and make a request, do you get a response back from the VIP?
Does the application use absolute references in the response data (as opposed to HTTP response headers) to the domain you want to proxy (ihstestweb.xxx.xx:1234)? If so, you'll want to add a stream profile to the iRule and set the global variable ::rewrite_response_payload to 1. You should also add a custom HTTP profile with response chunking set to Rechunk.
If the app uses local references in links, etc, in the response payload, you don't need to add a stream profile to the VIP and you should set ::rewrite_response_payload to 0.
If that's not the issue then can you use Fiddler for IE or HttpFox for FF and see if you get any response headers or content back from the VIP?
Aaron - Russell_E_Glaue
Nimbostratus
Can you just set up a pool, put "www.somesiteB.com:4444" in it, and then send the web user connection to that pool with an iRule?
Create a pool with the node: www.somesiteB.com:4444
Create a virtual server that responds on an IP that the domain "www.somesitea.com" will resolve to.
Add the loadBalancingiRule iRule to this virtual server.rule loadBalancingiRule { when HTTP_REQUEST { set http_host [string trim [getfield [HTTP::host] ":" 1]] set http_host [string tolower $http_host] if { $http_host equals "www.somesitea.com" } { pool somesiteB_pool return } else { HTTP::respond 404 content { Not Found Not Found } } } } - lmwf1_55268
Nimbostratus
Try this and see if it works.
when HTTP_REQUEST {
if {([string tolower [HTTP::host]] starts_with "www.somesiteA.com")}{
HTTP::header replace Host "www.somesiteB.com:4444"
}
} - delvinadm_21686
Nimbostratus
Hi rglaue,
thank you for your suggestion. But this won't work I think, because the Client would "see" the change... there is an reconnect happening, or am I wrong?
In the end, there will be one SSL connection to somesite.com with just one SSL-certificate (which signed somesite.com) and the iRule should get the application content from othersite.com. So the loadbalancer may not redirect to an other adresse, because the SSL-tunnel would be dropped. But thank you for your advise!Posted By rglaue on 02/18/2009 12:16 PM
Can you just set up a pool, put "www.somesiteB.com:4444" in it, and then send the web user connection to that pool with an iRule?
Create a pool with the node: www.somesiteB.com:4444
Create a virtual server that responds on an IP that the domain "www.somesitea.com" will resolve to.
Add the loadBalancingiRule iRule to this virtual server.rule loadBalancingiRule { when HTTP_REQUEST { set http_host [string trim [getfield [HTTP::host] ":" 1]] set http_host [string tolower $http_host] if { $http_host equals "www.somesitea.com" } { pool somesiteB_pool return } else { HTTP::respond 404 content { Not Found Not Found } } } } - delvinadm_21686
Nimbostratus
Hi lmwfl,
thank you for this example.
I've tried this and the result is exactly the same. It just displays an empty page (with empty htmlcode).
Can you modifiy this rule, so it can also manipulate the URI?
Now, I used it this way:
if {([string tolower [HTTP::host]] starts_with "webservice.xxx.xx/webservice/")}{
HTTP::header replace Host "ihstestweb.xxx.xx:1234/webservice/"
}
}Posted By lmwf1 on 02/18/2009 3:18 PM
Try this and see if it works.
when HTTP_REQUEST {
if {([string tolower [HTTP::host]] starts_with "www.somesiteA.com")}{
HTTP::header replace Host "www.somesiteB.com:4444"
}
} - hoolio
Cirrostratus
For details on the various HTTP:: commands you can check the iRule wiki page:
HTTP:: (Click here)
For a given URL of http://www.example.com:80/path/to/file.ext?param1=value1, you can use the following commands to get/set the values:
HTTP::host - get the host header value (www.example.com:80)
HTTP::header replace Host "newhost.example.com" - set a new host header value
HTTP::uri - get/set the URI (path plus query string: /path/to/file.ext?param1=value1)
HTTP::path - get/set the path (URI minus query string: /path/to/file.ext)
HTTP::query - get the query string (URI minus the path: param1=value1)
If you don't need the full functionality of the ProxyPass iRule, you can do something like this:when HTTP_REQUEST { Log a debug line on each request log local0. "[IP::client_addr]:[TCP::client_port]: New request to [HTTP::host][HTTP::uri]" Check if the host/path starts with the following string if {("[string tolower [HTTP::host]][HTTP::path]" starts_with "webservice.xxx.xx/webservice/")}{ Replace the host header HTTP::header replace Host "ihstestweb.xxx.xx:1234" Log a debug line on each Host rewrite log local0. "[IP::client_addr]:[TCP::client_port]: Rewrote Host header from [HTTP::host] to ihstestweb.xxx.xx:1234" } }
You may also need to rewrite redirects coming from the application if they contain the internal hostname. If so, you can add this event code:when HTTP_RESPONSE { Replace the internal hostname in the HTTP Location header value in redirects if {[HTTP::is_redirect]}{ log local0. "[IP::client_addr]:[TCP::client_port]: Rewriting redirect from [HTTP::header value Location] to\ [string map {ihstestweb.xxx.xx:1234 webservice.xxx.xx}] [HTTP::header value Location]]" HTTP::header value Location [string map {ihstestweb.xxx.xx:1234 webservice.xxx.xx}] [HTTP::header value Location]] } }
If you only want to replace the host in redirects if the location starts with webservice, you can replace the HTTP::is_redirect check with this:when HTTP_RESPONSE { Replace the internal hostname in the HTTP Location header value in redirects if {[HTTP::is_redirect] && [HTTP::header value "Location"] contains "ihstestweb.xxx.xx:1234/webservice"}{ log local0. "[IP::client_addr]:[TCP::client_port]: Rewriting redirect from [HTTP::header value Location] to\ [string map {ihstestweb.xxx.xx:1234 webservice.xxx.xx}] [HTTP::header value Location]]" HTTP::header value Location [string map {ihstestweb.xxx.xx:1234 webservice.xxx.xx}] [HTTP::header value Location]] } }
If you need to replace the internal hostname within the page content, you can add a stream profile and use the STREAM::expression and STREAM::enable commands to do this. Check the STREAM::expression wiki page (Click here) for details.
Aaron - Russell_E_Glaue
Nimbostratus
...But this won't work I think, because the Client would "see" the change... there is an reconnect happening, or am I wrong? ....
This is similar to how we do it.
The client does not see the change.
The client types in https://www.mysite.com
The BigIP answers with an SSL Certificate and SSL Connection
The iRule sees the Host header as "www.mysite.com"
The iRule issues the command "pool mysite.com_pool"
In the "mysite.com_pool" is a set of nodes:
server1.mysite.com:55011
server1.mysite.com:55012
server2.mysite.com:23543
server3.mysite.com:4002
the "pool" command causes the request to get forwarded to one of the 4 nodes in the mysite.com_pool
The chosen node receives the request, processes it, and sends it back to the BigIP.
The BigIP forwards the request back to the original user.
Also in this scenerio, the web server sees the request as coming from the original web user, and not from the BigIP. In other words, the Access logs show the web user's IP address for the request (not the BigIP IP address).
-RG - lmwf1_55268
Nimbostratus
Try this.
if { ([HTTP::host] equals "webservice.xxx.xx" ) and ([HTTP::uri] starts_with "/webservice") } {
HTTP::header replace Host "ihstestweb.xxx.xx:1234"
}
The uri is the same so why do you neeed to change it?
You can try this to see if it change the uri as well, but I am not sure if you need this step. Something to try tho. Not sure about the syntax but just give you some ideas.
if { ([HTTP::host] equals "webservice.xxx.xx" ) and ([HTTP::uri] starts_with "/webservice") } {
HTTP::header replace Host "ihstestweb.xxx.xx:1234"
HTTP::header replace uri "/webservice"
}
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects
