Confused on proper implementation of Flask blueprints and socketio - python

I have a Flask app that I have restructured to leverage blueprints. The application runs and everything seems to be going ok except for SocketIO and my socketio.on events. I never see SocketIO and the web socket attempt to connect or disconnect in Chrome debugger all it ever says is pending. I have checked the Flask SocketIO Chat example here, and got some ideas. I moved all my events back into my views.py. I can't seem to figure out why my sockio.on events are not getting called or firing off. Here is my code.
app.py
from factory import create_app
from flask.ext.socketio import SocketIO
app = create_app()
socketio = SocketIO(app)
factory.py
import logging
from logging.handlers import RotatingFileHandler
from flask import Flask
# from flask.ext.socketio import SocketIO
from flask.ext.login import LoginManager
import os
from celery import Celery
lm = LoginManager()
# socketio = SocketIO()
lm.login_view = 'main.login'
lm.session_protection = 'strong'
def create_app():
app = Flask(__name__)
app.clients = {}
app.config.from_object(os.environ.get('APP_CONFIG')) # export APP_CONFIG=settings.Development
lm.init_app(app)
from project.main import main as main_blueprint
app.register_blueprint(main_blueprint)
# socketio.init_app(app)
# print app.config['LOGPATH']
if not os.path.isdir(app.config['LOGPATH']):
print 'Log dir not found'
os.makedirs(app.config['LOGPATH'])
if not os.path.isdir(app.config['UPLOAD_FOLDER']):
print 'Upload dir not found'
os.makedirs(app.config['UPLOAD_FOLDER'])
# See Flask error handling for more info on logging
file_handler = RotatingFileHandler(app.config['LOGPATH'] + 'my.log', maxBytes=1024 * 1024 * 10, backupCount=20)
file_handler.setFormatter(logging.Formatter("%(asctime)s - %(name)s - %(levelname)s -%(module)s - %(lineno)d - %(message)s"))
app.logger.setLevel(logging.DEBUG)
app.logger.addHandler(file_handler)
app.logger.debug('Starting My Application')
# app.logger.debug(socketio)
return app
def make_celery(app=None):
app = app or create_app()
celery = Celery(app.import_name, broker=app.config['CELERY_BROKER_URL'])
# celery.conf.update(app.config)
celery.config_from_envvar('APP_CONFIG')
TaskBase = celery.Task
class ContextTask(TaskBase):
abstract = True
def __call__(self, *args, **kwargs):
with app.app_context():
return TaskBase.__call__(self, *args, **kwargs)
celery.Task = ContextTask
return celery
main/_init_.py
from flask import Blueprint
main = Blueprint('main', __name__, template_folder='templates', static_folder='static')
import views
# import events
main/views.py
from celery import chain
from flask import render_template, request, url_for, jsonify, current_app, session
from . import main
from flask.ext.socketio import emit, disconnect
from ..app import socketio
from flask.json import dumps
from werkzeug.utils import secure_filename, redirect
from flask.ext.login import login_required, login_user, logout_user
from uuid import uuid4
from project.tasks import *
#main.route('/')
# #login_required
def index():
event_count = 0
current_app.logger.debug('Loaded homepage')
current_app.logger.debug(socketio)
return render_template('index.html',
event_count=event_count,
http_id=session['http_id'])
# #login_required
#main.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
file = request.files['file']
websocket_session_id = request.form.get('session')
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(current_app.config['UPLOAD_FOLDER'], filename))
chain(
parse.s(filename, session['http_id']),
create_sphere.s(session['http_id'], websocket_session_id, url_for('main.event', _external=True))
)()
# parse.delay(filename, session['http_id'])
# (filename, session['http_id']),
# link=create_sphere.s(session['http_id'], websocket_session_id, url_for('main.event', _external=True))
# )
# parse.apply_async(chain)
return jsonify({'status': 'processing CSV'})
else:
return jsonify({'status': 'wrong file type'})
if request.method == 'GET':
return render_template('upload.html')
#main.route('/clients', methods=['GET'])
def clients():
return jsonify({'clients': current_app.clients.keys()})
#main.route('/event/', methods=['POST'])
def event():
print '\n'
print 'request =', request
print 'request.json =', request.json
current_app.logger.debug('task: {t}'.format(t=request.json['task']))
current_app.logger.debug('success: {s}'.format(s=request.json['success']))
websocket_id = request.json['websocket_id']
current_app.logger.debug(websocket_id)
if request.json['task'] == 'task_sphere' and request.json['success']:
current_app.logger.debug('successfully parsed CSV data')
current_app.logger.debug(request)
websocket_id = request.json['websocket_id']
http_id = request.json['http_id']
current_app.logger.debug(websocket_id)
current_app.logger.debug(http_id)
# try:
conn = pymongo.MongoClient(current_app.config['MONGO_URL'])
db = conn.events
collection = db['%s' % http_id]
current_app.logger.debug('Collection: {c}'.format(c=collection))
ns = current_app.clients.get(websocket_id)
if ns:
current_app.logger.debug(ns)
nodes = dumps(list(collection.find({'type' : 'node'})))
edges = dumps(list(collection.find({'type' : 'edge'})))
if nodes:
ns.emit('insert_nodes', nodes)
if edges:
ns.emit('insert_edges', edges)
# ns.emit('insert_data', dumps(list(collection.find())))
# return 'ok'
# except:
# print 'Could not connect to MongoDB: %s'
# return 'ok'
return 'ok'
# #lm.user_loader
# def load_user(username):
# u = main.config['USERS_COLLECTION'].find_one({"_id": username})
# if not u:
# return None
# return User(u['_id'])
#main.route('/login', methods=['GET', 'POST'])
def login():
error = None
if request.method == 'POST':
if request.form['username'] != 'admin' or request.form['password'] != 'admin':
error = 'Invalid Creds'
else:
session['logged_in'] = True
session['http_id'] = str(uuid4())
return redirect(url_for('main.login'))
return render_template('login.html', error=error)
#main.route('/logout')
#login_required
def logout():
logout_user()
return redirect(url_for('main.login'))
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in current_app.config['ALLOWED_EXTENSIONS']
##### Put events here for the time being #####
#socketio.on('status', namespace='/events')
def events_message(message):
current_app.logger.debug(message['status'])
print 'socketio.on: status'
emit('status', {'status': message['status']})
#socketio.on('disconnect request', namespace='/events')
def disconnect_request():
print 'socketio.on: disconnect request'
current_app.logger.debug('DISCONNECT REQUEST')
emit('status', {'status': 'Disconnected!'})
disconnect()
#socketio.on('connect', namespace='/events')
def events_connect():
print 'socketio.on: connect'
websocket_id = str(uuid4())
session['websocket_id'] = websocket_id
current_app.logger.debug(websocket_id)
current_app.clients[websocket_id] = request.namespace
emit('websocket_id', {'websocket_id': websocket_id})
#socketio.on('disconnect', namespace='/events')
def events_disconnect():
print 'socketio.on: diconnect'
current_app.logger.debug('DISCONNECT')
del current_app.clients[session['websocket_id']]
print('Client %s disconnected' % session['websocket_id'])
static/js/application.js
var namespace = '/events'; // change to an empty string to use the global namespace
var socket = io.connect('http://' + document.domain + ':' + location.port + namespace);
var jared;
var edges;
var nodes;
socket.on('connect', function () {
console.log('socketio: connect');
});
socket.on('disconnect', function () {
console.log('socketio: disconnect');
$('#websocket_id').text('not available');
});
socket.on('websocket_id', function (msg) {
console.log('updating html elements with correct session', msg.websocket_id);
$('input[name="session"]').val(msg.websocket_id);
$('#websocket_id').text(msg.websocket_id);
});
socket.on('insert_nodes', function (msg) {
//console.log(msg);
//jared = msg;
$('#myModal').modal('hide');
nodes = JSON.parse(msg);
console.log('here are the nodes', nodes);
var pcGeometry = new THREE.Geometry();
for (var i = 0; i < nodes.length; i++) {
var position = nodes[i].position;
//console.log(position);
vector = new THREE.Vector3(position.x, position.y, position.z);
//console.log(vector);
pcGeometry.vertices.push(vector);
}
//console.log(geometry);
pcMat = new THREE.PointCloudMaterial();
pcMat.size = 10;
pcMat.transparent = true;
pcMat.blending = THREE.AdditiveBlending;
pcMat.color = new THREE.Color(0x5555ff);
pc = new THREE.PointCloud(pcGeometry, pcMat);
pc.sizeAttenuation = true;
webGLScene.add(pc);
});
socket.on('insert_edges', function (msg) {
function getById(id, myArray) {
return myArray.filter(function (obj) {
if (obj._id.$oid == id) {
return obj
}
})[0]
}
edges = JSON.parse(msg);
console.log('here are the edges', edges);
var material = new THREE.LineBasicMaterial({
opacity: .3,
blending: THREE.AdditiveBlending,
transparent: true
});
//geometry.vertices.push(start);
for (var i = 0; i < edges.length; i++) {
var start = edges[i].start.$oid;
var start_pos = getById(start, nodes);
var start_vec = new THREE.Vector3(start_pos.position.x, start_pos.position.y, start_pos.position.z);
var end = edges[i].end.$oid;
var end_pos = getById(end, nodes);
var end_vec = new THREE.Vector3(end_pos.position.x, end_pos.position.y, end_pos.position.z);
var geometry = new THREE.Geometry();
geometry.vertices.push(start_vec);
geometry.vertices.push(end_vec);
var line = new THREE.Line(geometry, material);
webGLScene.add(line);
}
});
socket.on('status', function (msg) {
console.log('status', msg);
});

