Forum Discussion

Juan_Carlos_Rom's avatar
Juan_Carlos_Rom
Icon for Altostratus rankAltostratus
Jul 18, 2022

irule replace and modify uri and response

Hello everyone,

I have a problem with the irule that I've develop to the response from the server.

To put them in context the user access to the app with three different uri:

1. https://example.com/ris1

2.https://example.com/ris2

3.https://example.com/ris3

There are three different pools with two pool members for each.

When the servers receives the resquests is more like:

first sever http://example.com/Novaris with the same name for the path.

My irule is like this:

when HTTP_REQUEST {

STREAM::disable
# Check the requested path (set to lowercase)
# -glob: allow string pattern matching
switch -glob -- [string tolower [HTTP::uri]] {
"/ris1" {
log local0. "Matched pool 1 paths for [HTTP::uri]"
set uri [ string map -nocase { "/ris1" "/Novaris"} [HTTP::uri] ]
HTTP::uri $uri
HTTP::header remove "Accept-Encoding"
pool P1
}
"/ris2" {
log local0. "Matched pool 1 paths for [HTTP::uri]"
set uri [ string map -nocase { "/ris2" "/Novaris"} [HTTP::uri] ]
HTTP::uri $uri
HTTP::header remove "Accept-Encoding"
pool P2
}
"/ris3" {
log local0. "Matched pool 1 paths for [HTTP::uri]"
set uri [ string map -nocase { "/ris3" "/Novaris"} [HTTP::uri] ]
HTTP::uri $uri
HTTP::header remove "Accept-Encoding"
pool P3
}
default {
log local0. "Hit default for [HTTP::uri]"
HTTP::header remove "Accept-Encoding"
persist cookie insert "Redimed"
pool Pool_demobank
}
}
}

when HTTP_RESPONSE {
STREAM::disable
if {([HTTP::status] == 200) && ([HTTP::header value Content-Type] contains "text") } {
STREAM::expression { @http@https@ @/Novaris@/ris1@ @/Novaris@/ris2@ @/Novaris@/ris3@ }
STREAM::enable
}
}

My problem is in the response.

When the server response because the payload don't show the image so I fix with the stream:expression but with the other two not. Because the path have the same name there is another way to map this problem o I need to explain to the development team to modify the name of the path with each pool.

