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.
Related
I am trying to create an error handler in my Flask API such that when an empty body is sent in a post request, the response should generate a jsonified 400 error message and give the status code as 400 Bad Request on Postman. But currently I am getting 400 error message in the response body and 500 status code on Postman
[1]: https://i.stack.imgur.com/DV1BX.png
import pyodbc
from pytz import timezone
from flask import Flask, jsonify, request, Response
from datetime import datetime, timedelta
from waitress import serve
from flask_api import status
app = Flask(__name__)
server = 'bla'
database = 'bla'
username = 'bla'
password = 'bla'
driver = '{ODBC Driver 18 for SQL Server}'
connection_string = 'DRIVER='+driver+';SERVER=tcp:'+server + \
';PORT=bla;DATABASE='+database+';UID='+username+';PWD=' + password
def hello(data):
try:
if data["url"] == "":
return jsonify({"message": "Error Code : 404 - Not found"}), status.HTTP_404_NOT_FOUND
Headers = {"Content-Type": "application/json",
"Authorization": "Bearer " + access_token}
resp = requests.post(
data["url"], json=bla, headers=Headers)
if resp.status_code == 200:
values = resp.json()["value"]
{perform some operation here}
return filtered_values, status.HTTP_200_OK
else:
return resp.json()["error"]["message"],resp.status_code
except Exception as e:
print("Error", e)
raise
#app.route("/")
def status():
return jsonify({"status": "OK"}), status.HTTP_200_OK
#app.errorhandler(404)
def not_found(e):
return jsonify({"message": str(e)}), status.HTTP_404_NOT_FOUND
#app.route("/somepath", methods=["GET", "POST"])
def details():
if request.method == "POST":
try:
operation_data = request.get_json()
data, code = hello(operation_data )
if code != 200:
return jsonify({"message": str(data)}), code
else:
if len(data) != 0 and data is not None:
conn = pyodbc.connect(connection_string)
cursor = conn.cursor()
for d in data:
cursor.execute(some query)
conn.commit()
cursor.close()
conn.close()
new_resp = jsonify({"message": "successful"})
return new_resp, status.HTTP_200_OK
else:
new_resp = jsonify({"message": "nothing to do"})
return new_resp, status.HTTP_200_OK
except Exception as exception:
print(exception)
return jsonify(str(exception)), status.HTTP_500_INTERNAL_SERVER_ERROR
else:
return jsonify({"status": str(request.method) + " - Method not allowed"}),status.HTTP_405_METHOD_NOT_ALLOWED
if __name__ == "__main__":
app.run(host='0.0.0.0', port=8000, debug=True)
# serve(app, listen='*:8000')```
I've been working on trying to edit a webhook that was originally meant to be used for a weather API to get to be used with a postcode/zipcode API. The original file is here: https://github.com/dialogflow/fulfillment-webhook-weather-python/blob/master/app.py
I can't understand where mine is different, I thought I had solved it when I replaced urlencode with quote but alas, it wasn't enough.
The problem is very unlikely to do with the source json request that collects the postcode in postcodeValue(). The api url comes out correct when you enter it into a browser and is presented quite simply.
https://api.getaddress.io/find/SW11%201th?api-key=I98umgPiu02GEMmHdmfg3w12959
Is it in the correct format? Maybe I need to convert it to become even more JSON then it already is. This question is essentially an end of day brain dump that I I'm hoping that someone can save me with.
from __future__ import print_function
from future.standard_library import install_aliases
install_aliases()
from urllib.parse import urlparse, urlencode, quote
from urllib.request import urlopen, Request
from urllib.error import HTTPError
import json
import os
from flask import Flask
from flask import request
from flask import make_response
# Flask app should start in global layout
app = Flask(__name__)
#this line is just naming conventions I reckon with a reference to expect to receive data as POST
#app.route('/webhook', methods=['POST'])
def webhook():
req = request.get_json(silent=True, force=True)
#who knows where this is getting printed
print("Request:")
print(json.dumps(req, indent=4))
res = processRequest(req)
res = json.dumps(res, indent=4)
# print(res)
r = make_response(res)
r.headers['Content-Type'] = 'application/json'
return r
def processRequest(req):
if req.get("result").get("action") != "yahooWeatherForecast":
return {}
baseurl = "https://api.getaddress.io/find/"
apikey = "?api-key=I98umgPiu02GEMmHdmfg3w12959"
yql_query = postcodeValue(req)
if yql_query is None:
return {}
#this line is the actual api request
yql_url = baseurl + quote(yql_query) + apikey
result = urlopen(yql_url).read()
data = json.loads(result)
res = makeWebhookResult(data)
return res
#this function extracts an individual parameter and turns it into a string
def postcodeValue(req):
result = req.get("result")
parameters = result.get("parameters")
postcode = parameters.get("postcode")
if postcode is None:
return None
return postcode
#def housenoValue(req):
# result = req.get("result")
#parameters = result.get("parameters")
#houseno = parameters.get("houseno")
#if houseno is None:
# return None
#return houseno
def makeWebhookResult(data):
longitude = data.get("longitude")
if longitude is None:
return {}
#def makeWebhookResult(data):
# query = data.get('query')
# if query is None:
# return {}
# result = query.get('results')
# if result is None:
# return {}
# channel = result.get('channel')
# if channel is None:
# return {}
# item = channel.get('item')
# location = channel.get('location')
# units = channel.get('units')
# if (location is None) or (item is None) or (units is None):
# return {}
# condition = item.get('condition')
# if condition is None:
# return {}
# print(json.dumps(item, indent=4))
speech = "Sausage face " + longitude
print("Response:")
print(speech)
return {
"speech": speech,
"displayText": speech,
# "data": data,
# "contextOut": [],
"source": "apiai-weather-webhook-sample"
}
#More flask specific stuff
if __name__ == '__main__':
port = int(os.getenv('PORT', 5000))
print("Starting app on port %d" % port)
app.run(debug=False, port=port, host='0.0.0.0')
Here is a bit cleaner version of your code:
from urllib.request import urlopen
import os
from flask import Flask
app = Flask(__name__)
#app.route('/webhook', methods=['GET'])
def webhook():
res = processRequest()
return res
def processRequest():
try:
result = urlopen("https://api.getaddress.io/find/SW11%201th?api-key=I98umgPiu02GEMmHdmfg3w12959").read()
return result
except:
return "Error fetching data"
if __name__ == '__main__':
port = int(os.getenv('PORT', 5000))
print("Starting app on port %d" % port)
app.run(debug=False, port=port, host='0.0.0.0')
Open your browser and go to http://localhost:5000/webhook and you should see a response.
I'm trying to get my targets from vuforia's API, but I can't pass the last value of the header "Authorization" which is an encoded data, the error that I'm getting is this:
Unicode-objects must be encoded before hashing
this is in try snippet of the code, I'm following the vuforia's documentation but still, something is wrong with my code and I don't have a clue what it is
import base64
import hashlib
import hmac
import requests
from flask import Flask, request
from email.utils import formatdate
import logging
app = Flask(__name__)
#app.route('/')
def hello_world():
try:
import http.client as http_client
except ImportError:
# Python 2
import httplib as http_client
http_client.HTTPConnection.debuglevel = 1
logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True
url = 'https://vws.vuforia.com/targets'
req = requests.Request('GET', url)
req.headers = setHeaders(req)
resp = requests.Session().send(req.prepare())
return resp.text
def compute_md5_hex(data):
"""Return the hex MD5 of the data"""
h = hashlib.md5()
h.update(data)
return h.hexdigest()
def compute_hmac_base64(key, data):
"""Return the Base64 encoded HMAC-SHA1 using the provide key"""
h = hmac.new(key, None, hashlib.sha1)
h.update(data)
return base64.b64encode(h.digest())
def setHeaders(request):
date = formatdate(None, localtime=False, usegmt=True)
accessKey = "ce1500fhfth429279173fd839f9d414532014a3da"
secret_key = b"5d3fdawd7211447c35be607ae5a08ec794a09d71d"
headers = {'Date': date, 'Authorization': "VWS " + accessKey + ":" + tmsSignature(request, secret_key)}
return headers
def tmsSignature(request, secretKey):
method = request.method
contentType = ""
hexDigest = "d41d8cd98f00b204e9800998ecf8427e"
if method == "GET" or method == "POST":
pass
# Do nothing because the strings are already set correctly
elif method == "POST" or method == "PUT":
contentType = "application/json"
# If this is a POST or PUT the request should have a request body
hexDigest = compute_md5_hex(request)
else:
print("ERROR: Invalid content type passed to Sig Builder")
# Date in the header and date used to calculate the hash must be the same
dateValue = formatdate(None, localtime=False, usegmt=True)
requestPath = str(request.url)
components_to_sign = list()
components_to_sign.append(method)
components_to_sign.append(str(hexDigest))
components_to_sign.append(str(contentType))
components_to_sign.append(str(dateValue))
components_to_sign.append(str(requestPath))
string_to_sign = "\n".join(components_to_sign)
shaHashed = ""
try:
shaHashed = compute_hmac_base64(secretKey, string_to_sign)
except Exception as e:
print("ERROR ", e)
return shaHashed
if __name__ == '__main__':
app.run()
Looking into your hmac_base64_key function, this particular call is the cause:
h.update(data)
Since that is the update function from the hmac library, that requires the input to be byte instead of string/unicode (check out the documentation on hmac which refers to hashlib for its update signature).
So it seems like the fix is simply:
h.update(data.encode("utf8")) # or other encoding you want to use
Note that you'll need to change the return value of compute_hmac_base64 (shaHashed) to string again since you're concatenating it with a string in setHeaders.
(I'm assuming a Python 3 code even though you have a check for Python 2 in your code by the way, since you've tagged this Python 3).
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.
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.