0

Trying to call an api with Python where a part of the headers contain "{}".

With Curl it works directly:

curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' --header 'token: {"uid": "[email protected]","timestamp": 0,"token": "","client": "web","version": "","language": "zh-CN" }' -d '{ \ 
   "account": "[email protected]", \ 
   "pwd": "mypassword", \ 
   "is_local": true, \ 
   "agreement_agreement": 0 \ 
 }' 'http://globalapi.sems.com.cn:82/api/v1/Common/CrossLogin'

But with Python I cannot get it to work, the api throws an error. I suspect it is due to the format of the token in the header as it is a string containing {}. See the different variants commented out below - the api accepts none of them. It works fine to use {} in a dict with Python just using regular code:

sems_headers = {
    'Content-Type':'application/json',
    'Accept':'text/json',
    'token': '{"uid": "[email protected]","timestamp": 0,"token": "","client": "web","version": "","language": "en-GB"}' 
}
for c, d in sems_headers.items():
    print(c, d)

How can I call the api with the format required of the token in Python?

sems_headers = {
    'Content-Type':'application/json',
    'Accept':'text/json',
    #'token': "'uid':'[email protected]', 'timestamp':'0', 'token':'', 'client':'web', 'version':'', 'language':'en-GB'" 
    #'token': '{"uid": "[email protected]","timestamp": 0,"token": "","client": "web","version": "","language": "en-GB"}' 
    #'token': ''{{"uid": "[email protected]","timestamp": 0,"token": "","client": "web","version": "","language": "en-GB"}}' 
    #'token': "{""uid"": ""[email protected]"", ""timestamp"": 0, ""token"": "" "", ""client"": ""web"", ""version"": "" "", ""language"": ""en-GB"" }"
}

sems_post_data = {
    'account':'[email protected]',
    'pwd':'mypassword',
    'is_local':True,
    'agreement_agreement':0
}

post = requests.post("https://globalapi.sems.com.cn/api/v1/Common/CrossLogin", headers=sems_headers, data=sems_post_data)

print(post.text)
6
  • 2
    Have you tried using an actual dict rather than putting it in a string? As in 'token': {'uid': '[email protected]', 'timestamp': '0' ...so on} Commented Apr 9, 2020 at 11:02
  • 1
    Also can you include a copy/paste of the specific error you're encountering so we can best help you? Commented Apr 9, 2020 at 11:04
  • 1
    @awarrier99 Using a dict as token is invalid. Header values "must be of type str or bytes, not <class 'dict'>". Commented Apr 9, 2020 at 11:13
  • @MisterMiyagi yup just found that in the docs. @herrbert ignore my original suggestion of using an actual dict, but please do include the error so we can see what's going wrong Commented Apr 9, 2020 at 11:15
  • @MisterMiyagi is correct. Below can refer - iot-guider.com/raspberrypi/… Commented Apr 9, 2020 at 11:24

1 Answer 1

1

From the requests docs here it looks like your issue may actually be with how you're sending your JSON payload, as the data keyword argument sends form-encoded data rather than JSON-encoded. Try either explicitly JSON-encoding your payload, or using the json keyword argument instead:

post = requests.post("https://globalapi.sems.com.cn/api/v1/Common/CrossLogin", headers=sems_headers, json=sems_post_data)

or

import json
post = requests.post("https://globalapi.sems.com.cn/api/v1/Common/CrossLogin", headers=sems_headers, data=json.dumps(sems_post_data))

Also your Accept header should be changed to application/json and in order to parse the JSON response content, you should use post.json() rather than post.text

Altogether this would be:

sems_headers = {
    'Content-Type':'application/json',
    'Accept':'application/json',
    'token': '{"uid": "[email protected]","timestamp": 0,"token": "","client": "web","version": "","language": "en-GB"}' 
}

sems_post_data = {
    'account':'[email protected]',
    'pwd':'mypassword',
    'is_local':True,
    'agreement_agreement':0
}

post = requests.post("https://globalapi.sems.com.cn/api/v1/Common/CrossLogin", headers=sems_headers, json=sems_post_data)

print(post.json())
Sign up to request clarification or add additional context in comments.

2 Comments

thanks, adding json-dumps for the data in the request solved it!
@herrbert awesome, no problem

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.