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

Was this article helpful?

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..