Python equivalent of wrapping POST payload in single quotes - python

This is more of a python question than Splunk but would be helpful if anyone had done this... specifically here, there's a discussion of sending multiple metrics in a single POST to the server. The example they provide is using curl and wrapping the entire payload in single quotes ('), e.g.
curl -k http://<IP address or host name or load balancer name>:8088/services/collector \
-H "Authorization: Splunk 98a1e071-bc35-410b-8642-78ce7d829083"
\
-d '{"time": 1505501013.000,"source":"disk","host":"host_99","fields":
{"region":"us-west-1","datacenter":"us-west- 1a","rack":"63","os":"Ubuntu16.10","arch":"x64","team":"LON","service":"6","service_version":"0","service_environment":"test","path":"/dev/sda1","fstype":"ext3","_value":999311222774,"metric_name":"total"}}
{"time": 1505511013.000,"source":"disk","host":"host_99","fields":
{"region":"us-west-1","datacenter":"us-west-1a","rack":"63","os":"Ubuntu16.10","arch":"x64","team":"LON","service":"6","service_version":"0","service_environment":"test","path":"/dev/sda1","fstype":"ext3","_value":1099511627776,"metric_name":"total"}}'
My question is how to do the same thing in python – i.e. you can't wrap multiple JSON objects in single quotes like in the curl command - that just makes the entire payload a string. Is there some other wrapper that can be used for this purpose?
So, this works:
payload = {"time": 1505501013.000,"source":"disk","host":"host_99","fields":
{"region":"us-west-1","datacenter":"us-west- 1a","rack":"63","os":"Ubuntu16.10","arch":"x64","team":"LON","service":"6","service_version":"0","service_environment":"test","path":"/dev/sda1","fstype":"ext3","_value":999311222774,"metric_name":"total"}}
But this does not:
payload = {"time": 1505501013.000,"source":"disk","host":"host_99","fields":
{"region":"us-west-1","datacenter":"us-west- 1a","rack":"63","os":"Ubuntu16.10","arch":"x64","team":"LON","service":"6","service_version":"0","service_environment":"test","path":"/dev/sda1","fstype":"ext3","_value":999311222774,"metric_name":"total"}}
{"time": 1505511013.000,"source":"disk","host":"host_99","fields":
{"region":"us-west-1","datacenter":"us-west-1a","rack":"63","os":"Ubuntu16.10","arch":"x64","team":"LON","service":"6","service_version":"0","service_environment":"test","path":"/dev/sda1","fstype":"ext3","_value":1099511627776,"metric_name":"total"}}
FYI, then the POST looks like:
resp = requests.post(splunkurl,json=payload,headers=headers)

Well, "multiple json objects" is not a valid json, until it's a list of objects.
Generally, python doesn't care (just like any other network tool), json is just data format, and you need a different one. So you need to construct text payload yourself, i.e. json.dumps(payload1) + json.dumps(payload2), and send it via your network client as "raw" data.
I highly doubt that mainstream http libraries provide such usecase out of the box.
Not sure on reason for downvotes, i.e. requests library (which is kinda standard de-facto for high-level networking) have smart processing for payloads:
requests.post(url, data={'v1': 1, 'v2': 2}) # will encode it as form data
requests.post(url, json={'v1': 1, 'v2': 2}) # will encode as json
requests.post(url, data="{'v1': 1}{'v2': 2}") # will send as-is
Json has nothing to do with http itself, it's just a way to serialize data. Most clients will eventually use urllib, which doesn't care at all, the only question is if library gives easy way to send data raw

Related

Sending requests - provide a dictionary or a string

