JustaCookie
JustaCookie

Reputation: 181

How to POST this API code in Python 3 with Requests module? Keep getting 405 error

I want to use the API for a link shortener site. I know the example given is in curl and that -H means there's a header as well as PUT means it's posting, but I can't seem to get the result I want no matter how much I try. All I can do is either get a 405 error or break it.

I am on Windows with Python 3 and do have requests installed already.

For developers Shorte.st prepared API which returns responses in JSON format.

Currently there is one method which can be used to shorten links on behalf of your account.

Take a look on the sample below to learn how to use our API.

curl -H "public-api-token: (my token)" -X PUT -d
"urlToShorten=google.com" https://api.shorte.st/v1/data/url 

When received,

{"status":"ok","shortenedUrl":"http:\/\/sh.st\/XXXX"}

I have tried a few things namely,

import requests
import json
gogo = { 'public-api-token: (my token)' : 'urlToShorten=google.com'}
yep = requests.post('https://api.shorte.st/v1/data/url',   
data=json.dumps(gogo))
print (yep.text)

shows me an HTML webpage with error 405.

import requests
import json
gogo = { 'public-api-token' : '(my token)', 'urlToShorten=' : 'google.com'}
yep = requests.post('https://api.shorte.st/v1/data/url',    
data=json.dumps(gogo))
print (yep.text)

Also shows me a webpage with error 405.

I now know the -H is for headers and am using this while still just gets me the page.

import requests
import json

headers = { 'public-api-token' : '(my token)' }
gogo = {"urlToShorten" : "google.com"}
yep = requests.post('https://api.shorte.st/v1/data/url',  
data=json.dumps(gogo), headers=headers)
print (yep.text)

and another attempt another 405

gogo = {"public-api-token: (my token)" : "urlToShorten=google.com"}
yep = requests.post('https://api.shorte.st/v1/data/url', 
data=json.dumps(gogo))
print (yep.text)

Even this just gives me a full html page/405 if I take off the text.

headers = { "public-api-token: (my token)" : "urlToShorten=google.com" }
yep = requests.post('https://api.shorte.st/v1/data/url', headers=headers)
print (yep.text)

Upvotes: 3

Views: 1932

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1123410

You are putting your PUT payload in the headers. Put it in the body instead. Your payload is not JSON, so there is no need to try and treat it as such.

The headers need to be specified as a dictionary with the header name and token as key and value. The parameters for the payload can be treated in the same way.

You are also using the wrong requests method; to send a PUT request, use the put function instead:

headers = {'public-api-token': '(my token)'}
payload = {'urlToShorten': 'google.com'}
response = requests.put(
    'https://api.shorte.st/v1/data/url',
    data=payload, headers=headers)

print(response.json())

The response object has a json() method to decode the JSON data returned by the API; it'll give you the Python data structure corresponding to the JSON text.

I don't have a token for the service you are using; I created a demo using the httpbin.org service; it reflects what was sent as a JSON response:

>>> import requests
>>> headers = {'public-api-token': '(my token)'}
>>> payload = {'urlToShorten': 'google.com'}
>>> response = requests.put(
...     'http://httpbin.org/put',
...         data=payload, headers=headers)
>>> from pprint import pprint
>>> pprint(response.json())
{u'args': {},
 u'data': u'',
 u'files': {},
 u'form': {u'urlToShorten': u'google.com'},
 u'headers': {u'Accept': u'*/*',
              u'Accept-Encoding': u'gzip, deflate',
              u'Content-Length': u'23',
              u'Content-Type': u'application/x-www-form-urlencoded',
              u'Host': u'httpbin.org',
              u'Public-Api-Token': u'(my token)',
              u'User-Agent': u'python-requests/2.5.0 CPython/2.7.9 Darwin/14.1.0'},
 u'json': None,
 u'origin': u'94.118.96.0',
 u'url': u'http://httpbin.org/put'}

If you compare that to the output produced for curl sending a PUT request to the same URL you'll see the same results are produced:

$ curl -H "public-api-token: (my token)" -X PUT \
     -d "urlToShorten=google.com" http://httpbin.org/put
{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "urlToShorten": "google.com"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Content-Length": "23", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "Public-Api-Token": "(my token)", 
    "User-Agent": "curl/7.37.1"
  }, 
  "json": null, 
  "origin": "94.118.96.0", 
  "url": "http://httpbin.org/put"
}

Upvotes: 6

Related Questions