Related

Python multithread and share class object

My python program has several threads and they need to share (read and write) to the same object.
I am having problems, sometimes the value is stored correctly but other threads don't have it updated quick enough and only on a second or third interaction they have it updated.
this is my code:
from flask import Flask, render_template, request, jsonify
import threading
from time import sleep
from gpiozero import LED, Button, DigitalOutputDevice
SUM_ALARM_NC = LED(5)
SUM_ALARM_NO = LED(6)
SUM_ALARM_LED = LED(13)
SUM_ALARM_IN = Button(12)
from dataclasses import dataclass
import string
#dataclass
class Config_File:
status: string
serial_interface: string
changed:string
app = Flask(__name__, static_folder = 'assets')
#app.route("/")
def Index():
return render_template("index.html")
#app.route("/_monitoring")
def _monitoring():
return jsonify(_status = Config_File.status.strip(), _serial_interface = Config_File.serial_interface.strip())
#---------------------------------------------------------------------------------------------------------------
#app.route("/_saveserial")
def saveserial():
Config_File.changed = "1\n"
Config_File.serial_interface = str(request.args.get('RS232')) + "," + str(request.args.get('baudrate')) + "," + str(request.args.get('parity')) + "," + str(request.args.get('databit')) + "," + str(request.args.get('address')) + "\n"
return ""
def Monitoring_IO_thr():
while (True):
if SUM_ALARM_IN.is_pressed:
Config_File.changed = "0\n"
Config_File.status = "1\n"
SUM_ALARM_LED.on()
else:
Config_File.status = "0\n"
SUM_ALARM_LED.off()
sleep(0.5)
#### Save config_file class to the config.ini file ######################
def Save_Config_File_thr():
while (True):
if Config_File.changed == "1\n":
Config_File.changed = "0\n"
file_read = "config.ini"
fileobj = open(file_read,'r').readlines()
fileobj[3]= "Status:"+ Config_File.status
fileobj[21]= "Serial:" + Config_File.serial_interface
fileobj[55]= "Changed:" + Config_File.changed
# writes lines
with open(file_read,'w') as file:
file.writelines(fileobj)
file.close()
sleep(1)
if __name__ == "__main__":
Config_File.serial_interface="RS232,9600,Even,7,A\n"
Monitoring_IO_thread = threading.Thread(target = Monitoring_IO_thr)
Monitoring_IO_thread.start()
Save_Config_File_thread = threading.Thread(target = Save_Config_File_thr)
Save_Config_File_thread.start()
app.run(host='192.168.150.144', port=5050, debug=True)
Monitoring_IO_thread.join()
Save_Config_File_thread.join()
and this are my scripts
<script>
$(document).ready(function ()
{
$(function()
{
//SERIAL INTERFACE CHANGE - script to deal with the request to change the serial interface
$('#saveserial').on('click',function()
{
var data =
{
RS232: $('#RS232').val(),
baudrate: $('#baudrate').val(),
parity: $('#parity').val(),
databit: $('#databit').val(),
address: $('#address').val(),
};
$.getJSON("/_saveserial", data, function ()
{
});
});
});
$(function monitoring()
{
$.getJSON('/_monitoring', function(data)
{
if (data._status == "1")
{
$("#alarm_on").attr("hidden", false);
$("#alarm_off").attr("hidden", true);
}
if (data._status == "0")
{
$("#alarm_on").attr("hidden", true);
$("#alarm_off").attr("hidden", false);
}
setTimeout(function(){monitoring();},500);
});
}
);
});
</script>
How can I share Config_File between threads?
After your precious help I tried the following:
from multiprocessing import Process, Lock
mutex=Lock()
def Monitoring_IO_thr():
mutex.acquire()
try:
while(True):
Inputs_Monitoring()
sleep(0.5)
finally:
mutex.release()
def Save_Config_File_thr():
mutex.acquire()
try:
while(True):
if Config_File.changed == "1\n":
Config_File.serial_interface)
#save to file
Config_File.changed = "0\n"
Save_config()
out("saving config.ini")
sleep(1)
finally:
mutex.release()
if __name__ == "__main__":
Init()
app.run(host='192.168.150.144', port=5050, debug=True)
while(True):
Monitoring_IO_thread = threading.Thread(target = Monitoring_IO_thr)
Monitoring_IO_thread.start()
Save_Config_File_thread = threading.Thread(target = Save_Config_File_thr)
Save_Config_File_thread.start()
Not sure why but the program never runs both threads... any ideas what am I doing wrong?