I was to automate action using python requests, when encountered strange behavior.
I want to generate reports from a certain domain, to do so I have to send a POST request providing parameters in form of an XML. In devtools it looks like this:
xmlWe: <REPORTPARS><PROC_ID>11</PROC_ID>
..... and so on
when I send report data by python requests, it works perfectly whe provided a with dictionary:
data = dict(xmlWe = '<REPORTPARS><PROC_ID>11</PROC_ID>(...) '
r = s.post(URL_generate, data=data))
IMO, its kind of strange, dictionary is a type in python so why would this server handle or expect this type?
I was trying to send this XML as text or JSON, adding the corresponding header 'Content-type' but without success. The server will return 777 Java nullptr exception, which is the same as in case of sending any other nonsense datatype. So it looks like he was expecting some sort of dictionary.
My problem is, my company uses pl/sql for automation, so I will finally have to use this language. There, in http_utils data can be sent merely by write_text, so I'm restricted to sending string (can be dumped JSON).
What do You think, Is there an option for this server will accept report_pars as a string by any chance?
You need to send a xml directly:
import requests
headers = {'Content-Type': 'application/xml'}
r = requests.post(URL_generate, data=xmlWe, headers=headers)

python request with authentication access token

I am trying to get an API query into python. The command line
curl -X POST https://xxxx.com/api/auth/refreshToken -d access_token
it will give output in text string.access_tokenis a hexadecimal variable that remains constant throughout. I would like to make this call from python so that I can loop through different ids and analyze the output. Any ideas?
Many thanks.
You can use requests library https://2.python-requests.org/en/master/user/quickstart/#make-a-request
Maybe something like this :
response = requests.post('https://httpbin.org/post', data = {'key':'value'})
Then you can utilise the response and process it

django nested body request not being set

I'm trying to make a request to the box api using python and django. I'm getting a 400 Entity body should be a correctly nested resource attribute name\\/value pair error.
My requests looks like:
requests.options(headers.kwargs['url'], headers=headers.headers,
data={'parent': {'id': 'xxxx'}, 'name': 'name.pdf'})
When I inspect the 400 request.body it contains 'parent=id&name=name.pdf' which leads me to believe I'm not setting the body properly
A curl works with the body
-d '{"name": "name.pdf", "parent": {"id": "xxxxx"}}'
Explicitly encode the dictionary to prevent form-encoding. Otherwise, it will be form-encoded as the way similar to urllib.urlencode (or urllib.parse.urlencode in Python 3.x).
import json
...
requests.options(
headers.kwargs['url'], headers=headers.headers,
data=json.dumps({'parent': {'id': 'xxxx'}, 'name': 'name.pdf'}))
In other word, instead of passing a dictionary, pass a string.
According to More complicated POST requests - Request documentation:
...
There are many times that you want to send data that is not
form-encoded. If you pass in a string instead of a dict, that data
will be posted directly.

Print out the whole raw http request

how do I get the whole raw http request in the python framework bottle?
I need something like this:
GET\n
myurl.com\n
/\n
attribute=value
&att2=value2
I need this to sign my http api requests
As far as I can tell from the docs you can't get the data in raw format.
What you can do is reconstruct it using bottle.request.data and bottle.request.headers. That may be enough for your purposes.
If you just want to print the request you can do the following:
headers_string = ['{}: {}'.format(h, request.headers.get(h)) for h in request.headers.keys()]
print('URL={}, method={}\nheaders:\n{}'.format(request.url, request.method, '\n'.join(headers_string)))

The data format for post in urllib2.Request

What should data look like before data encoding in:
urllib2.Request(someurl,data) I tried [('name1','value1'),('name2','value2'),...]but not work.:(
EDIT:
I made a log in the program and recorded the value of urllib.urlencode(data):
content=%E5%8F%91%E5%B8%83%E4%BA%86%E4%B8%80%E4%B8%AA%E6%96%B0%E4%B8%BB%E9%A2%98%EF%BC%9A%3Ca+href%3D%27http%3A%2F%2Fbbs.jianshe99.com%2Fforum-5-195%2Ftopic-448618.html%27+target%3D%27_blank%27%3E+fsdfdsf%3C%2Fa%3E
then post it to a php script which is
<?php
print_r($_POST);
?>
but always get a response as:
array()
data may be a string specifying additional data to send to the server, or None if no such data is needed. Currently HTTP requests are the only ones that use data; the HTTP request will be a POST instead of a GET when the data parameter is provided. data should be a buffer in the standard application/x-www-form-urlencoded format. The urllib.urlencode() function takes a mapping or sequence of 2-tuples and returns a string in this format.
See Also
urllib2.Request

Categories