[SalesForce] Using Python to send POST request with REST API on Wave Analytics

this is a follow on from this question

Something is wrong with my saqlquery string variable I am passing as 'data' to the api.

The below code is returning the response

{"errorCode":"118","message":"The request body is empty"}

Python code below

import json, requests


consumer_key = "xxxx"
consumer_secret = "xxxx"
username = "xxxx"
password = "xxxx"

payload = {
    'grant_type': 'password',
    'client_id': consumer_key,
    'client_secret': consumer_secret,
    'username': username,
    'password': password
}

r = requests.post("https://login.salesforce.com/services/oauth2/token",
    headers={"Content-Type":"application/x-www-form-urlencoded"},
    data=payload)


print r.content
body = json.loads(r.content)
token = body["access_token"]
saqlquery = "q = load \"0Fb28000000PBfqCAG/0Fc28000000Ag0nCAC;\";q = group q by 'Name';q = foreach q generate 'Name' as 'Name', sum('Amount') as 'sum_Amount';}"
url = body["instance_url"] + "/services/data/v36.0/wave/query"

r = requests.post(url, headers = {"Authorization":"Bearer " + token}, data = {"query":saqlquery});

print r.content

Best Answer

If you print your JSON request:

print {"query" : saqlquery}

You will get python String:

{
    'query': 'q = load "0Fb28000000PBfqCAG/0Fc28000000Ag0nCAC;";
    q = group q by \'Name\';
    q = foreach q generate \'Name\' as \'Name\', sum(\'Amount\') as \'sum_Amount\';}'
}

When example should be JSON:

{
    "query":"q = load \"0Fbxx0000000006CAA/0Fcxx000000001dCAA\";
     q = group q by 'FirstName';
     q = foreach q generate 'FirstName' as 'FirstName', count() as 'count';
     q = limit q 2000;"
}

Try to load your String into JSON:

msgStr = {
    'query':'q = load \"0Fbxx0000000006CAA/0Fcxx000000001dCAA\";'
        +'q = group q by \'FirstName\';'
        +'q = foreach q generate \'FirstName\' as \'FirstName\', count() as \'count\';'
        +'q = limit q 2000;'
}

msgJson = json.dumps(msgStr)
print msgJson

Result is same as example.

Finally send request:

headers = {"Authorization":"Bearer " + token,"Content-Type":"application/json"}
r = requests.post(url, headers = headers, data = msgJson);
print r.content

I dont have access to wave(its stuck), but I've checked similar String with SF rest api, please add any issues if you have