I've been trying to send data from flask over socket io. I need to access this data from a different origin, but it is giving a CORS error. I have tried using all kinds of cross origin stuff and none of it has worked. Can somebody help with this.
The view that should be called thought socket io:
from flask.ext.cors import cross_origin
#socketio.on('increment',namespace="/api")
#cross_origin()
def increment(message):
number += 1;
emit('number',{'data':number},broadcast=True)
Running the server:
app = Flask(__name__)
cors = CORS(app,resources={r"/api/*":{"origins":"*"}})
socketio = SocketIO(app)
app.debug = True
app.host = '0.0.0.0'
socketio.run(app)
I solved by following:
socketio = SocketIO(app, cors_allowed_origins="*")
For some reason, cors_allowed_origins="*" did not work for me. I had to instead specify the full address of the origin as the following:
socketio = SocketIO(app, cors_allowed_origins=['http://127.0.0.1:5500'])
The error message that says "<client_address> is not an accepted origin. (further occurrences of this error will be logged with level info)" should indicate which address you should be typing in.
I had a similar issue, got it working with this setup:
#you may not need all these options
from flask import Flask, render_template, request
from flask.ext.socketio import SocketIO, emit, join_room, leave_room
from flask.ext.cors import CORS
app = Flask(__name__, template_folder='./', static_folder='./', static_url_path='')
app.config['SECRET_KEY'] = 'some-super-secret-key'
app.config['DEFAULT_PARSERS'] = [
'flask.ext.api.parsers.JSONParser',
'flask.ext.api.parsers.URLEncodedParser',
'flask.ext.api.parsers.FormParser',
'flask.ext.api.parsers.MultiPartParser'
]
cors = CORS(app,resources={r"/*":{"origins":"*"}})
socketio = SocketIO(app)
socketio.run(app,port=5000,host='0.0.0.0')
You can set up routes as such:
#app.route("/")
def indexRoute():
return render_template('index.html',version=VER)
And socket requests:
#socketio.on('connect',namespace="/home")
def test_connect():
print "client connected:",rooms()[0]
On the client side in JS i did the following:
var socket = io.connect('http://' + location.hostname + ':5000/home');
socket.on('connect',function(data) {
console.log('connected to socket');
});
Also, take a look at this snippet from Flask developers.
Check that you are using the supported version of socket.io in your html file.
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.0.4/socket.io.js" integrity="sha512-aMGMvNYu8Ue4G+fHa359jcPb1u+ytAF+P2SCb+PxrjCdO3n3ZTxJ30zuH39rimUggmTwmh2u7wvQsDTHESnmfQ==" crossorigin="anonymous"></script>
Related
I have a flask app running on localhost:5000:
from flask import Flask
app = Flask(__name__)
#app.route("/api")
def parse():
return {"test": "json"}
if __name__ == "__main__":
# for production change debug to False
app.run(debug=True)
And on the front end I'm fetching the data here:
useEffect(() => {
fetch("http://localhost:5000/api")
.then((res) => res.json())
.then((data: Data) => {
setData(data);
console.log(data);
});
}, []);
When I try and fetch the data from my react-app I get this error in the console:
I've seen a bunch of answers to similar questions, but all the other questions were more complicated than mine and I don't know what to add to my flask app since mine is pretty bare bones.
Luckly it's pretty simple to solve it. All you need to do is to install flask-CORS with pip install flask-cors and then add an CORS header on your app, like this:
from flask_cors import CORS
from flask import Flask
app = Flask(__name__)
CORS(app)
#app.route("/api")
def parse():
return {"test": "json"}
if __name__ == "__main__":
# for production change debug to False
app.run(debug=True)
For more information, visit flask-cors documentation
#app.route("/", methods=["GET"])
def get_example():
"""GET in server"""
response = jsonify(message="Simple server is running")
# Enable Access-Control-Allow-Origin
response.headers.add("Access-Control-Allow-Origin", "*")
return response
or
I built a very simple flask app that uses socketIo in order to make a simple chatapp, where you can write messages.
In my js file i built a function that every few seconds sends the current location of the user using geolocation.
Because im using the geolocation, i need my to use https instead of http that the flask created.
I found out about SSLify and tried it, but because im using also the socketIo it ran on http and not on https. In apps without socketIo it works, what is the problem?
this is my flask app:
from flask import Flask, render_template
from flask_socketio import SocketIO
from flask_sslify import SSLify
app = Flask(__name__)
app.config['SECRET_KEY'] = 'jsbcfsbfjefebw237u3gdbdc'
socketio = SocketIO(app)
sslify = SSLify(app)
#app.route('/')
def index():
return render_template('./ChatApp.html')
def messageRecived():
print('message was received!!!')
#socketio.on('my event')
def handle_my_custom_event(json):
print('recived my event: ' + str(json))
socketio.emit('my response', json, callback=messageRecived)
if __name__ == '__main__':
socketio.run(app, debug=True, host='0.0.0.0')
The reason it does not work is that Flask-SSLify is applied to your Flask application (the app instance), and not to Socket.IO (the socketio instance).
To my knowledge there is no equivalent to Flask-SSLify for the Socket.IO server, so you will need to either build it yourself as a WSGI middleware, or else implement the HTTP to HTTPS redirection in a reverse proxy that sits above your Python server, such as nginx or Apache.
I'm trying to understand how sessions work in flask_session extension. I have server-side code:
from flask import Flask, session
from flask_session import Session
from flask_socketio import SocketIO
app = Flask(__name__)
app.config['SECRET_KEY'] = 'top-secret!'
app.config['SESSION_TYPE'] = 'filesystem'
Session(app)
socketio = SocketIO(app, manage_session=False)
#socketio.on('get-session')
def get_session():
print(session.get('value', 'NO'))
#socketio.on('set-session')
def set_session(data):
session['value'] = data
print(session.get('value', 'NO'))
if __name__ == '__main__':
socketio.run(app)
and client:
from socketIO_client import SocketIO
with SocketIO('localhost', 5000) as socketio:
socketio.emit('set-session', '3')
socketio.emit('get-session')
I get following output on server:
3
NO
But i want to get:
3
3
I can't understand why session variable is not preserved. Would appreciate any help.
UPD: execution of the above code results in two different files in \flask_session directory
When I run my local application with flask-socketio I can access session using from flask import session, but when I run it with gunicorn on server (gunicorn --worker-class eventlet -w 1 app:app) it return me session.keys() as Array[0].
How could I fix it to establish this local-proxy with session on server?
Thanks
from flask import Flask, render_template, session, request
from flask_socketio import SocketIO, emit
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
#app.before_request
def before_request():
session['key_1'] = 'Hello,'
session['key_2'] = 'World'
#app.route('/')
def index():
return render_template('index.html')
#socketio.on('connect', namespace='/')
def socket_connect():
session_keys = session.keys()
emit('connect response', {
'session_keys': session_keys
})
#socketio.on('disconnect', namespace='/')
def socket_disconnect():
print('Client disconnected', request.sid)
if __name__ == '__main__':
socketio.run(app)
I found a solution.
Session was dissapearing and could not be shared to socketio, because I added redirect page rules on cloudflare for my domain.
When I changed Forwarding type of all rules to 302 - Temporary everything worked well.
My python app does not throw any errors on Google App Engine, but the Allow-Control-Access-Origin header is never sent. How can I ensure that I am sending it with flask-cors?
import MySQLdb
import os
import webapp2
import json
import flask
from flask import Flask, jsonify, render_template, request
from flask.ext.cors import CORS, cross_origin
app = Flask(__name__)
#app.route('/')
#cross_origin()
def do_search():
if (os.getenv('SERVER_SOFTWARE') and
os.getenv('SERVER_SOFTWARE').startswith('Google App Engine/')):
db = MySQLdb.connect(unix_socket='/cloudsql/my-instance-name:storeaddressdb', db='store_locator', user='myuser', passwd='password')
else:
db = MySQLdb.connect(host='localhost', user='root')
cursor = db.cursor()
query = 'SELECT * FROM stores WHERE 1 LIMIT 5'
cursor.execute(query)
resp = jsonify(data=cursor.fetchall())
return resp
db.close()
It appears that this code actually does work, although I do not see the Allow-Control-Access-Origin header when I use cURL to test the url. The logs in Google App Engine show CORS selectively adding the header unless the client specifically skipped it. Also, the Javascript client is no longer showing an error, and receives the data. It may not be the prettiest python code, but it is functionally correct for my purposes.