I have 2 possible errors that I could get in my use case: 'RSA key format is not supported' for incorrect passphrase and 'PEM encryption format not supported.' for required passphrase but none given. These are both ValueError type.
I'm trying to do this in try-except
from flask import Flask, url_for, request, json, jsonify
from Crypto.PublicKey import RSA
app = Flask(__name__)
#app.route('/key2pub', methods = ['POST'])
def api_keypub():
if request.headers['Content-Type'] == 'application/json':
resp = None
try:
pubkey = RSA.importKey(request.json['key'], request.json['passphrase'])
except ValueError as e:
if e == 'RSA key format is not supported':
global resp
resp = jsonify({"error": "Incorrect passphrase", "raw": e})
elif e == 'PEM encryption format not supported.':
global resp
resp = jsonify({"error": "Passphrase missing", "raw": e})
return resp
if __name__ == '__main__':
app.run(debug=True);
I'm getting the error:
...
ValueError: View function did not return a response
So it seems that resp is not getting set in the except if statement.
I suspect I'm using try-except in the wrong manner, can someone show me the correct way to do this?
You write to a global resp while you actually have a local one. So the global resp will be set, but your local resp which is set to None will not be changed, therefore you will return None. So if you remove the global resp declaration should it work correctly. Maybe also set a default resp in case its another error which you would miss. So something like the following
resp = None
try:
pubkey = RSA.importKey(request.json['key'], request.json['passphrase'])
except ValueError as e:
if str(e) == 'RSA key format is not supported':
resp = jsonify({"error": "Incorrect passphrase", "raw": str(e)})
elif str(e) == 'PEM encryption format not supported.':
resp = jsonify({"error": "Passphrase missing", "raw": str(e)})
else:
resp = jsonify({"error": "Unexpected error", "raw": str(e)})
return resp
api_keypub is your innermost context here: resp is local to that context. Using global isn't going to help.
On top of that, you need to indent your if statement to be part of the except clause.
Related
I'm using python3 requests module to access Github v3 API (DELETE /user/keys/:key_id) of the deleting public ssh-key that it return the error
{'message': 'Not Found''documentation_url':'https://developer.github.com/v3'}.
I use python3 virtual environmemt and requests module to handle.
I checked the URL and method of the api and it has no problem. In addition, I added access_token='My token' after the URL parameter. but no effect. i try to use command
curl -H "Authorization: token 93ca7d685602dca9d32e8788ddffafc8e7385003" https://api.github.com/users/codertocat -I to find the scope of the token.
and I checked that the the key_id is correct also.
def __init__(self):
self.accessToken = '93ca7d685602dca9d32e8788ddffafc8e7385003'
self.rootUrl = 'https://api.github.com'
self.headers = {"Authorization": "token %s" % self.accessToken}
def baseGet(self, url, me='get', data=None):
try:
response = ''
if me == 'get':
response = requests.get(url)
if me == 'post':
response = requests.get(url, data)
if me == 'delete':
response = requests.delete(url)
else:
print('no support')
try:
data = response.json()
except:
data = response.content
return data
except Exception as e:
print('error by', e)
return False
def del_user_public_key(self, key_id):
# del_user_public_key
userkey = self.rootUrl + '/users/keys/%d?access_token=%s' % (key_id, self.accessToken)
print(userkey)
return self.baseGet(userkey, me='delete')
I expect the output of the result to be Status 204 No Content and the public deleted in github.
I am calling an API. While making requests I hit the maximum number of tries and I get a connection error. I would like to edit the url programmatically by incrementing the number in the url. I do know how to change the arguments programmatically but not sure how to change/increment an argument when I hit connection error.
My language of usage is Python and I am using requests library.
Code Snippet
Libraries importing
from requests.auth import HTTPBasicAuth
import requests
from requests.exceptions import ConnectionError
```def make_request(data , id=None):
url = "http://server001.net:8080/?id="
result = {}
if id:
response = requests.get(url +id , auth=HTTPBasicAuth('uname', 'pass'))
return response
else :
for line in data:
try:
response = requests.get(url +line , auth=HTTPBasicAuth('uname', 'pass'))
result = html_parser2(response)
if result:
write_csv(result)
else:
pass
except ConnectionError as e:
print (e)```
Expected output
url = "http://server001.net:8080/?id="
url_edited = "http://server002.net:8080/?id="
Only if I hit the maximum number of tries, i.e I get an exception or
else keep requesting the same url.
One of the options is to enclose the try..except block with a while loop.
Besides, may be you should put your first requests.get into try..except block too.
Also try to avoid multiple unrelated operations in one try..except block, i.e. execute write_csv after successful connection only.
def make_request(data , id=None):
url = 'http://server001.net:8080/?id={}'
connection_failed = False
response = None
if id:
try:
response = requests.get(url.format(id) , auth=HTTPBasicAuth('uname', 'pass'))
except ConnectionError as e:
print('id = {}, e: {}'.format(id, e))
else:
for line in data:
while not connection_failed:
try:
response = requests.get(url.format(line) , auth=HTTPBasicAuth('uname', 'pass'))
except ConnectionError as e:
connection_failed = True
print('line = {}, e: {}'.format(id, e))
else:
result = html_parser2(response)
if result:
write_csv(result)
return response
def make_request(data , id=None):
url = 'http://server001.net:8080/?id={}'
response = None
if id:
try:
response = requests.get(url.format(id) , auth=HTTPBasicAuth('uname', 'pass'))
except ConnectionError as e:
print('id = {}, e: {}'.format(id, e))
else:
for line in data:
try:
response = requests.get(url.format(line) , auth=HTTPBasicAuth('uname', 'pass'))
except ConnectionError as e:
print('line = {}, e: {}'.format(id, e))
else:
result = html_parser2(response)
if result:
write_csv(result)
break
return response
I've been trying for hours, and I just don't know what I'm doing wrongly. It's just for planning/research (not performant) -- playing around with some code from github -- but I need to see it functional.
RPC_USER = username
RPC_PASS = pasword
rpc_id = ID HERE
jsonrpc = "2.0"
payload = {"jsonrpc": jsonrpc, "id": rpc_id, "method": method, "params": params}
authstr = base64.encodestring(bytes('%s:%s' % (RPC_USER, RPC_PASS), 'utf-8')).strip()
request_headers = {"Authorization": "Basic %s" % authstr, 'content-type': 'application/json'}
try:
response = requests.get(RPC_URL, headers = request_headers, data = json.dumps(payload)).json()
print(response['result'])
except Exception as e: print(str(e))
if response['id'] != rpc_id:
raise ValueError("invalid response id!")
I get an error as follows:
Here's the whole traceback:
Expecting value: line 1 column 1 (char 0) # prints the Exception
Traceback (most recent call last):
File "miner_2017.py", line 411, in <module>
solo_miner(bin2hex("------coinbase message here -----"), "-----bitcoin address here-----")
File "miner_2017.py", line 401, in solo_miner
mined_block, hps = block_mine(rpc_getblocktemplate(), coinbase_message, 0, address, timeout=60)
File "miner_2017.py", line 63, in rpc_getblocktemplate
try: return rpc("getblocktemplate", [{}])
File "miner_2017.py", line 52, in rpc
if response['id'] != rpc_id:
UnboundLocalError: local variable 'response' referenced before assignment
Which after doing some looking seems to be a problem with decoding the json object from a bytes object rather than a string object. I don't know how to fix this. It seems the "response" variable assignment was unsuccessful due to the json problem. How can I get the json object in string form from the request?
Would somebody help me out? Thanks
#!/usr/bin/env python
import getpass
import json
import requests
def instruct_wallet(method, params):
url = "http://127.0.0.1:8332/"
payload = json.dumps({"method": method, "params": params})
headers = {'content-type': "application/json", 'cache-control': "no-cache"}
try:
response = requests.request("POST", url, data=payload, headers=headers, auth=(rpc_user, rpc_password))
return json.loads(response.text)
except requests.exceptions.RequestException as e:
print e
except:
print 'No response from Wallet, check Bitcoin is running on this machine'
rpc_user='foo'
rpc_password='bar'
passphrase = getpass.getpass('Enter your wallet passphrase: ')
timeout = raw_input('Unlock for how many seconds: ')
answer = instruct_wallet('walletpassphrase', [passphrase, timeout])
if answer['error'] != None:
print answer['error']
else:
print answer['result']
I'm using something similar for Altcoins
import decimal
import itertools
import json
import requests
id_counter = itertools.count()
class BTCJsonRPC(object):
def __init__(self, url, user, passwd, log, method=None, timeout=30):
self.url = url
self._user = user
self._passwd = passwd
self._method_name = method
self._timeout = timeout
self._log = log
def __getattr__(self, method_name):
return BTCJsonRPC(self.url, self._user, self._passwd, self._log, method_name, timeout=self._timeout)
def __call__(self, *args):
# rpc json call
playload = json.dumps({'jsonrpc': '2.0', 'id': next(id_counter), "method": self._method_name, "params": args})
headers = {'Content-type': 'application/json'}
resp = None
try:
resp = requests.post(self.url, headers=headers, data=playload, timeout=self._timeout,
auth=(self._user, self._passwd))
resp = resp.json(parse_float=decimal.Decimal)
except Exception as e:
error_msg = resp.text if resp is not None else e
msg = u"{} {}:[{}] \n {}".format('post', self._method_name, args, error_msg)
self._log.error(msg)
return
if resp.get('error') is not None:
e = resp['error']
self._log.error('{}:[{}]\n {}:{}'.format(self._method_name, args, e['code'], e['message']))
return None
elif 'result' not in resp:
self._log.error('[{}]:[{}]\n MISSING JSON-RPC RESULT'.format(self._method_name, args, ))
return None
return resp['result']
I'm pretty sure you just need to change from using a GET to a POST, i.e.:
change
response = requests.get(RPC_URL, headers = request_headers, data = json.dumps(payload)).json()
to
response = requests.post(RPC_URL, headers=request_headers, data=json.dumps(payload)).json()
In fact, when I tried this with GET (without dumping the response to json), I got a 405 response. You should always take a look at your response object before doing further debugging with it.
from flask import Flask, session, render_template, request, redirect, url_for
from urllib2 import Request, urlopen, HTTPError
from json import dump
import json
def checkLogin():
data = {}
data['login'] = request.form['login']
data['password'] = request.form['password']
headers = {'Content-Type': 'application/json'}
jsonData = json.dumps(data)
myRequest = Request("http://edi.iem.pw.edu.pl....", data=jsonData,
headers=headers)
try:
myResponse = urlopen(myRequest)
myResponseDict = json.load(myResponse)
if myResponse.getCode() == 200 and myResponseDict['info'] == 'OK':
session['token'] = myResponseDict['token']
session['uid'] = myResponseDict['uid']
else:
myResponseDict['error']
except HTTPError as e:
print e.code
print e.reason
return e.read()
I get error: "AttributeError: addinfourl instance has no attribute 'getCode'"
I check if it work when I write method "getCode" without brackets but it doesn't work.
In similar topic I didn't got the answer so I have question what can I do in this case?
I have just change from upper "C" to lower "c" in getcode() although PyCharm prompted me to getCode() method.
def do_request(url, token, json_data=None,
mode="get", work_around_for_image_custom_list=False):
"""Uploads a file. """
header_collection = {"X-Auth-Token": token}
if json_data is not None:
header_collection['Content-Type'] = 'application/json'
try:
if mode == "delete":
# this looks ugly, but there is absolutely no way to
# get requests to do DELETE when there is a blank JSON
# included
r = requests.delete(url, headers=header_collection, timeout=10)
else:
r = getattr(requests, mode)(url, data=json.dumps(json_data),
headers=header_collection, timeout=10)
if r.status_code == 200:
#This looks ugly also, but has to be for a particular function that calls it
if work_around_for_image_custom_list:
return r
else:
http_info = (json.dumps(r.json(), indent=2), r.status_code)
else:
http_info = (r.text, r.status_code)
return http_info
except requests.exceptions.ConnectionError:
print "Connection Error! Http status Code {}".format(r.status_code)
sys.exit()
except (requests.exceptions.RequestException,
requests.exceptions.HTTPError):
print "Ambiguous Error! Http status Code {}".format(r.status_code)
sys.exit()
Using Python 2.7 and the requests module, I have this function that I call with several other functions to make api calls. However, I have to make an exception for one particular function and return the request object...if work_around_for_image_custom_list is True. This seems seems like a ugly hack/work around and I am wondering how I could re-write it to compensate if work_around_for_image_custom_list. For instance, would it be better to make this a class and have each function create a object to use it? If so, how would I over ride if r.status_code == 200:?
Expanding on the comment I made:
def do_raw_request(url, token, json_data=None, mode="get"):
"""Uploads a file. """
header_collection = {"X-Auth-Token": token}
if json_data is not None:
header_collection['Content-Type'] = 'application/json'
try:
if mode == "delete":
# this looks ugly, but there is absolutely no way to
# get requests to do DELETE when there is a blank JSON
# included
r = requests.delete(url, headers=header_collection, timeout=10)
else:
r = getattr(requests, mode)(url, data=json.dumps(json_data),
headers=header_collection, timeout=10)
if r.status_code == 200:
return r, r.status_code
return r.text, r.status_code
except requests.exceptions.ConnectionError:
print "Connection Error! Http status Code {}".format(r.status_code)
sys.exit()
except (requests.exceptions.RequestException,
requests.exceptions.HTTPError):
print "Ambiguous Error! Http status Code {}".format(r.status_code)
sys.exit()
Then:
def do_request(url, token, json_data=None, mode="get"):
res, code = do_raw_request(url, token, json_data, mode)
if code == 200:
return (json.dumps(r.json(), indent=2), r.status_code)
return res, code
and now you call either do_raw_request or do_request as appropriate.
Note that I changed the return so it always returns a tuple otherwise you would have to start checking types to know whether you have a status text or a response object.