Custom Python HP ILO Node Exporter not changing hostname by request

Im trying to edit this project in Python to have HP ILO exporter for Prometheus, so far I read a few articles here on stackoverflow and tried to implement some functionalities, eventually I came up to partialy working script but the hostname is not changing after first request, is there a way to dump collector?
I have tried it with try&except but it just does not work.
The goal is to use curl like this
curl localhost:9116/metrics?hostname=ip
And what will happen if there will be 10 requests at the same time with different hostname? Should it create somekind of a queue?
Can someone help me? Thanks
Original Project : https://github.com/JackWindows/ilo-exporter
My code :
#!/usr/bin/env python
import collections
import os
import time
import flask
import redfish
import waitress
from flask import Flask
from prometheus_client import make_wsgi_app
from prometheus_client.core import GaugeMetricFamily, REGISTRY
from werkzeug.middleware.dispatcher import DispatcherMiddleware
from flask import request
from time import sleep
from flask import Flask, Response, request
import traceback
from werkzeug.wsgi import ClosingIterator
class AfterResponse:
def __init__(self, app=None):
self.callbacks = []
if app:
self.init_app(app)
def __call__(self, callback):
self.callbacks.append(callback)
return callback
def init_app(self, app):
# install extension
app.after_response = self
# install middleware
app.wsgi_app = AfterResponseMiddleware(app.wsgi_app, self)
def flush(self):
for fn in self.callbacks:
try:
fn()
except Exception:
traceback.print_exc()
class AfterResponseMiddleware:
def __init__(self, application, after_response_ext):
self.application = application
self.after_response_ext = after_response_ext
def __call__(self, environ, after_response):
iterator = self.application(environ, after_response)
try:
return ClosingIterator(iterator, [self.after_response_ext.flush])
except Exception:
traceback.print_exc()
return iterator
class ILOCollector(object):
def __init__(self, hostname: str, port: int = 443, user: str = 'admin', password: str = 'password') -> None:
self.ilo = redfish.LegacyRestClient(base_url=hostname, username=user, password=password)
self.ilo.login()
system = self.ilo.get('/redfish/v1/Systems/1/').obj
self.label_names = ('hostname', 'product_name', 'sn')
self.label_values = (hostname, system.Model, system.SerialNumber.strip())
def collect(self):
embedded_media = self.ilo.get('/redfish/v1/Managers/1/EmbeddedMedia/').obj
smart_storage = self.ilo.get('/redfish/v1/Systems/1/SmartStorage/').obj
thermal = self.ilo.get('/redfish/v1/Chassis/1/Thermal/').obj
power = self.ilo.get('/redfish/v1/Chassis/1/Power/').obj
g = GaugeMetricFamily('hpilo_health',
'iLO health status, -1: Unknown, 0: OK, 1: Degraded, 2: Failed.',
labels=self.label_names + ('component',))
def status_to_code(status: str) -> int:
status = status.lower()
ret = -1
if status == 'ok':
ret = 0
elif status == 'warning':
ret = 1
elif status == 'failed':
ret = 2
return ret
g.add_metric(self.label_values + ('embedded_media',), status_to_code(embedded_media.Controller.Status.Health))
g.add_metric(self.label_values + ('smart_storage',), status_to_code(smart_storage.Status.Health))
for fan in thermal.Fans:
g.add_metric(self.label_values + (fan.FanName,), status_to_code(fan.Status.Health))
yield g
g = GaugeMetricFamily('hpilo_fan_speed', 'Fan speed in percentage.',
labels=self.label_names + ('fan',), unit='percentage')
for fan in thermal.Fans:
g.add_metric(self.label_values + (fan.FanName,), fan.CurrentReading)
yield g
sensors_by_unit = collections.defaultdict(list)
for sensor in thermal.Temperatures:
if sensor.Status.State.lower() != 'enabled':
continue
reading = sensor.CurrentReading
unit = sensor.Units
sensors_by_unit[unit].append((sensor.Name, reading))
for unit in sensors_by_unit:
g = GaugeMetricFamily('hpilo_temperature', 'Temperature sensors reading.',
labels=self.label_names + ('sensor',), unit=unit.lower())
for sensor_name, sensor_reading in sensors_by_unit[unit]:
g.add_metric(self.label_values + (sensor_name,), sensor_reading)
yield g
g = GaugeMetricFamily('hpilo_power_current', 'Current power consumption in Watts.', labels=self.label_names,
unit='watts')
g.add_metric(self.label_values, power.PowerConsumedWatts)
yield g
label_values = self.label_values + (str(power.PowerMetrics.IntervalInMin),)
g = GaugeMetricFamily('hpilo_power_average', 'Average power consumption in Watts.',
labels=self.label_names + ('IntervalInMin',), unit='watts')
g.add_metric(label_values, power.PowerMetrics.AverageConsumedWatts)
yield g
g = GaugeMetricFamily('hpilo_power_min', 'Min power consumption in Watts.',
labels=self.label_names + ('IntervalInMin',), unit='watts')
g.add_metric(label_values, power.PowerMetrics.MinConsumedWatts)
yield g
g = GaugeMetricFamily('hpilo_power_max', 'Max power consumption in Watts.',
labels=self.label_names + ('IntervalInMin',), unit='watts')
g.add_metric(label_values, power.PowerMetrics.MaxConsumedWatts)
yield g
# Create Flask app
app = Flask('iLO Exporter')
#app.route('/')
def root():
return '''<html>
<head><title>iLO Exporter</title></head>
<body>
<h1>iLO Exporter</h1>
<p><a href='/metrics'>Metrics</a></p>
</body>
</html>'''
AfterResponse(app)
#app.after_response
def say_hi():
print("hi")
#app.route("/metrics")
def home():
try:
REGISTRY.unregister(collector)
except:
print("An exception occurred")
pass
port = int(os.getenv('ILO_PORT', 443))
user = os.getenv('ILO_USER', 'admin')
password = os.getenv('ILO_PASSWORD', 'password')
hostname = request.args.get('hostname')
app.wsgi_app = DispatcherMiddleware(app.wsgi_app, {
'/metrics': make_wsgi_app()
})
collector = ILOCollector(hostname, port, user, password)
REGISTRY.register(collector)
if __name__ == '__main__':
exporter_port = int(os.getenv('LISTEN_PORT', 9116))
waitress.serve(app, host='0.0.0.0', port=exporter_port)

