Forum Discussion
DaveC_21078
Altostratus
Aug 27, 2009How can I chab=nge the format of a URL?
I need to be able to search for a URL similar to
http://example.com/adserver/impression/pid=123/oid=860/rand=12345/?click=http://www.publisher.com/track/ad.aspx?click=1&test=2&imp=1
and manipulte it to look like
http://example.com/ad.imp?pid=123&oid=860&rand=12345/?pclk=http://www.publisher.com/track/ad.aspx?click=1&test=2&imp=1
before passing it on. Can I do this with an iRule?
Thanks for looking.
19 Replies
- hoolio
Cirrostratus
Hi,
You can rewrite the URI using HTTP::uri or HTTP::path. You can retrieve the URI and path with these commands as well. You can use HTTP::query to get the query string value. You can use URI::query [HTTP::uri] param_name to get the value of a specific parameter in the query string.
Here is an untested example which should give you some ideas on how to do this. I made some assumptions about when you would want to rewrite the URI and which fields you would want to take from the original URI.when HTTP_REQUEST { log local0. "[IP::client_addr]:[TCP::client_port]: New HTTP request to [HTTP::uri]" Check the requested path? if {[HTTP::path] eq "/adserver/impression/pid=123/oid=860/rand=12345/"}{ Rewrite the URI to /ad.imp? then take the third through fifth fiels in the path and append the query string parameter pclk with the value of click from the original query string HTTP::uri "/ad.imp?[URI::path [HTTP::uri] 3 5]?pclk=[URI::query [HTTP::uri] click]" log local0. "[IP::client_addr]:[TCP::client_port]: Rewrote URI to: /ad.imp?[URI::path [HTTP::uri] 3 5]?pclk=[URI::query [HTTP::uri] click]" } } when HTTP_REQUEST priority 501 { This event is just used for debug logging of the values that are cached in the default priority 500 HTTP_REQUEST event above You can comment out or remove this event when you're done testing log local0. "[IP::client_addr]:[TCP::client_port]: Actual updated URI: [HTTP::uri]" }
Aaron - The_Bhattman
Nimbostratus
How about this?when HTTP_REQUEST { HTTP::uri [string map {"adserver/impression/pid=123/oid=860/rand=12345/?clic" "ad.imp?pid=123&oid=860&rand=12345/?pcl"} [HTTP::uri]] }
CB - DaveC_21078
Altostratus
Thanks, but the pid, oid and rand are variables. Is there a way to do it w/o knowing what those values are ahead of time? - The_Bhattman
Nimbostratus
Okay how about thiswhen HTTP_REQUEST { set uri [HTTP::uri] scan $uri "adserver/impression/pid=%d/oid=%d/rand=%d" pidnum oidnum randnum log local0. "This is the URI = $uri" log local0. "Pid = $pidnum, Oid = $oidnum, rand = $randnum" HTTP::uri [string map {"adserver/impression/pid=$pidnum/oid=$oidnum/rand=$randnum/?clic" "ad.imp?pid=$pidnum&oid=$oidnum&rand=$randnum/?pcl"} [HTTP::uri]] }
I have never done the string map with variables so I hope it works.
CB - DaveC_21078
Altostratus
Thanks for your help. Below is what I have, but it’s not quite working. If I implement the iRule, the page returns an error, which I expect because the web server doesn’t know what to with the new URL format yet, but the IIS logs don’t show the request making it that far. Do I have a syntax mistake somewhere?
when HTTP_REQUEST {
if { [HTTP::uri] contains "adserver/impression" }{
set uri [HTTP::uri]
scan $uri "adserver/impression/pid=%d/oid=%d/rand=%d" pidnum oidnum randnum
log local0. "This is the URI = $uri"
log local0. "Pid = $pidnum, Oid = $oidnumm, rand = $randnum"
HTTP::uri [string map {"adserver/impression/pid=$pidnum/oid=$oidnum/rand=$randnum/?click" "ad.imp?pid=$pidnum&oid=$oidnum&rand=$randnum/?pclk"} [HTTP::uri]]
}} - Yeah, that one burned me a long time ago and forgot about it. the "string map" command performs a literal replacement (ie. it doesn't do variable substitution). So in your example it was looking for the literal string "adserver/impression/pid=$pidnum/oid=$oidnum/rand=$randnum/?click" instead of the correct "adserver/impression/pid=123/oid=860/rand=12345/?click" Same goes for the replacement string.
Also, your second log statement as a typo with the $oidnumm variable which may throw an error.
The good news about the variable substitution is that you can fix that by wrapping the map strings with a "subst" command. This should work for you:when HTTP_REQUEST { if { [HTTP::uri] contains "adserver/impression" }{ set found [scan [HTTP::uri] "/adserver/impression/pid=%d/oid=%d/rand=%d" pidnum oidnum randnum] if { $found == 3 } { log local0. "This is the URI = [HTTP::uri]" log local0. "Pid = $pidnum, Oid = $oidnum, rand = $randnum" set newuri [string map [subst {"adserver/impression/pid=$pidnum/oid=$oidnum/rand=$randnum/?click" "ad.imp?pid=$pidnum&oid=$oidnum&rand=$randnum/?pclk"}] [HTTP::uri]] log local0. "New URI: $newuri"; HTTP::uri $newuri; } } }
I threw in a sanity check for the scan to verify that it did indeed find the three values and I also put in the newly mapped URI into a variable and logged it so you can verify in the BIG-IP logs whether the "string map" worked. Oh, and I removed the $uri variable for optimization. You can remove the $newuri variable after you've tested and it works.
A fully optimized iRule would be this:when HTTP_REQUEST { if { [HTTP::uri] contains "adserver/impression" }{ set found [scan [HTTP::uri] "/adserver/impression/pid=%d/oid=%d/rand=%d" pidnum oidnum randnum] if { $found == 3 } { log local0. "This is the URI = [HTTP::uri]" log local0. "Pid = $pidnum, Oid = $oidnum, rand = $randnum" HTTP::uri [string map [subst {"adserver/impression/pid=$pidnum/oid=$oidnum/rand=$randnum/?click" "ad.imp?pid=$pidnum&oid=$oidnum&rand=$randnum/?pclk"}] [HTTP::uri]] } } }
Hope this helps!
-Joe - hoolio
Cirrostratus
If you replace the curly braces with double quotes, the variables can be expanded in string map:
% set find abc
abc
% set replace def
def
% string map {$find $replace} abcdefg
abcdefg
% string map "$find $replace" abcdefg
defdefg
Aaron - DaveC_21078
Altostratus
This looks right, but it is still passing the original URI. I'm stumped.
when HTTP_REQUEST {
if { [HTTP::uri] contains "adserver/impression" }{
set found [scan [HTTP::uri] "/adserver/impression/pid=%d/oid=%d/rand=%d" pidnum oidnum randnum]
if { $found == 3 } {
log local0. "This is the URI = [HTTP::uri]"
log local0. "Pid = $pidnum, Oid = $oidnum, rand = $randnum"
set newuri [string map [subst {"adserver/impression/pid=$pidnum/oid=$oidnum/rand=$randnum/?click" "ad.imp?pid=$pidnum&oid=$oidnum&rand=$randnum/?pclk"}] [HTTP::uri]]
log local0. "New URI: $newuri";
HTTP::uri $newuri;
}
}
} - JRahm
Admin
THe URI is cached for the duration of the event, so if you move your log statement to a new HTTP_REQUEST event with a higher priority value you should see the correct value:when HTTP_REQUEST priority 501 { log local0. "New URI: [HTTP::uri]" }
Oh, and remove those semi-colons. - JRahm
Admin
updated above post...Monday brain fog.
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
