How to call a REST API using Python using json request/response- Crucible Development
Asked by Amit Pandey:

I am a newbie to python and am trying to create a script to login to crucible and use the token to pass to other services.

1) I am able to make a xml request and get a response but as soon as I pass the headers to my conn.request it says HTTP Error 415, unsupported Media Type.

I have done quiet a bit of research on this topic and found out that the rest API might not be supporting the json reques, but Crucible says that there API supports json so seems to be some other issue,

2) when trying to pass the args generated using feauth the auth token is not getting used , for now I have appended it to url and it works.

Please help me with the same , below is my script

import httplib

import urllib

import json

from xml.etree.ElementTree import XML

import xml.dom.minidom

conn = httplib.HTTPSConnection("fisheye")

args=urllib.urlencode({'userName':'UNAME', 'password':'PWD'})

headers={'content-type':'application/json', 'accept':'application/json'}

#headers={'Authorization' : 'Basic %s' % base64.b64encode("username:password")}

r1 = conn.request("post", "/rest-service/auth-v1/login", args)

#status = r1\[u'headers'\]\['status'\]

#conn.connect()

r2 = conn.getresponse()

print r1,r2.status,r2.reason,r2

r3=r2.read()

print(r3)

r4=str(r3)

print r4

data = XML(r4).find("token").text

print data

# data1=urllib.quote_plus(data, safe=":")

# print data1

args=urllib.urlencode({'FEAUTH':data}).replace("%3A", ":")

print "args is", args

#args={}

req = conn.request("get","/rest-service/reviews-v1")

r3 = conn.getresponse()

status = r3.status

print "the url is"#, r3.getheader('Location')

url=r3.getheader('location', '')

print url

url1=r3.msg#.dict\['location'\]

print url1

#print req.url

#print req.get_method()

print dir(req) # list lots of other stuff in Request

print "after sending open review request"

print r3

print req,r3.status,r3.reason,r3

r4=r3.read()

print(r4)

r5=str(r4)

print r5

# json_ob=json.loads(r3.read())

# print json_ob


Answers:
author: Amit Pandey
body: Thanks for replying, I had already checked the above mentioned URL and was trying in same way but was still getting exception.

I was able to resolve the issues and here are answers for someone facing similar issues

1) changed the line headers={'Accept':'application/json'}

that is removed the content-type and sentence cased Accept

2)I was not able to pass the arguments to login request because it was a get request and so we need to append the values to URL and not try to pass it as argument.


author: LucasA
body: Hi Amit,

Have you checked this page?

- <https://developer.atlassian.com/display/FECRUDEV/Writing+a+REST+Client+in+Python>

It has a good example to performing REST calls on FishEye/Crucible. It may be used with JIRA as well -- you'll only need to change the request's URL.

I hope it helps!

Best regards,  
Lucas Timm

comments: author: Amit Pandey
body: Hi Lucas,

Thanks for replying, I had already checked the above mentioned URL and was trying in same way but was still getting exception.

I was able to resolve the issues and here are answers for someone facing similar issues

1) changed the line headers={'Accept':'application/json'}

that is removed the content-type and sentence cased Accept

2)I was not able to pass the arguments to login request because it was a get request and so we need to append the values to URL and not try to pass it as argument.


author: A
body: Hi Lucas, the code in that page doesn't work. Please check my comment


author: Prakash Subedi
body: `reviews = toList(json.loads(resp[u``'body'``])[u``'reviews'``],u``'reviewData'``) `  

line is giving error when executing example given on Lucas's link:

```
Traceback (most recent call last):  File "C:\crucible\fecru-3.2.4\content\api\rest_client_reivews.py", line 44, in &lt;module&gt;    reviews = toList(json.loads(resp[u'body'])[u'reviews'],u'reviewData')KeyError: u'reviews'
```

Any suggestion?


author: A
body: Based on Amit's code:

```
import httplibimport urllibimport jsonconn = httplib.HTTPConnection("codereview.site.optiver.com")args=urllib.urlencode({'userName':'myuser', 'password':'*****'})headers={'accept':'application/json'}conn.request("post", "/rest-service/auth-v1/login", args, headers)r = conn.getresponse()if r.status not in (200, 304):    raise Exception("Problems getting a token from codereview. %s %s" % (r.status, r))token = json.loads(r.read())["token"]token=urllib.urlencode({'FEAUTH':token}).replace("%3A", ":")req = conn.request("get","/rest-service-fecru/admin/repositories-v1/business_intelligence?%s" % token, None, headers)r3 = conn.getresponse()status = r3.statusjson_ob=json.loads(r3.read())print json_ob
```


author: Amit Pandey
body: After resolving the above mentioned problems I am now stuck at the next step , that is passing the auth token and json argument both to the rest API to create a review.

I am trying

```
data = json.dumps({  "reviewData" : {    "projectKey" : "EEU",    "name" : "Example review.",    "description" : "Test Description",    "author" : {      "userName" : "user",      "displayName" : "User User",      "avatarUrl" : "https://fisheye/avatar/user?s=48"    },    "moderator" : {      "userName" : "user",      "displayName" : "user user",      "avatarUrl" : "https://fisheye/avatar/user?s=48"    },    "creator" : {      "userName" : "user",      "displayName" : "user user",      "avatarUrl" : "https://fisheye/avatar/user?s=48"    },    "permaId" : {      "id" : "EEU-598"    },    "permaIdHistory" : [ "EEU-597" ],    "type" : "REVIEW",    "allowReviewersToJoin" : "false",    "metricsVersion" : "2",    "createDate" : "2013-03-11T15:38:54.046+1100",    "dueDate" : "2013-03-12T15:38:54.046+1100",    "jiraIssueKey" : ""  }})data1 = (data)args=urllib.urlencode({'FEAUTH':token}).replace("%3A", ":")req = conn.request("post","/rest-service/reviews-v1"+"?"+ args, data1, headers)
```

The above code snippet is the only change that has happened in the code provided in te question

comments: author: Amit Pandey
body: Adding the content type resolved the issue .

Content-Type: application/json


Tags: crucible-development