Why Flask pytest wont post data within app?

I'm trying to test the following app:
import os
import json
import pytest
from flask import Flask, request, jsonify
def create_app(test_config=None):
app = Flask(__name__, instance_relative_config=True)
if test_config is None:
app.config.from_pyfile('config.py', silent=True)
else:
app.config['TESTING'] = True
try:
os.makedirs(app.instance_path)
except OSError:
pass
#app.route('/predict', methods=['POST'])
def predict():
p = (request.get_json()) * 2
try:
return jsonify({'status': 200, 'message': 'ok', 'data': p})
except Exception as e:
return jsonify({'status': 400, 'message': str(e)}), 400
return app
#pytest.fixture
def client():
app = create_app()
app.config["TESTING"] = True
app.testing = True
with app.test_client() as client:
yield client
def test_predict(client):
response = client.post('/predict', data=json.dumps({'res': 3}))
data = json.loads(response.get_data(as_text=True))
assert response.status_code == 200
assert data['data'] == 6
When I'm running the following command:
pytest
Im getting the following error:
FAILED test_flask_testing.py::test_predict - TypeError: unsupported operand type(s) for *: 'NoneType' and 'int'
It seems like my post request won't pass data to the app, what's wrong with my post request?
Thanks in advance!
The data is being passed, but I don't understand what you are trying to do with this line:
p = (request.get_json()) * 2
Did two small changes, so the tests now are passing:
## -20,7 +20,7 ## def create_app(test_config=None):
#app.route('/predict', methods=['POST'])
def predict():
- p = (request.get_json()) * 2
+ p = request.get_data()
try:
return jsonify({'status': 200, 'message': 'ok', 'data': p})
except Exception as e:
## -42,4 +42,4 ## def test_predict(client):
response = client.post('/predict', data=json.dumps({'res': 3}))
data = json.loads(response.get_data(as_text=True))
assert response.status_code == 200
- assert data['data'] == 6
+ assert data['data'] == '{"res": 3}'
If you are trying to receive the incoming data as json, then you need to run the post like this:
response = client.post('/predict', json={'res': 3})
Then you need to parse as json:
#app.route('/predict', methods=['POST'])
def predict():
p = request.get_json()

