Learn F5 Technologies, Get Answers & Share Community Solutions Join DevCentral

Filter by:
  • Solution
  • Technology
Answers

Regex

I've been requested to perform a rewrite / redirect which does the following:

http://subdomain.ourcompany.com/webext/01.aspx?status=error (pass the 01 over to the url below and say id=thatNumber)

needs to rewrite to

http://subdomain.ourcompany.com/post/post.ashx?id=01&status=error

I'm trying to make sure I'm going in the right direction here by using regex to analyze the URI, however the 01.aspx will be a different number, it will not always come from the application that way.

The web application may spit out a different error number such as 45.aspx or 123.aspx. The web application increments this number based on the number of errors received within the application, so there's a possibility that we will get into triple, 4, 5, 6 digits in the future.

The only thing that changes in the uri is this number. The ?status=error needs to be appended and the number moved over to result in something like:

http://subdomain.ourcompany.com/post/post.ashx?id=01&status=error

I found this iRule - can I use this or something similar to increment using \d+ to say one or more digits within the regex?

Or a string match?

string match -nocase {[0-9999][[0-9999]} 

Thanks for any help - I'm unsure how to move forward.

elseif {[HTTP::host] == "subdomain.ourcompany.com" } { if { [HTTP::uri] contains "/webext/\d+.aspx?status=error"} {
set urivar
if { ! ( $urivar matches_regex ^.*?
\/webext\/\d+\[a-zA-Z0-9]) } {
rewrite here
}
else {
pool something else
}
}
2
Rate this Question

Answers to this Question

placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
OK, I've been able to string match somewhat using the following:
if { ([HTTP::host] eq "subdomain.ourcompany.com") and ([string match {/webext/[0-999]*} [HTTP::uri]]) } {

However, the following does not match for some reason:


if { ([HTTP::host] eq "subdomain.ourcompany.com") and ([string match {/webext/[0-999].aspx?status=error} [HTTP::uri]]) } {


strange?
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
The reason the match doesn't work is that the sections between the brackets represents a single character.  I'm not sure how the interpreter will deal with 999 in this case, but it's not the way you are thinking.

Let's step back a bit and rethink the problem.  Whenever I hear "regex" I cringe because it's such a costly operation.  In some cases, it's the only way to go, but for this case where you know the format of the inbound URI, it's fairly easy to use the TCL string functions to extract the value of ID.  Something like this should work for you

when HTTP_REQUEST {   # Lowercase the URI for string comparison purposes (.aspx implies case-insensitive URIs)   set uri [string tolower [HTTP::uri]]   # Only process URIs of the format /webext/xxxxx.aspx?status=error   if { ($uri starts_with "/webext/") && ($uri ends_with ".aspx?status=error") } {     # Set the start index to the first char after "/webext/" in the URI     set idxStart 8     # Set the end index to the dot in ".aspx".     set idxEnd [string first ".aspx" $uri]     if { -1 != $idxEnd } {       # decrement the end index to the last character in the id       incr idxEnd -1;             # extract the id from the uri from the uri       set id [string range $uri $idxStart $idxEnd]             # Issue the redirect       HTTP::redirect "http://[HTTP::host]/post/post.ashx?id=${id}&status=error"     }   } }


Granted, I made some assumptions here that you won't be handling URI's with both numbers/characters between the "/webext/" and ".aspx?status=error".  It should still work, but it will replace the value of the "id" variable with whatever is between those two strings.

Hope this helps...

-Joe
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
Wow - thank you Joe.

One other question - I've been told that these numbers will increment fairly quickly (the app is very buggy) and they've requested that I up the number quite a bit.

Let's say I want to use a number such as [0-99999999] - would I simply change your code to reflect that many characters?  
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
Nevermind - I took another look at your code and saw it does exactly what I needed!

Only change I had to make was to change this:

# Issue the redirect
HTTP::redirect "[HTTP::host]/post/post.ashx?id=${id}&status=error" /
to this (it was appending the host name twice in the beginning of the url)
# Issue the redirect
HTTP::redirect "/post/post.ashx?id=${id}&status=error"
Your help is greatly appreciated.
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
No change is necessary.  This will work for any length number.  Since I'm using the "string first" to get the index of the ".aspx" that will increase the larger the id is.

For this:

http://server/webext/123.aspx?status=error

idxStart would be where the "1" is and idxEnd would be where the "3" is.  The string range will then return "123"

For

http://server/webext/123456789.aspx?status=error

idxStart would be the "1" and idxEnd would be where the "9" is.  The string range will then return "123456789"

Keep in mind that this does no validation that what's in the URI in that section is actually a number.  For

http://server/webext/foo/bar/yahoo.aspx?status=error

The extracted ID would be "foo/bar/yahoo".  But I'm assuming that you know the format of the application.  You might want to thrown in a verification check in there.

-Joe


0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
Oops, left out the beginning "http://" from the redirect command. Your way should work though if you are redirecting to the same hostname.
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
Awesome - either way works. Tell me, how did you incorporate code tags to your post? every time I try using [code ] it doesn't display correctly, I've resorted to blockquote tags.

Using code tags only seems to work using quick reply.

Thanks again Joe
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
Another option would be to extract the web object and extension using URI::basename:

http://devcentral.f5.com/wiki/default.aspx/iRules/URI__basename.html

when HTTP_REQUEST {

# Check if URI starts with /webext and there is a query string parameter named status set to "error"
if {[string tolower [HTTP::uri]] starts_with "/webext" and [URI::query "?&[HTTP::query] &status] eq "error"}{

# Parse 000file.ext from /path/to/000file.ext and save the leading digits to the $id variable
# where 000 is one or more digits and file.ext is any string
scan [URI::basename [HTTP::uri]] {%[0-9]%s} id rest
if {$id ne ""}{
log local0. "Scanned $id from $uri"
HTTP::redirect "http://[HTTP::host]/post/post.ashx?id=${id}&status=error"
}
}
}


Aaron
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
Hey guys,

Turns out that rather than capturing ?status=error and passing it along, this needs to take whatever is after .aspx and append it, no matter what it is.

For example, they want the following examples to be able to work:

from:

http://server/webex/(.*).aspx?(.*)

to:

http://server/post/post.ashx?id=$1&$2

more examples:

http://server/webex/10.aspx?status=Good -> http://server/post/post.ashx?id=10&status=good

http://server/webex/10.aspx -> http://server/post/post.ashx?id=10

http://server/webex/234234.aspx?* -> http://server/post/post.ashx?id=234234&*

Does this iRule need to be completely re-worked all over again?

I was thinking of doing something like this:

HTTP::redirect "/post/post.ashx?id=${id}&[HTTP::query]"

rather than

HTTP::redirect "/post/post.ashx?id=${id}&status=error"

Thanks for any help, I'm trying to work on it on my own as well.
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
Can you try this? You might get a trailing & in the query string if there wasn't a query string already. But hopefully that won't break anything.

when HTTP_REQUEST {

   # Check if URI starts with /webex/
   if {[string tolower [HTTP::uri]] starts_with "/webex/"}{

      # Parse 000file.ext from /path/to/000file.ext and save the leading digits to the $id variable
      # where 000 is one or more digits and file.ext is any string
      scan [URI::basename [HTTP::uri]] {%[0-9]%s} id rest
      if {$id ne ""}{
         log local0. "Scanned $id from $uri"
         HTTP::redirect "http://[HTTP::host]/post/post.ashx?id=${id}&[HTTP::query]"
      }
   }
}


Aaron
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
This ended up working:

HTTP::redirect "/post/post.ashx?id=${id}&[HTTP::query]"

It does append the ampersand - any thoughts on how to remove that if its not needed?

http://server/webex/234234.aspx

Becomes this:

http://server/post/post.ashx?id=234234&*

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
You could add a check to see if the query string is null, but it's extra work with no benefit (unless the extra ampersand breaks the app).

when HTTP_REQUEST {

   # Check if URI starts with /webex/
   if {[string tolower [HTTP::uri]] starts_with "/webex/"}{

      # Parse 000file.ext from /path/to/000file.ext and save the leading digits to the $id variable
      # where 000 is one or more digits and file.ext is any string
      scan [URI::basename [HTTP::uri]] {%[0-9]%s} id rest
      if {$id ne ""}{
         log local0. "Scanned $id from $uri"
	 if {[HTTP::query] eq ""}{
            HTTP::redirect "http://[HTTP::host]/post/post.ashx?id=${id}"
         } else {
            HTTP::redirect "http://[HTTP::host]/post/post.ashx?id=${id}&[HTTP::query]"
         }
      }
   }
}


Aaron
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
Funny i just thought of that - Works perfectly. Thanks again to you all.
0