For more information regarding the security incident at F5, the actions we are taking to address it, and our ongoing efforts to protect our customers, click here.

Convert curl command to BIG-IP Monitor Send String

Problem this snippet solves:

Convert curl commands into a HTTP or HTTPS monitor Send String.

How to use this snippet:

Save this code into a Python script and run as a replacement for curl.

Related Article: How to create custom HTTP monitors with Postman, curl, and Python

An example would be:

% python curl_to_send_string.py -X POST -H "Host: api.example.com" -H "User-Agent: Custom BIG-IP Monitor" -H "Accept-Encoding: identity" -H "Connection: Close" -H "Content-Type: application/json" -d '{
  "hello":
      "world"
}
' "http://10.1.10.135:8080/post?show_env=1"
SEND STRING:
POST /post?show_env=1 HTTP/1.1\r\nHost: api.example.com\r\nUser-Agent: Custom BIG-IP Monitor\r\nAccept-Encoding: identity\r\nConnection: Close\r\nContent-Type: application/json\r\n\r\n{\n  \"hello\":\n      \"world\"\n}\n

Code :

Python 2.x

import getopt
import sys
import urllib

optlist, args = getopt.getopt(sys.argv[1:], 'X:H:d:')
flat_optlist = dict(optlist)

method = flat_optlist.get('-X','GET')

(host,uri) = urllib.splithost(urllib.splittype(args[0])[1])
protocol = 'HTTP/1.1'

headers = ["%s %s %s" %(method, uri, protocol)]
headers.extend([h[1] for h in optlist if h[0] == '-H'])
if not filter(lambda x: 'host:' in x.lower(),headers):
    headers.insert(1,'Host: %s' %(host))


send_string =  "\\r\\n".join(headers)
send_string += "\\r\\n\\r\\n"

if '-d' in flat_optlist:
    send_string += flat_optlist['-d'].replace('\n','\\n')
send_string = send_string.replace("\"", "\\\"")
print "SEND STRING:"
print send_string

Python 3.x

import getopt
import sys

from urllib.parse import splittype, urlparse

optlist, args = getopt.getopt(sys.argv[1:], 'X:H:d:')
flat_optlist = dict(optlist)

method = flat_optlist.get('-X','GET')

parts = urlparse(splittype(args[0])[1])
(host,uri) = (parts.hostname,parts.path)
protocol = 'HTTP/1.1'

headers = ["%s %s %s" %(method, uri, protocol)]
headers.extend([h[1] for h in optlist if h[0] == '-H'])
if not filter(lambda x: 'host:' in x.lower(),headers):
    headers.insert(1,'Host: %s' %(host))


send_string =  "\\r\\n".join(headers)
send_string += "\\r\\n\\r\\n"

if '-d' in flat_optlist:
    send_string += flat_optlist['-d'].replace('\n','\\n')
send_string = send_string.replace("\"", "\\\"")
print("SEND STRING:")
print(send_string)

Tested this on version:

11.5

Updated Jun 06, 2023
Version 3.0

17 Comments

  • response size is 39Kb.

     

    This is the actual request from the logs and i am getting HTTP 400 but curl works just fine:

     

    send=POST /globalSearch/basicSearch HTTP/1.1\x0d\x0acontent-type: application/json\x0d\x0ahost: host.domain.com\x0d\x0aContent-Length: 120\x0d\x0a\x0d\x0a{\x0a"queryParam":"cleaning",\x0a"start":"0",\x0a "rows":"20",\x0a"searchType":[\x0a"ALL"\x0a],\x0a"facetSelection":[\x0a"SC:catalogs"\x0a ],\x0a"userRoles":[""\x0a ]\x0a}\x0a

     

  • My response string appears in the 1st line of the response which is within 5,120 bytes so i doubt this is the problem

     

  • What version are you running, here's what I get from my monitor log. Running TMOS 13.1.0.5

    [0][6132] 2018-05-04 01:07:41.595594: ID 46    :(_send_active_service_ping): writing [ tmm?=false td=true tr=false addr=::ffff:192.168.1.187:80 srcaddr=::ffff:192.168.1.250%0:56436 ] send=POST /test.json HTTP/1.1\x0d\x0acontent-type: application/json\x0d\x0ahost: host.domain.com\x0d\x0a\x0d\x0a{\\xe2\x80\x9cqueryParam\\xe2\x80\x9c:\\xe2\x80\x9ccleaning\\xe2\x80\x9c,\\xe2\x80\x9cstart\\xe2\x80\x9c:\\xe2\x80\x9c0\\xe2\x80\x9c,\\xe2\x80\x9crows\\xe2\x80\x9c:\\xe2\x80\x9c20\\xe2\x80\x9c,\\xe2\x80\x9csearchType\\xe2\x80\x9c:[\\xe2\x80\x9cALL\\xe2\x80\x9c],\\xe2\x80\x9cfacetSelection\\xe2\x80\x9c:[\\xe2\x80\x9cSC:catalogs\\xe2\x80\x9c],\\xe2\x80\x9cuserRoles\\xe2\x80\x9c:[\\xe2\x80\x9c\\xe2\x80\x9d]}

    Are you using the GUI to create the monitor or using iControl REST?

  • Hello,

     

    In this example, you are trying to send the monitoring traffic in http but in port tcp/8080 right ? But where are you mentioning that. I want to perform the same type of GET request but in a different port. Where should I mention that for a monitor.

  • By default a monitor will use the IP:PORT that is configured for the pool member. If you need to target a specific different port than what the service is using than you can specify a "Alias Service Port" as part of the monitor.

  • Yes Eric, I just found out that couple of minutes back. But thanks for the information..