Why database datas are being deleted after restarting flask server?

Recently, I have started flask. I found flask-sqlalchemy to work with flask. So I was using this. But I faced some problems. I am working on repl.it. When the repl goes assleep, I tried to use with the flask enabled website. But saw that no datas were showing. But before that I added a lot of datas. I can't figure out what is wrong but could you help me?
It may help you:
from flask_sqlalchemy import SQLAlchemy
import re
from flask import Flask, abort, jsonify, redirect, request
import os
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite3'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
class apikey(db.Model):
apikey = db.Column(db.String(25), primary_key=True, unique = True)
def __init__(self, apikey):
self.apikey = apikey
class shorturl(db.Model):
short_query = db.Column(db.String(15), primary_key=True, unique = True)
original = db.Column(db.String(1000))
visits = db.Column(db.Integer)
def __init__(self, short_query,original, visits):
self.short_query = short_query
self.original = original
self.visits = visits
def url_valid(url):
return re.match(regex, url) is not None
def bad_request(message):
response = jsonify({'message': message})
response.status_code = 400
return response
def errreq(message):
response = jsonify({'message': message})
response.status_code = 404
return response
#app.route('/')
def show_all():
return redirect("https://www.cburst.ml", code=301)
#app.route('/addapi', methods=['GET'])
def addapi():
if request.args.get('apikey') is not None:
api_key = request.args.get('apikey')
apiadd = apikey(apikey=api_key)
db.session.add(apiadd)
db.session.commit()
return jsonify({'message':"Done"}), 200
else:
return bad_request("Nothing Provided")
#app.route('/add', methods=['POST'])
def add():
if not request.json:
return bad_request('Url must be provided in json format.')
if "original" not in request.json :
return bad_request('Url parameter not found.')
if "short_query" not in request.json:
return bad_request('Url parameter not found.')
original = request.json['original']
short = request.json['short_query']
if shorturl.query.filter_by(short_query = short).first() is not None:
return bad_request("Already Exists")
visits = 0
if original[:4] != 'http':
original = 'http://' + original
if not url_valid(original):
return bad_request('Provided url is not valid.')
url_db = shorturl(
short_query=short, original=original, visits=visits)
shortened_url = short
db.session.add(url_db)
db.session.commit()
return jsonify({'link': shortened_url}), 201
#app.route('/add', methods=['GET'])
def add_get():
if request.args.get('apikey') is not None and request.args.get('original') is not None and request.args.get('short_query') is not None:
api_key = request.args.get('apikey')
original = request.args.get('original')
short_query = request.args.get('short_query')
if apikey.query.filter_by(apikey = api_key).first() is None:
return errreq("Invalid API Key")
else:
if shorturl.query.filter_by(short_query=short_query).first() is not None:
return errreq("Already Exists")
else:
if original[:4] != 'http':
original = 'http://' + original
if not url_valid(original):
return bad_request('Provided url is not valid.')
url_db = shorturl(
short_query=short_query, original=original, visits=0)
db.session.add(url_db)
db.session.commit()
return jsonify({'link': short_query}), 200
else:
return bad_request("Nothing Provided")
#app.route('/view/<alias>', methods=['GET'])
def get_viewcount(alias):
if shorturl.query.filter_by(short_query=alias).first() is None:
return bad_request('Unknown alias.')
else:
return jsonify({'visits':shorturl.query.filter_by(short_query=alias).first().visits}),200
#app.route('/<alias>', methods=['GET'])
def get_shortened(alias):
if shorturl.query.filter_by(short_query=alias).first() is None:
return bad_request('Unknown alias.')
visits = shorturl.query.filter_by(short_query=alias).first().visits
url_db = shorturl.query.filter_by(short_query=alias).first()
url_db.visits = visits + 1
db.session.commit()
url = shorturl.query.filter_by(short_query=alias).first().original
return redirect(url, code=302)
# From https://stackoverflow.com/questions/7160737/python-how-to-validate-a-url-in-python-malformed-or-not#7160778
# Slightly modified to not use ftp.
regex = re.compile(
r'^(?:http)s?://'
r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|'
r'localhost|'
r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'
r'(?::\d+)?'
r'(?:/?|[/?]\S+)$', re.IGNORECASE)
if __name__ == '__main__':
'''
if os.path.exists('./db.sqlite3'):
app.run(host="0.0.0.0", port=8000, debug=False)
else: '''
db.create_all()
app.run(host="0.0.0.0", port=8000, debug=False)
Here if I add api key in /appapi with key in query string, I can add the key in the database. But the key added in the database does not work after a couple of hours.
Thanks in advance.
I figured this out. It is because I have added db.create_all() inside the main function. Removing this just works.

