I believe I have the same problem as described here: Flask-Limiter does not work with Flask-Restful API-based application. But I still can't get it to work. Here's my problem:
I have an app.py where I import all my REST-API endpoints. I use flask-RESTful resources as described in this guide: https://flask-restful.readthedocs.io/en/latest/quickstart.html
I use the "Flask-Limiter" library for rate limiting: https://flask-limiter.readthedocs.io/en/stable/. The rate-limiter gets instantiated in a separate file, not inside app.py because this would create circular references between app.py and the REST-API endpoints. I think this could be the cause of my problem.
This is the rate-limiter file (located in: /controller/helpers/rate_limiter.py)
from flask import current_app
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
limiter = Limiter(
current_app,
key_func=get_remote_address
)
This is the app.py file (located in: /):
from flask import Flask
from flask_restful import Api
from controller.actions.my_endpoint import MyEndpoint
flask_app = Flask(__name__)
api = Api(flask_app)
api.add_resource(MyEndpoint, '/endpoint')
flask_app.run(debug=True, use_reloader=True, host='0.0.0.0', port=8000)
And finally this is an example of an endpoint (located in: /controller/actions/my_endpoint):
from flask_restful import reqparse, Resource
from controller.helpers.rate_limiter import limiter
class MyEndpoint(Resource):
decorators = [limiter.limit("1/minute", methods=["POST"])]
def __init__(self):
self.parser = reqparse.RequestParser()
self.parser.add_argument(
"someData", type=int, nullable=False, required=True)
def post(self):
data = self.parser.parse_args(strict=True)
someData = data.someData
return "Got your message {0}".format(someData), 200
I would expect that after the first request I would get response 429 because the rate limit of 1/minute is reached but it doesn't do that.
However, when I instantiate the limiter inside app.py and set a default rate-limit, it works (getting that error 429):
from flask import Flask
from flask_restful import Api
from controller.db_actions.my_endpoint import MyEndpoint
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
flask_app = Flask(__name__)
limiter = Limiter(
flask_app,
key_func=get_remote_address,
default_limits=["1 per minute"]
)
api = Api(flask_app)
api.add_resource(MyEndpoint, '/endpoint')
flask_app.run(debug=True, use_reloader=True, host='0.0.0.0', port=8000)
Question: I think I'm doing something wrong with instantiating the limiter. What is it? :)
Related
im was working with my flask app on my development server, but now i want to move that same application to a production enviroment. The thing is that when i was running that same application with flask run, i got the lazy loading message so i move to waitress in order to avoid this behaviour. When i use waitress the message dissapears but the behaviour is the same. The app is slow at the first request and then works properly.
Bellow you can find part of my code :
import flask
import io
import string
import time
import os
from flask import Flask, jsonify, request
import load_model
import prepare_image
from flask_cors import CORS
from waitress import serve
from paste.translogger import TransLogger
app = Flask(__name__)
#control archivo mayor a 16 mb
app.config['MAX_CONTENT_LENGTH'] = 4096 * 4096
cors = CORS(app, resources={r"/*": {"origins": "*"}})
#app.route('/predict', methods=['POST'])
blablabla
if __name__ == '__main__':
serve(TransLogger(app, setup_console_handler=False),port=5000)
Thanks in advance
when the app is served with weitress the lazy loading mode doesnt seem to disappear.
I've already read much about it on stack overflow but now I'm struggling with an issue and don't know how to fix it.
My main.py looks like the following:
from flask import Flask, jsonify, request
from flask_pymongo import PyMongo
from bson.objectid import ObjectId
from flask_cors import CORS
app = Flask(__name__)
# connect to LiTags database
app.config["MONGO_URI"] = "mongodb://localhost:27017/LiTags"
mongo = PyMongo(app)
CORS(app)
if __name__ == "__main__":
app.run(debug=True)
then I seperated some database requests (MongoDB) in another file(requests.py). I know that it's not necessary right now because there are not that much requests right now but there will be more after I fixed this problem.
So this is my requests.py:
from main import app, mongo
from flask import Flask, jsonify, request, Blueprint
from flask_pymongo import PyMongo
from bson.objectid import ObjectId
#app.route("/", methods=["GET"])
def getProjects():
result = []
projects = mongo.db.literature
for field in projects.find():
result.append(
{"_id": str(field["_id"]), "project_name": field["project_name"]})
return jsonify(result)
this is generally my frontend (ReactJS) request to flask:
// get project names from the backend
getProjects() {
axios.get(`http://127.0.0.1:5000/`)
.then(res => {
this.setState({ projects: res.data });
})
}
before I seperated the requests in requests.py from the main.py my program worked but now I get an error in the inspect tool in the browser which says:
"GET http://127.0.0.1:5000/ 404 (NOT FOUND)
Error: Request failed with status code 404
at createError (createError.js:17)
at settle (settle.js:19)
at XMLHttpRequest.handleLoad (xhr.js:63)"
In main.py you would have to import requests.py
from requests import *
because main.py doesn't know that you have code in other file .
But there can be problem with circular imports - main.py has to import requests.py but requests.py aready imports main.py and it makes problem.
You may have to split main in two files:
main.py - which doesn't need code from reuqests so it doesn't have to import it
from flask import Flask, jsonify, request
from flask_pymongo import PyMongo
from bson.objectid import ObjectId
from flask_cors import CORS
app = Flask(__name__)
# connect to LiTags database
app.config["MONGO_URI"] = "mongodb://localhost:27017/LiTags"
mongo = PyMongo(app)
CORS(app)
run.py - which needs code from requests (but requests doesn't import it)
from main import *
#from main import app
from requests import *
#from models import *
#from views import *
#from admin import *
if __name__ == "__main__":
app.run(debug=True)
and now you would have to use run.py instead of main.py to start server.
python run.py
BTW: most people and tutorials/documentations use name views.py instead of requests.py for file with code which use #app.route. Eventaully I would use name api.py because these views return JSON data like in many APIs.
I want to keep track of metrics in my flask application using the lib prometheus_flask_exporter.
For what i could understand this lib already tracks default metrics in the /metrics endpoint.
But when i try to access the http://localhost:5000/metrics I get 404 Not Found.
So i tried to set a histogram metric on the user_list, but i get the same 404 not Found when i try to access the http://localhost:5000/metrics
init.py:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flasgger import Swagger
from flask_caching import Cache
from prometheus_flask_exporter import PrometheusMetrics
app = Flask(__name__)
app.debug = True
app.config.from_object('dev_maintenance.yaml_config_loader')
cache = Cache(app)
db = SQLAlchemy(app)
swagger = Swagger(app)
metrics = PrometheusMetrics(app)
import dev_maintenance.mesos_callback
import dev_maintenance.db_model
import dev_maintenance.active_directory
import dev_maintenance.user_list
import dev_maintenance.audit
import dev_maintenance.machines
import dev_maintenance.yaml_config_loader
import dev_maintenance.roles
import dev_maintenance.user_details
if __name__ == '__main__':
app.run(debug=True)
user_list.py
from dev_maintenance import app
from flask import jsonify, request
from flask_simpleldap import LDAP
from flask_jwt_extended import jwt_required
from dev_maintenance import metrics
ldap = LDAP(app)
#app.route('/api/user', methods=['GET'])
#metrics.do_not_track()
#metrics.histogram('requests_by_status_and_path', 'Request latencies by status and path',
labels={'status': lambda r: r.status_code, 'path': lambda: request.path})
def user_list():
user_list = []
users = ldap.get_group_members('ship_crew')
for user in users:
user_list.append(str(user, encoding='utf-8').split(",")[0].split("=")[1])
return jsonify(user_list)
Do i need to create a /metrics route? Because in the git documentation does not say anything about that, so i suppose this is already set behind the scenes.
Instead of "app.run(debug=True)" use "app.run(debug=False)". debug=True was breaking things.
From:https://github.com/rycus86/prometheus_flask_exporter/blob/master/README.md
Please note, that changes being live-reloaded, when running the Flask app with debug=True, are not going to be reflected in the metrics. See https://github.com/rycus86/prometheus_flask_exporter/issues/4 for more details.
Alternatively - since version 0.5.1 - if you set the DEBUG_METRICS environment variable, you will get metrics for the latest reloaded code. These will be exported on the main Flask app. Serving the metrics on a different port is not going to work most probably - e.g. PrometheusMetrics.start_http_server(..) is not expected to work.
I have a python file which defines some endpoints using flask each doing some computation and return a JSON (POST method). I want to do unit testing on this in order to do this I want to be able to access the app I created in one python file in another file so I can test my endpoints.
I see a lot of this on the internet :
from source.api import app
from unittest import TestCase
class TestIntegrations(TestCase):
def setUp(self):
self.app = app.test_client()
def test_thing(self):
response = self.app.get('/')
assert <make your assertion here>
It doesn't explain how I can define and access my app in another file. This might be a stupid question but I really don't see how.
My app is defined as follows:
from flasgger import Swagger
from flask import Flask, jsonify, request
from flask_cors import CORS
import os
def init_deserializer_restful_api():
# Initiate the Flask app
app = Flask(__name__)
Swagger(app)
CORS(app)
# Handler for deserializer
#app.route("/deserialize", methods=['POST'])
def handle_deserialization_request():
pass
I have many other end points in this fashion. Should i just do:
import my_file_name
Thanks!!
Check out this question: What does if __name__ == "__main__": do?
As long as you have that in your python program, you can both treat it as a module and you can call it directly.
I have created a flask application and am hosting it on a Ubuntu server. I know that my apache config is correct since I am able serve the example flask application. However, this one seems to be giving me trouble. The code is below:
from flask import Flask, render_template, request, url_for
import pickle
import engine
import config
# Initialize the Flask application
app = Flask(__name__)
model = pickle.load(open(config.MODEL_PATH, "rb"))
collection = engine.Collection(config.DATABASE_PATH)
search_engine = engine.SearchEngine(model, collection)
#app.route('/')
def form():
return render_template('index.html')
#app.route('/search/', methods=['POST'])
def search():
query = request.form['query']
results = search_engine.query(query)
return render_template('form_action.html', query=query, results=results)
#app.route('/retrieve/<int:item_number>', methods=['GET'])
def retrieve(item_number):
item = engine.Product(item_number, collection.open_document(str(item_number)))
return render_template('document.html', item=item)
if __name__ == '__main__':
app.run()
When running the file directly through the python interpreter, it works fine and I can access. However, when starting through apache and wsgi, I get no response from the server. It just hangs when making a request and nothing is available on the logs.
I suspect that my issue may have something to do with the three objects I initialize at the beginning of the program. Perhaps it gets stuck running those?
Update: I have tried commenting out certain parts of the code to see what is causing it to stall. Tracing it out to the engine module, importing NearestNeighbors seems to be causing the issue.
import sqlite3
import config
from sklearn.neighbors import NearestNeighbors
from preprocessor import preprocess_document
from collections import namedtuple