I'm trying to access AWX API from a script Python.
The documentation has the ressource /api/v1/authtoken/ for that, however when visiting the URL:
https://myHost/api/v1/authtoken/
It says that it can't find the ressource.
I also tried:
response = requests.get('https://myHost/api/login/', verify=False,
data = json.dumps({"username": "user","password": "pass"}))
results = json.loads(response.text)
token = results['token']
But I get a :
ValueError: No JSON object could be decoded
AWX version: 10.0.0
The fine manual says that:
A GET to /api/login/ displays the login page of API browser
So = requests.get( is for sure not what you want; however, even if you were to switch to requests.post the very next line says:
It should be noted that the POST body of /api/login/ is not in JSON, but in HTTP form format. Four items should be provided in the form:
so data = json.dumps({ is also for sure also not what you want
Related
I'm trying to fetch metadata from thoughtspot. I am able to call the url using browser and fetch the data. But here I'm trying to achieve it via python program. According to thougthspot documentation. I have to enable trusted authentication and pass my secret key & username to obtain a token which I can use in my program.
https://developers.thoughtspot.com/docs/?pageid=api-auth-session
my username : username#username.com
secret key : secret-key
Below is my code:(generated by postman)
import requests
url = "https://<ThoughtSpot-host>/callosum/v1/tspublic/v1/session/auth/token?auth_token=secret-key&access_level=FULL&username=username#username.com"
payload={}
headers = {}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
I'm getting Bad request error. Anyone here using thoughtspot over this issue. Appreciate your support very much.
Error I'm getting:
{"type":"Bad Request","description":"The server could not understand the request due to invalid syntax."}
I can fetch data by calling the api using a web-browser. Below url returns list of all meta-data objects. I want to achieve this using a python program (I have to authenticate first & call the below URL - Authentication step is not working for me when I tried to follow the documentation)
https://<ThoughtSpot-host>/callosum/v1/tspublic/v1/metadata/list
Did you try changing the url so that it includes the domain name?
Also post the error you are getting. And a screenshot of a working request would be great!
I'm trying to use this service, Buffer, to publish a post on Facebook through API.
Here's my code:
params = {
'profile_ids': ids,
'text': "text",
'access_token': access_token
}
r = requests.post('https://api.bufferapp.com/1/updates/create.json', params=params)
print r.json()
print(r.url)
But when run I it, it prints out this message:
{"success":false,"message":"Please select at least one account to post from.","code":1004}
This is the URL used to make the request:
https://api.bufferapp.com/1/updates/create.json?access_token=ACCESS_TOKEN&text=TEXT&profile_ids=LIST_WITH_PROFILE_IDS
I made sure the id is correct and I got it both manually and through API still, I get the same message.
The only required parameter is the profile_ids which should be an array. Here's the documentation on their website about publishing posts("updates"): https://buffer.com/developers/api/updates
What am I doing wrong here?
It seems that the API expects the data in the post request payload, not as url parameters.
Use data, not params.
r = requests.post('https://api.bufferapp.com/1/updates/create.json', data=params)
# -------------------------------------------------------------------^^^^ here
I'm trying to do a curl command with python requests. As far as I can tell I'm doing everything correctly but the website won't recognize the api key no matter how I try to include it. Basically, the site I'm trying to reach wants the api key put in the beginning of the url. When I do this with curl, it works perfectly. When I try it via python requests, however, it doesn't work. It also doesn't work to send it in as a key-value pairing in dictionary.
This works
curl -H "Content-Type:application/json" -d '{"ndbno":["11124"],"type":"f"}' [API KEY]#api.nal.usda.gov/ndb/V2/reports
and here's the requests code:
import requests
headers = {'Content-Type': 'application/json',}
data = '{"ndbno":["11124"],"type":"f"}'
response = requests.post('http://[API KEY]#api.nal.usda.gov/ndb/V2/reports', headers=headers, data=data)
The result from this is a json response containing the message: "{'error': {'code': 'API_KEY_MISSING', 'message': 'No api_key was supplied. Get one at http://api.nal.usda.gov:80'}}
"
It also doesn't work if I remove the [API KEY] from the url and add it to the data dictionary as "api_key":"[API KEY]"
BTW I'm not passing the key in as a list or anything, I just didn't want to post the physical key in my question.
I'm a total newb to python and stackoverflow, but I've done my due diligence and have been searching out answers and testing different ways to format the request for a few hours now. Any help is greatly appreciated!
Looking at the PubAG API, it appears that you can simply pass the api_key in the URL query string. I'd assume it's the same for the API you're using, but a cursory search yielded no documentation.
Try:
https://api.nal.usda.gov/ndb/V2/reports?api_key=[API_KEY]
response = requests.post('https://api.nal.usda.gov/ndb/V2/reports?api_key=[API_KEY]', headers=headers, data=data)
I don't have an API key to try this out with, but navigating to https://api.nal.usda.gov/ndb/V2/reports?api_key=asdfds in my browser gives me an invalid API key error, which suggests that the endpoint recognizes that I've given an API key.
It's probably because requests does not parse the API KEY from the URL, try this:
response = requests.post('http://api.nal.usda.gov/ndb/V2/reports', headers=headers, data=data, auth=(API_KEY, ''))
This passes it using Basic Authentication (Authorization header) which is the same behavior that curl does when parsing the URL.
Normally in Basic Auth you would have the username and the password. E.g:
auth=('<username>', '<password>')
Since this API only seems to care about the username, I have left the password as blank.
I am trying to update an already saved form on a system using HTTP requests. Due to the server configuration for the third party app we use, updating by POST requires sending a fully filled out payload every single time.
I want to get round this by recovering the form data already present on the server and converting it into a dictionary. Then changing any values I need and reposting to make changes sever side.
The application we use sends a POST request when the save button is clicked for a particular form.
Here I send a post request with no payload.
[This simulates pressing the save button and is also the point where dev tools shows me a the payload I want to capture]
post_test = self.session.post(url_to_retrieve_from)
I thought that now I should be able to print the output, which should resemble what Google Dev tools Form data captures.
print(post_test.text)
This just gives me html found on the webpage.
If Dev Tools can get this from the server then I should also be able to?
Example of Data I am trying to get via requests:
Form Data
If Dev Tools can get this from the server then I should also be able to?
Yes, of course. In requests you pass form data in data keyword:
import requests
url = 'http://www.example.com'
data = {
'name': 'value',
}
response = requests.post(url, data=data)
You can get the data you sent with a request from the response in this way:
import requests
response = requests.post('http://your_url', data=data) # send request
body = response.request.body
parsed_data = dict(data.split('=') for data in body.split('&')) # parse request body
Here you can find more information about data argument
In the documentation, in the class requests.Response we can find the attribute:
request = None
The PreparedRequest object to which this is a response.
In requests.PreparedRequest class we can read:
body = None
request body to send to the server.
I am trying to add an attachment to my timeline with the multipart encoding. I've been doing something like the following:
req = urllib2.Request(url,data={body}, header={header})
resp = urllib2.urlopen(req).read()
And it has been working fine for application/json. However, I'm not sure how to format the body for multipart. I've also used some libraries: requests and poster and they both return 401 for some reason.
How can I make a multipart request either with a libary(preferably a plug-in to urllib2) or with urllib2 itself (like the block of code above)?
EDIT:
I also would like this to be able to support the mirror-api "video/vnd.google-glass.stream-url" from https://developers.google.com/glass/timeline
For the request using poster library here is the code:
register_openers()
datagen, headers = multipart_encode({'image1':open('555.jpg', 'rb')})
Here it is using requets:
headers = {'Authorization' : 'Bearer %s' % access_token}
files = {'file': open('555.jpg', 'rb')}
r = requests.post(timeline_url,files=files, headers=headers)
Returns 401 -> header
Thank you
There is a working Curl example of a multipart request that uses the streaming video url feature here:
Previous Streaming Video Answer with Curl example
It does exactly what you are trying to do, but with Curl. You just need to adapt that to your technology stack.
The 401 you are receiving is going to prevent you even if you use the right syntax. A 401 response indicates you do not have authorization to modify the timeline. Make sure you can insert a simple hello world text only card first. Once you get past the 401 error and get into parsing errors and format issues the link above should be everything you need.
One last note, you don't need urllib2, the Mirror API team dropped a gem of a feature in our lap and we don't need to be bothered with getting the binary of the video, check that example linked above I only provided a URL in the multipart payload, no need to stream the binary data! Google does all the magic in XE6 and above for us.
Thanks Team Glass!
I think you will find this is simpler than you think. Try out the curl example and watch out for incompatible video types, when you get that far, if you don't use a compatible type it will appear not to work in Glass, make sure your video is encoded in a Glass friendly format.
Good luck!
How to add an attachment to a timeline with multipart encoding:
The easiest way to add attachments with multipart encoding to a timeline is to use the
Google APIs Client Library for Python. With this library, you can simple use the following example code provided in the Mirror API timeline insert documentation (click the Python tab under Examples).
from apiclient.discovery import build
service = build('mirror', 'v1')
def insert_timeline_item(service, text, content_type=None, attachment=None,
notification_level=None):
timeline_item = {'text': text}
media_body = None
if notification_level:
timeline_item['notification'] = {'level': notification_level}
if content_type and attachment:
media_body = MediaIoBaseUpload(
io.BytesIO(attachment), mimetype=content_type, resumable=True)
try:
return service.timeline().insert(
body=timeline_item, media_body=media_body).execute()
except errors.HttpError, error:
print 'An error occurred: %s' % error
You cannot actually use requests or poster to automatically encode your data, because these libraries encode things in multipart/form-data whereas Mirror API wants things in multipart/related.
How to debug your current error code:
Your code gives a 401, which is an authorization error. This means you are probably failing to include your access token with your requests. To include an access token, set the Authorization field to Bearer: YOUR_ACCESS_TOKEN in your request (documentation here).
If you do not know how to get an access token, the Glass developer docs has a page here explaining how to obtain an access token. Make sure that your authorization process requested the following scope for multipart-upload, otherwise you will get a 403 error. https://www.googleapis.com/auth/glass.timeline
This is how I did it and how the python client library does it.
from email.mime.multipart import MIMEMultipart
from email.mime.nonmultipart import MIMENonMultipart
from email.mime.image import MIMEImage
mime_root = MIMEMultipart('related', '===============xxxxxxxxxxxxx==')
headers= {'Content-Type': 'multipart/related; '
'boundary="%s"' % mime_root.get_boundary(),
'Authorization':'Bearer %s' % access_token}
setattr(mime_root, '_write_headers', lambda self: None)
#Create the metadata part of the MIME
mime_text = MIMENonMultipart(*['application','json'])
mime_text.set_payload("{'text':'waddup doe!'}")
print "Attaching the json"
mime_root.attach(mime_text)
if method == 'Image':
#DO Image
file_upload = open('555.jpg', 'rb')
mime_image = MIMENonMultipart(*['image', 'jpeg'])
#add the required header
mime_image['Content-Transfer-Encoding'] = 'binary'
#read the file as binary
mime_image.set_payload(file_upload.read())
print "attaching the jpeg"
mime_root.attach(mime_image)
elif method == 'Video':
mime_video = MIMENonMultipart(*['video', 'vnd.google-glass.stream-url'])
#add the payload
mime_video.set_payload('https://dl.dropboxusercontent.com/u/6562706/sweetie-wobbly-cat-720p.mp4')
mime_root.attach(mime_video)
Mark Scheel I used your video for testing purposes :) Thank you.