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
- scyonix_360392Nimbostratus
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
- Eric_ChenEmployee
I think you’re hitting this limit (5kb response): https://support.f5.com/csp/article/K3451
You could try adding a range header or modify your query to get less data back.
- scyonix_360392Nimbostratus
My response string appears in the 1st line of the response which is within 5,120 bytes so i doubt this is the problem
- Eric_ChenEmployee
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?
- Accenture_LoreaNimbostratus
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.
- Eric_ChenEmployee
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.
- Accenture_LoreaNimbostratus
Yes Eric, I just found out that couple of minutes back. But thanks for the information..