Plaid API quickstart project error http://127.0.0.1:5000/get_access_token

I am trying to get started with the plaid API. I created my account to get the API keys and I have the quickstart project. I put my keys in the code(they are not applied in the code below) and when I run it I use the sandbox credentials. Unfortunately after the log in succeeds I always receive the same error when trying to receive the access token:
HTTP500: SERVER ERROR - The server encountered an unexpected condition
that prevented it from fulfilling the request.(XHR)POST -
http://127.0.0.1:5000/get_access_token
Here is the code:
import os
import datetime
import plaid
from flask import Flask
from flask import render_template
from flask import request
from flask import jsonify
app = Flask(__name__)
# Fill in your Plaid API keys - https://dashboard.plaid.com/account/keys
PLAID_CLIENT_ID = os.getenv('PLAID_CLIENT_ID')
PLAID_SECRET = os.getenv('PLAID_SECRET')
PLAID_PUBLIC_KEY = os.getenv('PLAID_PUBLIC_KEY')
# Use 'sandbox' to test with Plaid's Sandbox environment (username:
user_good,
# password: pass_good)
# Use `development` to test with live users and credentials and `production`
# to go live
PLAID_ENV = os.getenv('PLAID_ENV', 'sandbox')
client = plaid.Client(client_id = PLAID_CLIENT_ID, secret=PLAID_SECRET,
public_key=PLAID_PUBLIC_KEY, environment=PLAID_ENV)
#app.route("/")
def index():
return render_template('index.ejs', plaid_public_key=PLAID_PUBLIC_KEY,
plaid_environment=PLAID_ENV)
access_token = None
public_token = None
#app.route("/get_access_token", methods=['POST'])
def get_access_token():
global access_token
public_token = request.form['public_token']
exchange_response = client.Item.public_token.exchange(public_token)
print ('public token: ' + public_token)
print ('access token: ' + exchange_response['access_token'])
print ('item ID: ' + exchange_response['item_id'])
access_token = exchange_response['access_token']
return jsonify(exchange_response)
#app.route("/accounts", methods=['GET'])
def accounts():
global access_token
accounts = client.Auth.get(access_token)
return jsonify(accounts)
#app.route("/item", methods=['GET', 'POST'])
def item():
global access_token
item_response = client.Item.get(access_token)
institution_response = client.Institutions.get_by_id(item_response['item']
['institution_id'])
return jsonify({'item': item_response['item'], 'institution':
institution_response['institution']})
#app.route("/transactions", methods=['GET', 'POST'])
def transactions():
global access_token
# Pull transactions for the last 30 days
start_date = "{:%Y-%m-%d}".format(datetime.datetime.now() +
datetime.timedelta(-30))
end_date = "{:%Y-%m-%d}".format(datetime.datetime.now())
try:
response = client.Transactions.get(access_token, start_date, end_date)
return jsonify(response)
except plaid.errors.PlaidError as e:
return jsonify({'error': {'error_code': e.code, 'error_message':
str(e)}})
#app.route("/create_public_token", methods=['GET'])
def create_public_token():
global access_token
# Create a one-time use public_token for the Item. This public_token can
be used to
# initialize Link in update mode for the user.
response = client.Item.public_token.create(access_token)
return jsonify(response)
if __name__ == "__main__":
app.run(port=os.getenv('PORT', 5000))
Update your code like
PLAID_CLIENT_ID = 'client_id'
PLAID_SECRET = 'secret'
PLAID_PUBLIC_KEY = 'key'
PLAID_ENV = 'sandbox'
the problem was solved by putting the credentials to the client.py-file which is being created while you install plaid

Categories

Resources