Forum Discussion

Patrik_Jonsson's avatar
Nov 08, 2013

Cache based on SOAP XML Envelope content

Hi guys!

 

We got a tricky question from our developers. They have a service which gets a bit too much traffic and would like to cache the responses for around 10 seconds based on the content in the envelope tag of a SOAP request. I have an idea but I'd like to check with you guys first before starting to look into it properly.

 

So here's the sample SOAP request (could not paste it here so I needed to use tny): http://tny.cz/bbfdf261

 

My idea is to parse the SOAP request and create an URI out of the envelope content and cache the request based on the URI: https://subdomain.domain.com/PartnerService/PartnerServices.svc?FetchLiveMarkets=1&siteid=1&numberofmarkets=10&timezonename&gmtstandardtime&partnerref=1

 

Looking into either using HTTP::payload or the XML commands (not sure if I can trust them in production though as it requires an EA license. The alternative is to throttle the incoming requests and limit them to 1 per second but I prefer not to go down that route if the caching works.

 

Perhaps there's a better way? Grateful for any ideas, suggestions or even warnings. :)

 

Kind regards, Patrik

 

  • A few thoughts:

     

    1. The EA license and corresponding XML parsing functions no longer exists. The XML_CONTENT_BASED_ROUTING event is the only thing left from that, only works on request traffic, and is limited on the number of values it can return from the XPath query. Depending on your content, you may need to do this with string parsing.

       

    2. Is it the request or response payload that you need to capture and cache?

       

  • A developer of ours came up with a brilliant idea, which I'm trying to implement now. What if we make an md5 out of the content and cache using that?

    I wrote the iRule below but despite the devcentral page saying that the CACHE method can be used in the HTTP_REQUEST_DATA it seems like that's not the case.

    Thankful for any input!

    when HTTP_REQUEST {
      if {[HTTP::method] eq "POST"}{
         Trigger collection for up to 1MB of data
        if {[HTTP::header "Content-Length"] ne "" && [HTTP::header "Content-Length"] <= 524288}{
          set content_length [HTTP::header "Content-Length"]
        } else {
            set content_length 524288
        }
         Check if $content_length is not set to 0
        if { $content_length > 0} {
          HTTP::collect $content_length
        }
    
      }
    }
    when HTTP_REQUEST_DATA {
        Collect the data needed
        set payload [HTTP::payload]
    
        Make the md5sum
        set md5 [md5 payload]
    
        Store the uri for later use (the service might not be able to accept a uri)
        set uri [HTTP::uri]
    
        Set the uri to current uri+md5
        HTTP::uri "$uri?$md5"
    
        Cache the uri to current uri+md5
        CACHE::uri "$uri?$md5"
    
    }
    when HTTP_RESPONSE {
        For troubleshooting
        HTTP::header replace X-Via "F5 BigIP (DMZ)"
    }
    when CACHE_RESPONSE {
        For troubleshooting
        CACHE::header insert X-CacheStatus "Hit"
        CACHE::header insert X-CacheAge [CACHE::age]
    }
    
  • An update to this thread. Apparently you should be able to use the cache method in HTTP_REQUEST_DATA and it's a bug. Still waiting for a HF.