Python Requests Put not working with build.phonegap.com - python

I am making a python build script for a phonegap project.
I need to open the ios key before i build
I am trying to do this with a http put request through the requests module for python.
If i do it with cURL from command line, it works fine
curl -vvv -d 'data={"password":"myPassWord"}' -X PUT https://build.phonegap.com/api/v1/keys/ios/193686?auth_token=passwordlesstokenphg
But from python like this.
password_for_key = {'password': 'myPassword'}
authentication_token = {'auth_token': 'passwordlesstokenphg'}
requests.put('https://build.phonegap.com/api/v1/keys/ios/193686', data=password_for_key, params=authentication_token)
It just returns the json you would recieve if you did a cURL without the data.
For me it seems like the data is not being sent to phonegap correctly.
API reference from build.phonegap.com
docs.build.phonegap.com/en_US/2.9.0/developer_api_write.md.html
Please help :)

So when you do
curl -d "..." -X PUT https://example.com
curl sends exactly what's in that string. requests does not translate so directly to curl. To do something similar in requests you need to do the following:
import json
password_for_key = {'password': 'myPassword'}
authentication_token = {'auth_token': 'passwordlesstokenphg'}
requests.put('https://build.phonegap.com/api/v1/keys/ios/193686',
data={'data': json.dumps(password_for_key)},
params=authentication_token)
What requests will do is build data={"password":"myPassword"} for you if you use the above. First you have to JSON encode the data in password_for_key then pass it in the dictionary to data.

Related

Python OAuth Client Credentials Grant Type Returned 400, [error: unsupported grant] type but Curl Works Fine

I am very new to APIs (still learning) and I encountered a very weird issue with Python requests library when trying to initiate an OAuth Authentication flow with Client Credentials Grant Type.
For some reason, whenever I used my Python script (with the help of requests library) to send the HTTP request to the authentication endpoint, I always get
Response Status Code: 400
Response Body/Data returned: {"error":"unsupported_grant_type"}
However, if I tried using curl command line tool to send the request, I will get a successful response with status code 200 with the access token in the response body like this:
{'access_token': 'some access token',
'expires_in': 'num_of_seconds',
'token_type': 'Bearer'}
As a matter of fact, if I tried sending the request using Curl command line tool WITHIN my Python Script (with subprocess.Popen function), I can get the response with status code 200 and the access token with no problem.
Now, with that said, here's the Python script that I used to send the request to initiate the OAuth authentication flow:
import requests
import os
import base64
clientCredentialEndpoint = "https://base_url/path/token"
client_id = os.environ.get('CLIENT_ID')
client_secret = os.environ.get('CLIENT_SECRET')
# -- Encode the <client_id:client_secret> string to base64 --
auth_value = f'{client_id}:{client_secret}'
auth_value_bytes = auth_value.encode('ascii')
auth_value_b64 = base64.b64encode(auth_value_bytes).decode('ascii')
queryParams ={
'grant_type':'client_credentials',
'scope':'get_listings_data'
}
headers = {
'Authorization':f'Basic {auth_value_b64}',
'Content-Type':'application/x-www-form-urlencoded'
}
# send the post request to Authorisation server
response = requests.post(
clientCredentialEndpoint,
params=queryParams,
headers=headers,
)
print(response.status_code)
print(response.text)
whereas the curl command that I used (and worked) to send the request is:
curl -X POST -u '<client_id>:<client_secret>' \
-H "Content-Type: application/x-www-form-urlencoded" \
-d 'grant_type=client_credentials&scope=get_listings_data' \
'https://base_url/path/token'
Again, like I said, if I execute this curl command inside a Python script, it will successfully return the access token with no issue.
Does anyone know what I did wrong in my Python script which caused my request to always fail?
Thanks in advance!
My goodness me, I just realised that the -d in the curl command does not correspond to query params, it stands for 'data'.
Hence, I just need to change my Python script requests.post() a bit so that it looks like this:
response = requests.post(
clientCredentialEndpoint,
data=queryParams,
headers=headers,
)
Hope this helps others.

python upload file with curl

i'm trying to upload an apk to server
the code i used to upload using curl is written like this:
curl -u "musername:mypass" -X POST "https://myurl/upload" -F "file=#D:\path\to\location.apk"
i tried to make a script using python with requests library like this:
response = requests.post(
self.urlUpload,
files={"file" : open(self.apkLocation, 'r')},
auth=(self.BSUsername, self.BSToken)
)
but it gives me errors:
{"error":"Malformed archive"}
anyone knows why this erros appeared?
Have you had a chance to try something like below?
import requests
files = {
'file': ('/path/to/app/file/Application-debug.apk', open('/path/to/app/file/Application-debug.apk', 'rb')),
}
response = requests.post('https://api-cloud.browserstack.com/app-automate/upload',
files=files,
auth=('BSUsername ', 'BSToken'))
print (response.text)#THE APP URL (bs://<hashed appid>) RETURNED IN THE RESPONSE OF THIE CALL
Check the BrowserStack REST API doc here

Python - curl request with requests, header not set correctly? (possible GitLab API issue)

