Forum Discussion

steve_111974's avatar
steve_111974
Icon for Nimbostratus rankNimbostratus
Jul 24, 2008

rewrite a character with HTTP POST data

Hi,

 

 

Our application is having a problem recognizing the "&" within a POST sent by the client.

 

 

How do I write an irule which parses the POST data that contains the "&" sign and rewrite it to something else like "and", then pass it to the application server. I might need help on rewriting the "and" back to "&" for the response back to the client.

 

 

Here's a sample of the data being sent by a client:

 

 

POST /app/DentegraPortal/TransEDI HTTP/1.1

 

Content-Length: 514

 

Content-Type: text/plain; charset=UTF-8

 

Host: 192.168.130.129:8080

 

Connection: Keep-Alive

 

User-Agent: Jakarta-HttpComponents/1.1

 

 

 

ISA*00* *00* *ZZ*DDPA *ZZ*NY *080724*1127*U*00401*000000001*0*P*:~GS*HS*DDPA*NY*20080724*1127*1*X*004010X092~ST*270*0001~BHT*0022*13*DDPA-deprod2-1216916839069-0*20080724*1127~HL*1**20*1~NM1*PR*2*DELTA DENTAL NY*****PI*NY~HL*2*1*21*1~NM1*1P*2*MONTERUBIO & HERBOSA ORAL M*****FI*431554961~HL*3*2*22*0~NM1*IL*1*CONWAY*NATSUKO****MI*489846656~DMG*D8*19560225~EQ*30~SE*11*0001~GE*1*1~IEA*1*000000001~

 

 

Please help!

5 Replies

  • Colin_Walker_12's avatar
    Colin_Walker_12
    Historic F5 Account
    All you would need is an iRule that does inspection of the client data once a post is sent, and content replacement. You could use a string mapping or a regular expression, based on your needs. Have you searched the forums yet? There should be a few good examples either here or in the CodeShare.

     

     

    Colin
  • A stream profile and rule to enable it should work nicely to rewrite the post data in requests. You'll want to try to be very specific on when you rewrite the & as this is typically used as a delimiter for post data parameters. You might want to use something like this:

      
      when HTTP_REQUEST {    
        
          Disable the stream filter by default    
         STREAM::disable    
        
          Check if the request is a POST, with a content type of text, from the Jakarta user agent  
         if {[HTTP::method eq "POST" && [HTTP::header value Content-Type] contains "text" \  
            && [HTTP::header value "User-Agent"] contains "Jakarta-HttpComponents"}{  
        
             Match the literal string "&" and replace it with and  
            STREAM::expression {@&@and@}   
        
             Enable the stream filter for this request only    
            STREAM::enable    
         }    
      }     
      when STREAM_MATCHED {  
          This event is only included for debugging.  You should remove the event after testing is complete.  
         log local0. "[IP::client_addr]:[TCP::local_port]: matched: [STREAM::match]"    
      }   
      

    You could use a similar approach for rewriting the and back to & if it does appear in responses. Again, you'd want to try to be very specific about when you're rewriting the content as 'and' is a very common string.

    Aaron
  • Actually, I would guess your app expects the & to be URL encoded if it shouldn't be interpreted as an &. I think you could replace the stream expression line in the example above, with:

     

     

    STREAM::expression {@&@%26@}

     

     

    I don't think you'd need to do any rewriting on responses if the application is standards compliant.

     

     

    Aaron
  • Colin, I've checked the codeshare section and it suggested to use the http:collect and http:payload parameters. I tried building one from scratch but kept getting errors on the irule.

     

     

    Aaron, all the requests are POST so I commented the" if" statement out. So for the expression, I should use

     

    STREAM::expression {@&@%26@}

     

    instead of

     

    STREAM::expression {@&@and@}

     

     

    I'm not sure what you mean by "URL encoded".

     

     

    Also, when I look at the raw data, i see a "&" but I when export it and view in html, it shows just "&". Which one should I filter for?

     

     

    thanks so much for the quick response!

     

     

    Steve
  • Here is some info on URL (or percent) encoding:

    http://en.wikipedia.org/wiki/Percent-encoding

    Percent-encoding reserved characters

    When a character from the reserved set (a "reserved character") has special meaning (a "reserved purpose") in a certain context, and a URI scheme says that it is necessary to use that character for some other purpose, then the character must be percent-encoded. Percent-encoding a reserved character involves converting the character to its corresponding value in ASCII and then representing that value as a pair of hexadecimal digits. The digits, preceded by a percent sign ("%"), are then used in the URI in place of the reserved character.

    The reserved character "/", for example, if used in the "path" component of a URI, has the special meaning of being a delimiter between path segments. If, according to a given URI scheme, "/" needs to be in a path segment, then the three characters "%2F" or "%2f" must be used in the segment instead of a raw "/".

    This blog entry (Click here) suggests you may need to XML encode the element value and then URL encode it. So the XML encoded equivalent for & is & amp ; (without the spaces). & amp ; (without the spaces) URL encoded would be %26amp;.

    If you're able to test this, try the following rule which replaces & with %26amp;

        
          when HTTP_REQUEST {        
                
              Disable the stream filter by default        
             STREAM::disable        
                
              Check if the request is a POST, with a content type of text, from the Jakarta user agent      
             if {[HTTP::header value Content-Type] contains "text" \      
                && [HTTP::header value "User-Agent"] contains "Jakarta-HttpComponents"}{      
            
                 Match the literal string "&" and replace it with %26amp;    
                STREAM::expression {@&@%26amp;@}    
            
                 Enable the stream filter for this request only        
                STREAM::enable        
             }        
          }         
          when STREAM_MATCHED {      
              This event is only included for debugging.  You should remove the event after testing is complete.      
             log local0. "[IP::client_addr]:[TCP::local_port]: matched: [STREAM::match]"        
          }    
        

    If that doesn't work, try replacing the STREAM::expression line with this:

    STREAM::expression {@&@%26@}

    Aaron