Python: issue in displaying as a list httplib.HTTPMessage - python

I have a small problem here. So, I am writing some calls for a well known REST API. Everything is going well, except the fact that I want all the response to be displayed as a list(which is better for me to manipulate). My function is this:
import sys, httplib
HOST = "api.sugarsync.com"
API_URL = "https://api.sugarsync.com"
def do_request(xml_location):
request = open(xml_location,"r").read()
webservice = httplib.HTTPS(HOST)
webservice.putrequest("POST", "authorization", API_URL)
webservice.putheader("Host", HOST)
webservice.putheader("User-Agent","Python post")
webservice.putheader("Content-type", "application/xml")
webservice.putheader("Content-type", "application/xml")
webservice.putheader("Accept", "*/*")
webservice.putheader("Content-length", "%d" % len(request))
webservice.endheaders()
webservice.send(request)
statuscode, statusmessage, header = webservice.getreply()
result = webservice.getfile().read()
return statuscode, statusmessage, header
return result
do_request('C://Users/my_user/Documents/auth.xml')
I am used to use split() but in this case the result is this:
[201, 'Created', <httplib.HTTPMessage instance at 0x0000000001F68AC8>]
Well, I need also the third object(httplib.HTTPMessage instance at 0x0000000001F68AC8>), to be displayed as list, to extract some of the data in there.
Thanks in advance!

httplib.HTTPMessage is something like dict, here is a sample:
import httplib
from cStringIO import StringIO
h = httplib.HTTPMessage(StringIO(""))
h["Content-Type"] = "text/plain"
h["Content-Length"] = "1234"
print h.items()
you just call it's function items(), it will return a list of headers

Related

how can I call a function and pass params in a Python class?

I am attempting to use the Woo exchange trading api. They provided a snippet of code which is an impressive Python class structure. Copied below.
My question is how can I use it?
I have tried to run:
get_orders(self, 'BTCUSDT')
which throws an error "NameError: name 'self' is not defined"
and
get_orders('BTCUSDT')
which throws "TypeError: get_orders() missing 1 required positional argument: 'symbol'"
Here is the code (class structure) the kind woo guys provided:
import requests
import datetime
import time
import hmac
import hashlib
from collections import OrderedDict
#Application ID 9d4d96f6-3d3b-4430-966d-8733aa3dc3bc
#API Key
api_key = 'my_api_key'
#API Secret
api_secret = 'my_api_secret'
class Client():
def __init__(self, api_key=None, api_secret=None):
self.api_key = api_key
self.api_secret = api_secret
self.base_api = "https://api.woo.network/v1/"
def get_signature(self, params, timestamp):
query_string = '&'.join(["{}={}".format(k, v) for k, v in params.items()]) + f"|{timestamp}"
signature = hmac.new(
self.api_secret.encode('utf-8'),
query_string.encode('utf-8'),
hashlib.sha256
).hexdigest()
return signature
def get_orders(self, symbol):
url = self.base_api + "orders/"
params = {
"symbol": 'BTCUSDT'
}
params = OrderedDict(sorted(params.items()))
timestamp = str(int(time.time() * 1000))
signature = self.get_signature(params, timestamp)
headers = {
'Content-Type': "application/x-www-form-urlencoded",
'x-api-key': self.api_key,
'x-api-signature': signature,
'x-api-timestamp': timestamp,
'cache-control': 'no-cache'
}
resp = requests.get(url=url, params=params, headers=headers).json()
So, to repeat and summarize, when I write my own code to use this class, how can I call the function get_orders() and, more generally, reference the elements in the class structure? Thanks, in advance, for help.
Looks like you've truncated the code because get_orders doesn't appear to return anything.
However, you would start by constructing an instance of Client like this:
client = Client(api_key, api_secret)
...then...
client.get_orders(None)
That may look a little strange but get_orders requires one parameter but it's never used. I don't think the implementation of get_orders is quite how it was intended to be because it will always use BTCUSDT

Missing header error with Python requests but header defined

