Not getting complete API details in Python like Postman - python

I am just trying to access an API through Postman and its wokring fine.The Postman header response is returning some details like below
Authentication-Token →/DwG7gAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Connection →keep-alive
Content-Length →16
Content-Type →application/json;charset=UTF-8
Date →Tue, 25 Sep 2018 17:44:01 GMT
Server →Apache-Coyote/1.1
But when I am trying to do same in Python I am just receivig the response status.(200)
How can I get the above Authentication-Token etc details like Postman in python code.
import requests
import json
url = 'https://test-orchestrator.lmig.com/baocdp/rest/login/'
headers = {"Content-Type": "application/json"}
data1 = {"username":"abc", "password":"abc"}
print("Testing authentication for Remedy test environment...")
change_response=requests.post(url,data=json.dumps(data1),headers=headers)
print(change_response)

If you print change_response, it will most likely look like this <status [200]> or something to that effect. If you want to see the contents of the response, you can use the vars response.text, response.content, or response.headers (among others) or since this is a json response, you can use the method response.json() to convert the contents of the response into a dictionary full of native Python data types.
I would reccommend x = response.json(), as the contents of your response seem to contain an auth token that you will most likely need to communicate with this device further. You can then use auth+token = x[token_key] to isolate that token.

Related

OctoPrint API, error 400 when making a POST request

I'm working with Octoprint's API. I'm struggling trying to issue commands to the 3d printer.
For example, I want to issue a command that makes the 3d printer jog the X-axis.
import requests
headers = {"Authorization": "Bearer <token>"}
def Beep():
api_link = "http://octopi.local/api/printer/command"
params = {"command":"jog","x":10}
return requests.post(api_link, headers=headers, params=params)
The output of this code is <Response 400> (bad request). What I am missing?
From the API documentation:
If not otherwise stated, OctoPrint’s API expects request bodies and issues response bodies as Content-Type: application/json.
Your request is not sending JSON. Use this instead:
requests.post(api_link, headers=headers, json=params)
Also, it looks like the jog command is supposed to use the url path /api/printer/printhead.

Pyton requests: Extracting data from payload

this is my first ever question on here.
Currently I am looking into the Python requests module. I am trying to automate a task for which i need to pass on a csrf token.
The csrf token can be found in the payload of a previous request.
How can I extract the value out of the Payload?
Example Payload:
value1: ABCD
value2: EFGH
csrf_token: the token I am looking for
value3: false
Sorry if this is a dumb or easy question but I am not able to solve it right now.
Thanks for your help!
Here are some examples of where the data you might be looking for is located.
import requests
response = requests.get('http://some_url')
# raise an exception if the status code != 200
response.raise_for_status()
# the contents of the response. (bytes)
contents = response.contents
# the contents of the response if the contents are
# formatted as JSON. (dictionary)
contents = response.json()
# the headers of the response. (dictionary)
headers = response.headers
# You also have to consider if you are using the correct HTTP protocol
payload = {}
response = requests.put('http://some_url', json=payload)
response = requests.post('http://some_url', json=payload)
# the responses are going to function just like when using the "get" protocol

How to send POST request with each payload on its own line using Python requests

