I need help in debugging -the Same Origin Policy disallows reading the remote resource at https://some-domain.com. (Reason: CORS request did not succeed) in python flask-socketio error.
I am working on a chat application using python flask-socketio. In previously I have created that application in local and it works fine as expected, while I move the below code to the server it shows the above error. The client code runs in the https servers and server code also runs on the https server I don't know why that error shows.
I have attached my code below and please give a better solution to me.
server.py
import json
import os
from flask import Flask, render_template, request,session
from flask_socketio import SocketIO, send, emit
from datetime import timedelta,datetime
from flask_cors import CORS
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secretkey'
app.config['DEBUG'] = True
app.config['CORS_HEADERS'] = 'Content-Type'
cors = CORS(app, resources={r"/*": {"origins": "*"}})
socketio = SocketIO(app)
users = {}
#app.before_request
def make_session_permanent():
session.permanent = True
app.permanent_session_lifetime = timedelta(minutes=1)
#app.route('/')
##cross_origin(origin='*',headers=['Content- Type','Authorization'])
def index():
return render_template('index.html')
#socketio.on('connect')
def connect():
print("connected");
#app.route('/orginate')
def orginate():
socketio.emit('server orginated', 'Something happened on the server!')
return '<h1>Sent!</h1>'
#socketio.on('username')
def receive_username(username):
users[username] = request.sid
#users.append({username : request.sid})
#print(users)
emit('userList', users, broadcast=True)
print('Username added!')
print(users)
if _name_ == '__main__':
socketio.run(app,host='xxx.xxx.xx.x',port=5001)
client.js
var socket = io.connect("https://xxx.xxx.xx.x:5001/",{secure:false});
Screenshot 1:
This screenshot explains the access-control-allow-orgin works fine for images under static folder in flask framework
Screenshot 2:
This screenshot explains there is no access-control-orgin for socket call
You are using Flask-CORS to set up CORS on your Flask routes. You are missing a similar set up for Flask-SocketIO:
socketio = SocketIO(app, cors_allowed_origins=your_origins_here)
You can use '*' as the value to allow all origins (which I do not recommend), or set a single origin as a string, or a list of origins as a list of strings.
Related
POST UPDATE
I tested this same code on a different machine and it worked perfectly so it is probably a problem with some dependencies or something similar.
from flask import Flask, render_template
from flask_socketio import SocketIO
app = Flask(__name__)
socketio = SocketIO(app)
#app.route('/')
def index():
return render_template("index.html")
#socketio.on('test')
def test(message):
print(message)
if __name__ == '__main__':
socketio.run(app,host='0.0.0.0',port=8080,debug=True)
I saw in the documentation that you can run the web and socket server just by using
the SocketIO.run method.
When I execute my app.py it runs the server but I cannot access with my browser to webpage.
I saw somewhere that using async_mode='eventlet' on the SocketIO constructor could help but it threw an error.
ValueError: Invalid async_mode specified
import os, re
from flask import Flask, send_from_directory, json,request
from flask_socketio import SocketIO
from flask_cors import CORS
from flask_sqlalchemy import SQLAlchemy
import random
app = Flask(__name__, static_folder='./build/static')
# Point SQLAlchemy to your Heroku database
uri = os.getenv("DATABASE_URL") # or other relevant config var
if uri and uri.startswith("postgres://"):
uri = uri.replace("postgres://", "postgresql://", 1)
app.config['SQLALCHEMY_DATABASE_URI'] = uri
# Gets rid of a warning
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
import models
cors = CORS(app, resources={r"/*": {"origins": "*"}})
socketio = SocketIO(
app,
cors_allowed_origins="*",
json=json,
manage_session=False
)
#app.route('/', defaults={"filename": "index.html"})
#app.route('/<path:filename>')
def index(filename):
return send_from_directory('./build', filename)
# When a client connects from this Socket connection, this function is run
#socketio.on('connect')
def on_connect():
print('User connected!')
# When a client disconnects from this Socket connection, this function is run
#socketio.on('disconnect')
def on_disconnect():
print('User disconnected!')
#socketio.on('index')
def on_index():
all_students = db.Students.query.all()
random1 = random.randint(0,models.Students.query().count())
random2 = random.randint(0,models.Students.query().count())
total_table = []
for student in all_students:
total_table.append(student)
firstStudent = []
secondStudent = []
while(random2 == random1):
random2 = random.randint(0,models.Students.query().count())
firstStudent.append(total_table[random1])
secondStudent.append(total_table[random2])
twoStudents = [firstStudent,secondStudent]
socketio.emit('students', {twoStudents:twoStudents})
# Note we need to add this line so we can import app in the python shell
if __name__ == "__main__":
# Note that we don't call app.run anymore. We call socketio.run with app arg
socketio.run(
app,
)
The react end of the application launches fine with no errors, and the database has no issues. I've used this skeleton for the base of a bunch of other projects and i've never had any issues. But for some reason i'm stuck at a brick wall setting this up. I know the issue is within the #app.route('/') part of the code. i've tried hard coding the html file into the url path, but that just causes other errors like missing 1 required positional argument: 'filename' flask. Any help is greatly appreciated
I tested your configuration and it doesn't give me any errors. Nevertheless I offer you an alternative solution.
You can provide the entire react build folder as a static folder. You can then deliver the "index.html" as a single file in the root route. The prerequisite is that the prefix for the static url path is empty.
# ...
app = Flask(__name__,
static_url_path='',
static_folder='./build'
)
# ...
#app.route('/')
def index():
return app.send_static_file('index.html')
# ...
Whatever I seem to try (using different secret keys, trying to fix small errors) this error shows when I run my code.
I have tried making small changes to the code such as changing the secret key, fixing indentation, etc. However, I do not understand why my code does not work, so I wanted to ask here.
from flask import Flask, render_template, session, request
from flask_socketio import SocketIO, emit, join_room
app = Flask(__name__)
app.debug = True
app.config['SECRET_KEY'] = 'secretcodehere29403949493'
socketio = SocketIO(app)
#app.route("/template/chat.html/")
def chat():
return render_template("template/login.html")
#app.route(r'/template/login.html/')
def login():
return render_template('login.html')
#socketio.on('message', namespace='/chat')
def chat_message(message):
print("message = ", message)
emit('message', {'data': message['data']}, broadcast=True)
#socketio.on('connect', namespace='/chat')
def test_connect():
emit('my response', {'data': 'Connected', 'count': 0})
if __name__ == '__main__':
socketio.run(app)
Restarting with stat
Debugger is active!
Debugger PIN: 183-355-780
(18512) wsgi starting up on http://127.0.0.1:5000
nothing displays in the link it provides in the error here, and localhost:8080 shows nothing.
Your routes may not be correct. When you call app.route, you're mapping a url to the function.
In your case the urls in your routes are defining: 127.0.0.1:5000/template/chat.html/ and 127.0.0.1:5000/template/login.html/.
Try changing a route to #app.route('/') and then navigating to 127.0.0.1:5000 or localhost:5000
Concerning your last comment (I can't comment on dylanj.nz's post), the render_template function uses the default templates folder, so there is no need to specify it on your code :)
Thus you should remove template/ in this line:
return render_template("template/login.html").
If you want to change the default folder location, add a template_folder instruction in your app = Flask(...).
Example:
app = Flask(__name__, template_folder='application/templates', static_folder='heyanotherdirectory/static')
I've a flask endpoint where I've permitted CORS in the following manner.
app = Flask(__name__)
CORS(app, resources={r"/api/*": {"origins": "*"}})
app.register_blueprint(store, url_prefix='/api/')
I still run into the following issue.
Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'. Origin 'http://something.com:8888' is therefore not allowed access.
Any suggestions as to how I can fix this.
try this:
#Add these imports
from flask import jsonify
from flask_cors import CORS
#Add an app level config in this format
app = Flask(__name__)
CORS(autoINFER_app, resources={r"/*": {"origins": "*"}}, send_wildcard=True)
#While returning the GETs add this line
response = jsonify(all_dict)
response.headers.add('Access-Control-Allow-Origin', '*')
return response
This should take care of all permutations which might cause this.
Following some advice that I found here I am trying to use Flask as a web interface for an application that runs with twisted.
As suggested in Flask documentation I created a "templates" directory which is at the same level as my script but when I launch the server I get the following error:
Internal Server Error
The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.
When I do not try to load a template and just write a string in the request it works fine. This is what makes me think it is related to the load of the template.
from twisted.internet import reactor
from twisted.web.resource import Resource
from twisted.web.wsgi import WSGIResource
from twisted.internet.threads import deferToThread
from twisted.web.server import Site, NOT_DONE_YET
from flask import Flask, request, session, redirect, url_for, abort, \
render_template, flash
app= Flask(__name__)
app.config.from_object(__name__)
#app.route('/login', methods= ['GET', 'POST'])
def login():
return render_template('login.html', error= error)
if __name__ == '__main__':
root = WSGIResource(reactor, reactor.getThreadPool(), app)
factory = Site(root)
reactor.listenTCP(8880, factory)
reactor.run()
Some frameworks will change directory from your current working directory when they are run in daemon mode, and this might very well be the case here.
Flask, since 0.7, has supported passing a template_folder keyword argument when calling Flask, so you could try:
import os
tmpl_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates')
The following is a shorter version that will work just fine:
tmpl_dir = os.path.join(os.path.dirname(__file__), 'templates)
# ...
app = Flask('myapp', template_folder=tmpl_dir)
You can feed Jinja2 with a default templates directory (as written here) like this :
import jinja2
app = Flask(__name__)
app.jinja_loader = jinja2.FileSystemLoader('path/to/templates/directory')