Thank you if anyone can help me.

  • If I understand you correctly, you need to alter the stream expression in your HTTP_RESPONSE event, based either on the pool that was selected or the URI you received, during the HTTP_REQUEST event. 

    Note that you may need to capture that in a variable in the HTTP_REQUEST event, and check the variable in the HTTP_RESPONSE event, because you might only be able to use certain API functions inside certain events.

    Something like:

    when HTTP_REQUEST {
    set orig_uri [HTTP::uri]
    # the rest of your logic
    }
    when HTTP_RESPONSE {
    STREAM::disable
    if {([HTTP::status] == 200) && ([HTTP::header value Content-Type] contains "text") } {
    switch -glob -- [string tolower $orig_uri] {
    "/ris1*" {
    STREAM::expression {@http:@https:@ @/[Nn]ovaris@/ris1@}
    }
    "/ris2*" {
    STREAM::expression {@http:@https:@ @/[Nn]ovaris@/ris2@}
    }
    "/ris3*" {
    STREAM::expression {@http:@https:@ @/[Nn]ovaris@/ris3@}
    }
    }
     STREAM::enable
    }
    }

    (There are other optimisations that might shorten this, but you should get the gist)

    Note that I have also changed the expression for your http/https rewrite to http:/https: (note the colon), so that any https:// URI returned by the downstream server is not rewritten to httpss://.

    You may also need to handle a case-sensitive response back from the downstream server (I presume you would need to rewrite /Novaris or /novaris for instance).  To that end, you may need to make your stream search expression something like...

    @/[Nn][Oo][Vv][Aa][Rr][Ii][Ss]@/ris1@

    ...so it handles upper- and lower-case.

  • Hi,

    If the stream expression string starts or ends with space, it won't work.
    It looks neater with space, but it shouldn't. 🙂

    # This will work
    STREAM::expression {@IE@Apache@ @Windows@Linux@}
    
    # and this will work
    STREAM::expression [list "@IE@Apache" "@Windows@Linux@"]
    
    # but this will NOT work-- notice the space between the '{' and the '@'
    STREAM::expression { @IE@Apache@ @Windows@Linux@ }

    REF: https://clouddocs.f5.com/api/irules/STREAM__expression.html

  • If I understand you correctly, you need to alter the stream expression in your HTTP_RESPONSE event, based either on the pool that was selected or the URI you received, during the HTTP_REQUEST event. 

    Note that you may need to capture that in a variable in the HTTP_REQUEST event, and check the variable in the HTTP_RESPONSE event, because you might only be able to use certain API functions inside certain events.

    Something like:

    when HTTP_REQUEST {
    set orig_uri [HTTP::uri]
    # the rest of your logic
    }
    when HTTP_RESPONSE {
    STREAM::disable
    if {([HTTP::status] == 200) && ([HTTP::header value Content-Type] contains "text") } {
    switch -glob -- [string tolower $orig_uri] {
    "/ris1*" {
    STREAM::expression {@http:@https:@ @/[Nn]ovaris@/ris1@}
    }
    "/ris2*" {
    STREAM::expression {@http:@https:@ @/[Nn]ovaris@/ris2@}
    }
    "/ris3*" {
    STREAM::expression {@http:@https:@ @/[Nn]ovaris@/ris3@}
    }
    }
     STREAM::enable
    }
    }

    (There are other optimisations that might shorten this, but you should get the gist)

    Note that I have also changed the expression for your http/https rewrite to http:/https: (note the colon), so that any https:// URI returned by the downstream server is not rewritten to httpss://.

    You may also need to handle a case-sensitive response back from the downstream server (I presume you would need to rewrite /Novaris or /novaris for instance).  To that end, you may need to make your stream search expression something like...

    @/[Nn][Oo][Vv][Aa][Rr][Ii][Ss]@/ris1@

    ...so it handles upper- and lower-case.

  • Hi,

    If the stream expression string starts or ends with space, it won't work.
    It looks neater with space, but it shouldn't. 🙂

    # This will work
    STREAM::expression {@IE@Apache@ @Windows@Linux@}
    
    # and this will work
    STREAM::expression [list "@IE@Apache" "@Windows@Linux@"]
    
    # but this will NOT work-- notice the space between the '{' and the '@'
    STREAM::expression { @IE@Apache@ @Windows@Linux@ }

    REF: https://clouddocs.f5.com/api/irules/STREAM__expression.html

    • candc's avatar
      candc
      Icon for Cirrus rankCirrus

      Great point -- I have updated my example above.

      I do love TCL but, coming form other languages, their decision to use braces as a string-literal delimeter always catches me out!

  • Hi Juan_Carlos_Rom , are you using a OneConnect profile (to be assigned in the virtual server acceleration settings)?

    As you are trying to "demultiplex" requests coming in through a clientside KeepAlive connection, it will be necessary to use OneConnect. Otherwise the incoming connection will be balanced to a pool according to your iRule logic and just stick there. With OneConnect enabled each incoming request will be handled individually.

    I recommend to use a new OneConnect profile with a host mask of 32 bits (IPv4) or 128 bits (IPv6).

    • Juan_Carlos_Rom's avatar
      Juan_Carlos_Rom
      Icon for Altostratus rankAltostratus

      Hi Stephan,

      In this momento in the virtual server, I don't apply any acceleration settings.

      Tomorrow, I'm going to test again with the profile oneConnect with the mask of 32 bits for ipv4.

      Then, I will replay the outcome.

      And thank you,  for your suggestion.