I am trying to create an ansible module using the python requests library, and the module runs without errors but returns the response
"{\n \"code\" : \"generic_err_missing_required_header\",\n \"message\" : \"Missing header: [X-chkp-sid]\"\n}"
even though the header appears to be correctly defined.
Module code below:
from ansible.module_utils.basic import AnsibleModule
import requests
def somefunction(sid):
url = '<someurl>'
headers = {
'Content-Type': 'application/json',
'X-chkp-sid': sid,
}
data = {
'type': 'tag'
}
response = requests.post(url,headers,data,verify=False,timeout=10)
return response.content
def main():
module_args = dict(
sid = dict(type='str', required=True)
)
result = dict(
changed=False,
original_message='',
message=''
)
module = AnsibleModule(
argument_spec=module_args,
supports_check_mode=True
)
if module.check_mode:
return result
sid = module.params['sid']
result=somefunction(sid)
module.exit_json(somefunction_output=result)
if __name__ == '__main__':
main()
I have gotten a successful response using the ansible uri module and identical header/body parameters. Any other ideas?
Most arguments to requests.post() should be keyword-style args instead of plain positional args.
Try this instead:
response = requests.post(url,data=data,headers=headers,verify=False,timeout=10)
somefunction() does not return anything, therefore the return value is None.
Perhaps you wanted return requests.post(url,headers,data,verify=False,timeout=10)?

python function for HTTP calls

I have a script that uses a dictionary stored in "my_dict" variable, and values of url, user, password, along with the "id" variable. The script then does an HTTP GET call to the url depending on headers passed. How do I create a Python Function which is equivalent to this? And how to the function later for another set of url, user, password etc?
import urllib, urllib2, base64, json
my_dict = {'server': {'user': 'patrick', 'url': 'http://192.168.0.1/tasks', 'password': 'secret'}}
id = "8d4lkf8kjhla8EnsdAjkjFjkdb6lklne"
for value in my_dict.keys():
url = my_dict[value]['url']
pass = my_dict[value]['password']
authKey = base64.b64encode("patrick:"+str(pass))
headers = {"login-session": id, "Content-Type": "application/json", "Authorization": "Basic " + authKey}
data = {"param": "value"}
request = urllib2.Request(url)
for key, value in headers.items():
request.add_header(key, value)
response = json.load(urllib2.urlopen(request))
print response
Your question has a lot of subquestions such as what do you want variable or constant? Do you know the syntax? How your function will be used? etc etc.
Therefore the best way for you to get an answer is learn some basics, like here (free) for the functions syntax in python. After that you may very well have the answers to your question.
A simple function like this will work if I understood you correctly,
def send_request(my_dict, id):
for value in my_dict.keys():
url = my_dict[value]['url']
pass = my_dict[value]['password']
authKey = base64.b64encode("patrick:"+str(pass))
headers = {"login-session": id, "Content-Type": "application/json", "Authorization": "Basic " + authKey}
data = {"param": "value"}
request = urllib2.Request(url)
for key, value in headers.items():
request.add_header(key, value)
response = json.load(urllib2.urlopen(request))
print response

Python POST with urlencoded multidimensional dictionary

