I want to limit IP connection to a server (currently implemented locally).
Here is my code
from flask import Flask, request
from flask.ext.cors import CORS, cross_origin
import time
import redis
from flask.ext.limiter.extension import Limiter
from flask.ext.limiter.util import get_ipaddr
app = Flask(__name__)
cors=CORS(app)
limiter = Limiter(
app,
key_func=get_ipaddr,
global_limits=[str(LIMITPERDAY) + " per day", str(LIMITPERMINUTE) + " per minute"],
storage_uri ="redis://127.0.0.1:6379",
#strategy="moving-window",
headers_enabled=True
)
#app.errorhandler(429)
def ratelimit_handler(e):
return "Ratelimit exceeded : " + e.description, 429
if __name__ == '__main__':
app.run(host="0.0.0.0",port=10005,threaded=True )
If I comment out the strategy part, when I connect to the server using curl or plain html, I keep getting error 500: Internal Server Error. When I comment out the strategy, the code can work. However from what I read in
http://flask-limiter.readthedocs.org/en/latest/#flask_limiter.Limiter
I need to use "moving-window" to connect to redis, otherwise it's "fixed-window" by default. I really don't know what's wrong with my code.
I run redis-server on Windows 10. I run my Flask on cygwin-64.
Thanks!
After I activate the debug, I found out the error is
File "C:\Users\lita\Anaconda2\lib\site-packages\redis\connection.py", line 582, in read_response
raise response
ResponseError: unknown command 'EVALSHA'
I check on https://github.com/nvie/rq/issues/398 and it's because Redis >= 2.6.0 is required. After I upgrade my Redis, the problem is solved.
Related
I developed a web application with Python and Flask.
I have to limit the rate of access based on visitor's IPs, that is, how many times the same IP can access the same webpage in a given time, and for that I am using flask-limiter.
Here is my full code:
from flask import Flask
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
app = Flask(__name__)
limiter = Limiter(app, key_func=get_remote_address, default_limits=['300/day'], enabled=True)
counter = 0
#app.route('/')
#limiter.limit('200/day')
#limiter.limit('50/hour')
#limiter.limit('10/minute')
def hello_world():
global counter
counter = counter + 1
return f'Hello World! Visit number: {counter}'
if __name__ == '__main__':
app.run()
It is not working properly on the server (Cloudlinux + Litespeed); it ends-up generating a "time out" error frequently, but not always (a kind of intermittent error).
If I disable flask-limiter by setting enabled=False, then everything works fine.
What wrong I am doing? Any alternative?
It was possible to fix the problem by setting storage_uri to use "redis", and activating redis in my web hosting account.
This is how to implement Flask-Limiter with redis:
limiter = Limiter(app, key_func=get_remote_address, storage_uri="redis://localhost:6379")
The 6379 is the default port for redis.
More info at:
https://flask-limiter.readthedocs.io/en/latest/#configuring-a-storage-backend
When a user logs into my flask app it does not work first time, but it typically works on the second attempt. The following error occurs on the first login attempt:
MismatchingStateError: mismatching_state: CSRF Warning! State not equal in request and response
I did not have this problem when running on localhost on a windows PC. I obtained this problem when moving my code to a linode running ubuntu 20.04. I am considering flask in python3 as well as the following packages.
from flask import Flask
from flask import jsonify
from flask import redirect
from flask import render_template
from flask import session
from flask import url_for
from flask import request
from flask import send_from_directory
from authlib.integrations.flask_client import OAuth
My keys are fixed in a .env file. They are not randomly generated.
oauth = OAuth(app)
auth0 = oauth.register(
'auth0',
client_id=AUTH0_CLIENT_ID,
client_secret=AUTH0_CLIENT_SECRET,
api_base_url=AUTH0_BASE_URL,
access_token_url=AUTH0_BASE_URL + '/oauth/token',
authorize_url=AUTH0_BASE_URL + '/authorize',
client_kwargs={
'scope': 'openid profile email',
},
)
The following code in the callback handling gives the CSRF error.
#app.route('/callback')
def callback_handling():
auth0.authorize_access_token()
resp = auth0.get('userinfo')
I may have solved this question by updating my ntp on linux with the help of the following link:
https://askubuntu.com/questions/254826/how-to-force-a-clock-update-using-ntp
apt-get install -y ntp
sudo service ntp stop
sudo ntpd -gq
sudo service ntp start
I also added a try except in my python server
try:
auth0.authorize_access_token()
resp = auth0.get('userinfo')
userinfo = resp.json()
session[constants.JWT_PAYLOAD] = userinfo
session[constants.PROFILE_KEY] = {
'user_id': userinfo['sub'],
'name': userinfo['name'],
'picture': userinfo['picture'],
'email_verified':userinfo['email_verified']
}
except:
return redirect("/mainpage")
#Some code
return redirect('mainpage')
Ensure that the 'mainpage' requires authorisation.
I have a python script with flask incorporated running on a RaspberryPi. This is set to trigger a wakeonlan script when IFTTT sends the appropriate POST webhook. Since I've turned it on I've been getting a LOT of random webhooks from random IPs. Obviously, they all get a 404 error as nothing else is active, but it still concerns me a bit.
Is there a way to make flask ignore (just completely not respond) to any webhooks that aren't the specific one (a POST to /post) I'm looking for? I've tried screwing with the return line, but then flask throws an error saying "View function did not return a response" and returns an error 500.
Is this even possible?
#!/usr/bin/env python3
from flask import Flask, request
from wakeonlan import send_magic_packet
from datetime import datetime
app = Flask(__name__)
dt = datetime.now()
print("WakeOnLan started at: ", dt)
#app.route('/post', methods= ["POST"])
def post():
print("POST received at: ", dt)
body = request.get_data(as_text=True)
if body == "desktop":
send_magic_packet('XX.XX.XX.XX.XX.XX')
print("Magic Packet sent to", body, "at:", dt)
return ''
#Router forwards port 80 to 30000 on the pi
app.run(host='0.0.0.0', port = 30000)
I'm not getting the proper response for this particular API. Also , In actual implementation, I'm getting the proper 200 jsonify response when all things are running fine but if their is any exception and If I want to send back the response with 500 status code : the postman say Could not get response : "Error: read ECONNRESET" and in my console it display as "127.0.0.1 - - [04/Aug/2020 23:57:22] "←[37mPOST /hi HTTP/1.1←[0m" 500 -"
can someone please tell me , where I'm going wrong ?
from flask import Flask, jsonify, request, abort, json
from werkzeug.utils import secure_filename
from werkzeug.exceptions import HTTPException
from flask_cors import CORS, cross_origin
import traceback
app = Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'
#app.route("/hi", methods=['POST'])
def hi():
val = 500
dict_json = {"messgae": "lets work it out {} ".format(val)}
return jsonify(dict_json), val
I had this problem today and found that it seems to be an issue with the flask server. It works fine usually however sometimes requests with postman would time out with the error you've mentioned.
Can you try hosting it instead with waitress?
To do that add this to the top of your file
from waitress import serve
then instead of running app.run() you run serve(app, host='localhost', port=7777)
oh, and for waitress to work you will of course need to run pip install waitress first!
i follow the tutorial based on a service i wan't to use ( Drone Deploy) :
https://dronedeploy.gitbooks.io/dronedeploy-apps/content/server_example.html
i made a topic on their forum for this issue 2 days ago.( and repo on Github)
But maybe someone can help me here.
I got an issue with an Heroku server app i do.
i use Python and the Tornado module.
The fact is i got a 404 error
My terminal ( when test it localy ) ask me :
"WARNING:tornado.access:404 GET / (::1) 0.75ms"
so the "GET" function is not working , maybe because of HTTP access control (CORS) i try many fix , but none worked.
Maybe i made something wrong ,or forgot something.
update :
Recently someone of the Drone deploy said my tornado routes aren't being picked up by heroku.
After following many tutorial and read the Tornado documentation i have no idea how to routes this.
the url of the server : https://stardrone-server.herokuapp.com/
this the code :
import os
import requests
import tornado.ioloop
import tornado.web
GEOCODE_FMT = 'https://maps.googleapis.com/maps/api/geocode/json?address={address}&key={key}'
class GeocodeHandler(tornado.web.RequestHandler):
"""Proxy a call to the Google Maps geocode API"""
def set_default_headers(self):
# allow cross-origin requests to be made from your app on DroneDeploy to your web server
self.set_header("Access-Control-Allow-Origin", "https://www.dronedeploy.com")
self.set_header("Access-Control-Allow-Headers", "x-requested-with")
# add more allowed methods when adding more handlers (POST, PUT, etc.)
self.set_header("Access-Control-Allow-Methods", "GET, OPTIONS")
def get(self):
api_key = os.environ.get("MyApiKey")
address = self.get_query_argument("address")
url = GEOCODE_FMT.format(address=address, key=api_key)
# fetch results of the geocode from Google
response = requests.get(url)
# send the results back to the client
self.write(response.content)
def options(self):
# no body
self.set_status(204)
self.finish()
def main():
application = tornado.web.Application([
(r"/geocode/", GeocodeHandler)
])
port = int(os.environ.get("PORT", 5000))
application.listen(port)
tornado.ioloop.IOLoop.current().start()
if __name__ == "__main__":
main()
Maybe i missed something.
Any help, advices are appreciated
Thanks
John