I have to send a POST request to the /batch endpoint of : 'https://www.google-analytics.com'.
As mentioned in the Documentation I have to send the request to /batch endpoint and specify each payload on its own line.
I was able to achieve this using POSTMAN as follows:
My query is to make a POST request using Python's requests library
I tried something like this :
import requests
text = '''v=1&cid=43223523&tid=UA-XXXXXX-1&t=event&ec=aggregated_stats&ea=daily_kpi&el=bookmarks&ev=13
v=1&cid=43223523&tid=UA-XXXXXX-1&t=event&ec=aggregated_stats&ea=daily_kpi&el=upvotes&ev=65
v=1&cid=43223523&tid=UA-XXXXXX-1&t=event&ec=aggregated_stats&ea=daily_kpi&el=questions&ev=15
v=1&cid=43223523&tid=UA-XXXXXX-1&t=event&ec=aggregated_stats&ea=daily_kpi&el=postviews&ev=95'''
response = requests.post('https://www.google-analytics.com/batch', data=text)
but it doesn't works.
UPDATE
I Tried this and it works !
import http.client
conn = http.client.HTTPSConnection("www.google-analytics.com")
payload = "v=1&cid=43223523&tid=UA-200248207-1&t=event&ec=aggregated_stats&ea=daily_kpi&el=bookmarks&ev=13\r\nv=1&cid=43223523&tid=UA-200248207-1&t=event&ec=aggregated_stats&ea=daily_kpi&el=upvotes&ev=63\r\nv=1&cid=43223523&tid=UA-200248207-1&t=event&ec=aggregated_stats&ea=daily_kpi&el=questions&ev=11\r\nv=1&cid=43223523&tid=UA-200248207-1&t=event&ec=aggregated_stats&ea=daily_kpi&el=postviews&ev=23"
headers = {
'Content-Type': 'text/plain'
}
conn.request("POST", "/batch", payload, headers)
res = conn.getresponse()
But the question remains open, what's the issue with requests here.
You don't need to double-escape the newline symbol.
Moreover, you don't need the newline symbol at all for the multi-line string.
And also the indentations you put in your multi-line string are counted:
test = '''abc
def
ghi'''
print(test)
Here's an SO answer that explains this with some additional ways to make long stings: https://stackoverflow.com/a/10660443/4570170
Now the request body.
The documentation says
payload_data – The BODY of the post request. The body must include exactly 1 URI encoded payload and must be no longer than 8192 bytes.
So try uri-encoding your payload:
text = '''v=1&cid=43223523&tid=UA-XXXXXX-1&t=event&ec=aggregated_stats&ea=daily_kpi&el=bookmarks&ev=13
v=1&cid=43223523&tid=UA-XXXXXX-1&t=event&ec=aggregated_stats&ea=daily_kpi&el=upvotes&ev=65
v=1&cid=43223523&tid=UA-XXXXXX-1&t=event&ec=aggregated_stats&ea=daily_kpi&el=questions&ev=15
v=1&cid=43223523&tid=UA-XXXXXX-1&t=event&ec=aggregated_stats&ea=daily_kpi&el=postviews&ev=95'''
text_final = requests.utils.quote(text)
response = requests.post('https://www.google-analytics.com/batch', data=text_final)
Finally , I figured out the solution myself.
Updating for others help.
The problem was I was working on AWS Cloud9 and as mentioned in the documentation
Some environments are not able to send hits to Google Analytics directly. Examples of this are older mobile phones that can't run JavaScript or corporate intranets behind a firewall.
So we just need to include the User Agent parameter
ua=Opera/9.80
in each of our payloads
It works !

Flask: Cannot Decode Incoming JSON Submitted Using Requests

I'm having an issue trying to decode a python dictionary sent to my server as json.
This is what I have in my application:
payload = {'status':[bathroomId,item,percentage,timestamp]}
r=requests.post(url,None,json.dumps(payload))
Here is what I do in my Flask server:
req = request.get_json()
print req['status']
When I try to print the content of req['status'], it seems like python won't recognize it as a dictionary and I get an internal server error.
I tried printing req, and I get None
What am I missing?
Unless you set the Content-Type header to application/json in your request, Flask will not attempt to decode any JSON found in your request body.
Instead, get_json will return None (which is what you're seeing right now).
So, you need to set the Content-Type header in your request.
Fortunately since version 2.4.2 (released a year ago), requests has a helper argument to post JSON; this will set the proper headers for you. Use:
requests.post(url, json=payload)
Alternatively (e.g. using requests < 2.4.2), you can set the header yourself:
requests.post(url, data=json.dumps(payload), headers={"Content-Type": "application/json"})
Here is the relevant code from Flask:
Flask only loads JSON if is_json is True (or if you pass force=True to get_json). Otherwise, it returns None.
is_json looks at the Content-Type header, and looks for application/json there.

Sending json post request with python

With the firefox plugin "HttpFox" i'm getting the POST request which looks like this:
{'json':'{"command":"SEARCH","data":{"someData":"someValue","otherData":"otherData"}}'}
Now i need to send a http request build with python to get the same data as i would get via browser. See code:
headers = {'Content-type': 'application/json; charset=utf-8'}
payload = ?
req = requests.post(url, data=json.dumps(payload), headers = headers)
My problem is:
I'm not sure how to build the payload. It should be a dictionary as well, but im confused because of the POST type which is delivered with HttpFox. There are two dictionaries inside the main dictionary.
How should i handle this ?
Appreciate any help.
Ok, i found the solution:
It was necessary to build a dict like this:
valueString = """{"command":"SEARCH","data":{"someData":"someValue","otherData":"otherData"}}"""
/// the """ ensures that the whole text between """ is handled as a string.
payload = {'json': valueString}
The key 'json' requieres a string. In this case the string looks like a dictionary.
That's it.

Categories