Forum Discussion

FSC-IT_27241's avatar
FSC-IT_27241
Icon for Nimbostratus rankNimbostratus
Oct 19, 2015

How to change a put into a post

Let me start by saying I am in over my head. But due to various reasons for a quick workaround my dev team has asked me if there is a way to turn a put command into a post command using an irule.

 

Example: There are a set of three URL's where if the method comes in as a put, they would like to change that into a post.

 

url's = /data/rest/abc/list/shared/* /data/rest/abc/list/tag/* /data/rest/abc/group/*

 

Sorry if this is too vague, but as I mentioned, in way over my head. Thanks!

 

2 Replies

  • You will have to do something like this similar to this post, https://devcentral.f5.com/questions/irule-to-change-http-get-into-post:

    when CLIENT_ACCEPTED {
        TCP::collect
    }
    when CLIENT_DATA {
         separate uri and query string
        set uri [findstr [TCP::payload] "PUT " 4 " HTTP/1."]
        switch -glob $uri {
            "/data/rest/abc/list/shared/*" -
            "/data/rest/abc/list/tag/*" -
            "/data/rest/abc/group/*" {
                set uri_no_query [findstr $uri "" 0 "?"]
                set query [findstr $uri "?" 1]
    
                 replace TCP payload
                regsub -all -nocase "PUT" [TCP::payload] "POST" newdata
                set newdata1 [string map "$uri $uri_no_query" $newdata]
                regsub -all -nocase "Accept: " $newdata1 "Content-Type: application/x-www-form-urlencoded\r\nContent-Length: [string length $query]\r\nAccept: " newdata2
                TCP::payload replace 0 [TCP::payload length] ${newdata2}$query
            }
        }
        TCP::release
    }
    
  • There is greater ambiguity when transforming POST to PUT than that which is described in the cited article. In the case of that article, the transform is for two methods of submitting html form variables. In the GET case, form variables are part of the request-uri, while in the POST case, they are embedded in the message body. Form variables are not submitted using the PUT method. It may be used to upload resources.

    Alternatively, the methods in this case may be used as part of a so-called RESTful interface. Generally, since PUT is idempotent, it is used to create or replace a representation, and since POST is not idempotent, it has no specific interpretation, but is often used to amend a part of a representation.

    I assume that the original request requires only the transform of the method, but does not require alteration of the request headers or the message body. Unhappily, you cannot use

    HTTP::method
    to change the HTTP method, so you do in fact have to use
    TCP::collect
    (as in the article). You can combine this with a data-group, which allows you to alter the match list without reloading the iRule. Create the data-group as follows:

    tmsh create ltm data-group internal dg-post-transform-uris \
      type string \
      records add { \
        "/data/rest/abc/list/shared/" {} \
        "/data/rest/abc/list/tag/" {} \
        "/data/rest/abc/group/" {} \
      }
    
    when CLIENT_ACCEPTED {
        TCP::collect
    }
        
    when CLIENT_DATA {
        if { [TCP::payload] starts_with "POST " } {
            if { [class match [substr [TCP::payload] 5 " "] starts_with dg-post-transform-uris] } {
                TCP::payload replace 0 4 "PUT"
            }
        }
    }