I have many functions that successfully POST a urlencoded body using python. However, I have a body that is a multidimensional dictionary. Using this dictionary, I only get a 400 (bad request). bodytmp (below) is an example of the body that works using Fiddler. (The actual url and body can not be supplied.) I have also included a recursive urlencode function that I found here and am using now but with no success.
Does anyone have experience with this type of POST request with a multidimensional dictionary for the urlencoded body?
Thank you. ( I have abbreviated the code to make it more readable, but this is the gist. )
from httplib2 import Http
import httplib
import urllib
def postAgentRegister():
h = Http(disable_ssl_certificate_validation=True)
headers={'Content-Type':'application/x-www-form-urlencoded'}
bodytmp={"Username": "username",
"Password": "password",
"AccountId": "accountid",
"PublicKey": {
"Value1a": "32ab45cd",
"value1b": "10001"
},
"snId": "SN1",
"IpAddresses": {
"Value2a": ["50.156.54.45"],
"Value2b": "null"
}
}
body=recursive_urlencode(bodytmp)
try:
response,content=h.request('https://server/endpoint','POST',headers=headers,body=body)
conn = httplib.HTTPConnection(testserver)
conn.request('POST', endpoint, body, headers)
r1 = conn.getresponse()
status = r1.status
reason = r1.reason
except httplib.HTTPException, e:
status= e.code
print 'status is: ', status
def recursive_urlencode(d):
def recursion(d, base=None):
pairs = []
for key, value in d.items():
if hasattr(value, 'values'):
pairs += recursion(value, key)
else:
new_pair = None
if base:
new_pair = "%s[%s]=%s" % (base, urllib.quote(unicode(key)), urllib.quote(unicode(value)))
else:
new_pair = "%s=%s" % (urllib.quote(unicode(key)), urllib.quote(unicode(value)))
pairs.append(new_pair)
return pairs
return '&'.join(recursion(d))
Might I suggest that you serialize your body to JSON and de-serialize when your server receives it? This way you just have to do a url string encode rather than using your own recursive url encode.

Authentication Required - Problems Establishing AIM OSCAR Session using Python

I'm writing a simple python script that will interface with the AIM servers using the OSCAR protocol. It includes a somewhat complex handshake protocol. You essentially have to send a GET request to a specific URL, receive XML or JSON encoded reply, extract a special session token and secret key, then generate a response using the token and the key.
I tried to follow these steps to a tee, but the process fails in the last one. Here is my code:
class simpleOSCAR:
def __init__(self, username, password):
self.username = username
self.password = password
self.open_aim_key = 'whatever'
self.client_name = 'blah blah blah'
self.client_version = 'yadda yadda yadda'
def authenticate(self):
# STEP 1
url = 'https://api.screenname.aol.com/auth/clientLogin?f=json'
data = urllib.urlencode( [
('k', self.open_aim_key),
('s', self.username),
('pwd', self.password),
('clientVersion', self.client_version),
('clientName', self.client_name)]
)
response = urllib2.urlopen(url, data)
json_response = simplejson.loads(urllib.unquote(response.read()))
session_secret = json_response['response']['data']['sessionSecret']
host_time = json_response['response']['data']['hostTime']
self.token = json_response['response']['data']['token']['a']
# STEP 2
self.session_key = base64.b64encode(hmac.new(self.password, session_secret, sha256).digest())
#STEP 3
uri = "http://api.oscar.aol.com/aim/startOSCARSession?"
data = urllib.urlencode([
('a', self.token),
('clientName', self.client_name),
('clientVersion', self.client_version),
('f', 'json'),
('k', self.open_aim_key),
('ts', host_time),
]
)
urldata = uri+data
hashdata = "GET&" + urllib.quote("http://api.oscar.aol.com/aim/startOSCARSession?") + data
digest = base64.b64encode(hmac.new(self.session_key, hashdata, sha256).digest())
urldata = urldata + "&sig_sha256=" + digest
print urldata + "\n"
response = urllib2.urlopen(urldata)
json_response = urllib.unquote(response.read())
print json_response
if __name__ == '__main__':
so = simpleOSCAR("aimscreenname", "somepassword")
so.authenticate()
I get the following response from the server:
{ "response" : {
"statusCode":401,
"statusText":"Authentication Required. statusDetailCode 1014",
"statusDetailCode":1014,
"data":{
"ts":1235878395
}
}
}
I tried troubleshooting it in various ways, but the URL's I generate look the same as the ones shown in the signon flow example. And yet, it fails.
Any idea what I'm doing wrong here? Am I hashing the values wrong? Am I encoding something improperly? Is my session timing out?
Try using Twisted's OSCAR support instead of writing your own? It hasn't seen a lot of maintenance, but I believe it works.
URI Encode your digest?
-moxford

Categories

Resources