I am trying to use the Gitlab API to make an issue from Python.
The following curl request works (tested and confirmed):
curl --request POST --header "PRIVATE-TOKEN: <my token>" https://gitlab.com/api/v3/projects/<my project id>/issues?title=Issues%20with%20auth&labels=bug
My Python code:
import requests
r = requests.post("https://gitlab.com/api/v3/projects/2674887/issues", data={
"title":issueform.instance.title,
"description":issueform.instance.description
},
headers={"PRIVATE_TOKEN":"<token>"})
print(r.status_code, r.reason)
I get: 401 Unauthorized
Am I doing something wrong in my POST request or is this an issue with GitLab rejecting doing it this way possibly?
The relevant part from the API:
http://docs.gitlab.com/ee/api/issues.html#new-issue
EDIT:
Forgot to mention, ignore the issueform.instance stuff, they are just Strings (it is a Django project and I omitted the form stuff because it shouldn't be relevant)
change PRIVATE_TOKEN to PRIVATE-TOKEN
Maybe it just a typo? could you try the below?
"PRIVATE-TOKEN"
instead of
"PRIVATE_TOKEN"

Post multipart data in python with Requests module

I actually want to send mutlipart data on a web-application with python. I'm using this wery useful Requests module (http://requests-fr.readthedocs.org/en/latest/).
I have to send an audio file (stored in local on the system) and 2 parameters (GPS coordonates for information).
I have already mannage to do this with a curl command, but i'm looking for a Requests python implementation.
This is the curl command:
curl -u "user:pass" -F 'audio=#file.wav' -F "latitude=42.44646" -F "longitude=8.46464" 'http://my_server_ip/web/rest/vocal' -v --digest
This is how i'm trying to do that in python Requests:
url = "http://my_server_ip/web/rest/vocal"
files = {'audio' : open('/PATH/record.wav','rb'),'latitude':42.44646,'longitude':8.46464}
r = requests.post(url, auth=HTTPDigestAuth('user','pass'),data=files)
r.json
print r.json
For the moment, the only response i get is a 500 error.
Does someone understand what's wrong ? Feel free to tell me if you see a better solution to do that :)
Greetings!
Solved !
The solution is to separate the files and the datas like that:
files = {'audio' : open('/PATH//record.wav','rb')}
data = {'latitude':latitude,'longitude':longitude}
And build the resquest wit BOTH files AND data parameters:
r=requests.post(url,auth=HTTPDigestAuth('user','pass'),files=files,data=data)

Spaces in a URL when using requests and python

I hope I can explain myself. with out making an arse of myself.
I am trying to use python 3.4 to send a url to a sparkcore api.
I have managed to use curl direcly from the windows command line:-
curl https://api.spark.io/v1/devices/xxxxxxxxxxxxxxx/led -d access_token=yyyyyyyyyyyyyyyy -d params=l1,HIGH
All works fine. there is a space between the led and -d, but that is not a problem.
I have read that reting to do this within python using libcurl is a big pain and I saw lots of messaged about using Requests, so I though I would give it a go.
So I wrote a small routine:
import requests
r = requests.get('https://api.spark.io/v1/devices/xxxxxxxxxxxxxxxxxx/led -d access_token=yyyyyyyyyyyyyyyyy -d params=l1,HIGH')
print(r.url)
print(r)
I get as return:
<Response [400]>
When I examine the URL which actually got sent out the spaces in the URL are replaced with %20. This seems to be my actual problem, because the %20 being added by requests are confusing the server which fails
"code": 400,
"error": "invalid_request",
"error_description": "The access token was not found"
I have tried reading up on how to inpractice have the spaces with out having a %20 being added by the encoding, but I really could do with a pointer in the right direction.
Thanks
Liam
URLs cannot have spaces. The curl command you are using is actually making a request to the url https://api.spark.io/v1/devices/xxxxxxxxxxxxxxx/led with some command line arguments (using -d)
The curl man (manual) page says this about the -d command line argument
-d, --data
(HTTP) Sends the specified data in a POST request to the HTTP server, in the same way that a browser does when a user has filled in an HTML form and presses the submit button. This will cause curl to pass the data to the server using the content-type application/x-www-form-urlencoded. Compare to -F, --form.
-d, --data is the same as --data-ascii. To post data purely binary, you should instead use the --data-binary option. To URL-encode the value of a form field you may use --data-urlencode.
If any of these options is used more than once on the same command line, the data pieces specified will be merged together with a separating &-symbol. Thus, using '-d name=daniel -d skill=lousy' would generate a post chunk that looks like 'name=daniel&skill=lousy'.
If you start the data with the letter #, the rest should be a file name to read the data from, or - if you want curl to read the data from stdin. Multiple files can also be specified. Posting data from a file named 'foobar' would thus be done with --data #foobar. When --data is told to read from a file like that, carriage returns and newlines will be stripped out.
So that says -d is for sending data to the URL with the POST request using the content-type application/x-www-form-urlencoded
The requests documentation has a good example of how to do that using the requests library: http://docs.python-requests.org/en/latest/user/quickstart/#more-complicated-post-requests
So for your curl command, I think this should work
import requests
payload = {'access_token': 'yyyyyyyyyyyyyyyy', 'params': 'l1,HIGH'}
r = requests.post("https://api.spark.io/v1/devices/xxxxxxxxxxxxxxx/led", data=payload)
print(r.text)

Categories