I'm trying to make a Flask server (port 5000) that has a socket.io connection with a React client (port 3000). When I try to execute the server script (shown below), I get an error that says "http://localhost:3000 is not an accepted origin" even though I am using CORS.
server-test.py:
from flask import Flask
from flask_socketio import SocketIO, emit
from flask_cors import CORS, cross_origin
import os
from dotenv import load_dotenv, find_dotenv
load_dotenv(find_dotenv())
app = Flask(__name__)
app.config['CORS_HEADERS'] = 'Content-Type'
app.config['SECRET_KEY'] = os.environ.get('SECRET')
socketio = SocketIO(app)
CORS(app)
#socketio.on('connect')
#cross_origin()
def handle_connection():
emit('server-client', 'Test message')
#socketio.on('client-server')
#cross_origin()
def handle_client_msg(msg):
print("\n" + str(msg))
if __name__ == '__main__':
app.run(host="localhost", port=os.environ.get('PORT'))
socketio.run(app)
App.jsx:
import { io } from 'socket.io-client';
// ...
useEffect(() => {
const socket = io('http://localhost:5000');
socket.on('server-client', msg => {
alert(msg);
socket.emit('client-server', 'Client: Message received!');
});
}, []);
Error message in WSL terminal:
* Serving Flask app 'server-test' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://localhost:5000/ (Press CTRL+C to quit)
http://localhost:3000 is not an accepted origin. (further occurrences of this error will be logged with level INFO)
127.0.0.1 - - [16/May/2021 00:27:31] "GET /socket.io/?EIO=4&transport=polling&t=NboMpZQ HTTP/1.1" 400 -
127.0.0.1 - - [16/May/2021 00:27:31] "GET /socket.io/?EIO=4&transport=polling&t=NboMpZS HTTP/1.1" 400 -
127.0.0.1 - - [16/May/2021 00:27:31] "GET /socket.io/?EIO=4&transport=polling&t=NboMpZR.0 HTTP/1.1" 400 -
127.0.0.1 - - [16/May/2021 00:27:31] "GET /socket.io/?EIO=4&transport=polling&t=NboMpZR HTTP/1.1" 400 -
The Flask SocketIO documentation says this:
If an incoming HTTP or WebSocket request includes the Origin header, this header must match the scheme and host of the connection URL. In case of a mismatch, a 400 status code response is returned and the connection is rejected.
and this:
If necessary, the cors_allowed_origins option can be used to allow other origins. This argument can be set to a string to set a single allowed origin, or to a list to allow multiple origins. A special value of '*' can be used to instruct the server to allow all origins, but this should be done with care, as this could make the server vulnerable to Cross-Site Request Forgery (CSRF) attacks.
So instead of this:
socketio = SocketIO(app)
you could do this:
socketio = SocketIO(app, cors_allowed_origins="*")
Unrelated to the cors issue, but I also added return statements to the functions. Without returning something I got:
TypeError: The view function did not return a valid response.
Seems to be required if using the #cross_origin() decorators, so you could also remove those and then you don't need the return statements.
Related
I have an issue with #react-oauth/google npm package.
When I using react app on port 3000 and backend django on port 8000 every thing work's, but after I build react app and using port 8000, I try to log in via google, I get that Erros:
Failed to load resource: the server responded with a status of 400 m=credential_button_library:45 [GSI_LOGGER]: The given origin is not allowed for the given client ID.
I did double check on 'Authorised JavaScript origins' and 'Authorised redirect URIs' (image attached)
but the giving origin are allowed, so whats can be the problem?
I read about similar problems here on the site and also tried CHAT GPT but nothing helped.
This is my configurations:
CORS_ALLOWED_ORIGINS = [
"http://localhost:8000",
"http://localhost:3000",
"http://127.0.0.1:3000",
"http://127.0.0.1:8000"
]
class GoogleLogin(SocialLoginView):
adapter_class = GoogleOAuth2Adapter
callback_url = ['http://localhost:8000', 'http://localhost:3000', 'http://127.0.0.1:8000', 'http://localhost:8000/accounts/google/login/callback/'] # !
client_class = OAuth2Client
Comment the CORS_ALLOWED_ORIGINS and try with CORS_ALLOW_ALL_ORIGINS = True and if this doesn't work try to remove this http://localhost:3000 and http://127.0.0.1:8000 from both ( CORS_ALLOWED_ORIGINS and GoogleLogin ) and If the above things doesn't work then try to run your react app on PORT - 3000 and on the URL just change your port to 8000 and then try.
How do I get both https://example.com and https://www.example.com for endpoints to connect?
socket.io connect no problem at htttps://example.com
but not https://www.example.com
my server looks like
const server = http.createServer(app);
const io = socketIo(server, {
cors: {
origin: "https://www.example.com:3000",
methods: ["GET", "POST"],
allowedHeaders: ["my-custom-header"],
credentials: true
}});
and my client endpoint looks like this
const ENDPOINT = 'https://example.com/';
Configure your DNS to point both example.com and www.example.com to the same host IP address and then support both domains with your cors configuration. Then, either URL will go to the same host.
You can avoid cors entirely if you configure socket.io to start immediately with a webSocket, not with the http polling that it usually starts with. You can do that in the client by adding the transports: ['websocket'] option to the client connect.
And, your custom header was probably blocking CORs and requiring pre-flight permission. CORs has two levels, simple and not-simple. When you add a custom header, you force CORs into the not-simple route where it requires preflight which is probably more than the built-in socketio cors features will handle.
I have searched for hours trying to find a decent solution to my problem and I can't seem to find a solution. Basically, I broke up my Flask API into two separate files using blueprints, one that serves as the main Flask application and the other to handle all the authentication routes. I am running into CORS issues... Before I separated them, it worked fine with the flask-cors library. However, when I broke it into separate files using blueprints, it didn't work. I did a bunch of research and there seems be a couple ways to do it, but the best way seems to be solving the problem on the server side (at least in theory because I haven't found a solution to it yet).
app.py
# Third-party libraries
from flask import Flask
from flask_cors import CORS
# Internal imports
from login import login_page
# Flask app setup
app = Flask(__name__)
app.register_blueprint(login_page)
CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'
if __name__ == "__main__":
app.run(host="localhost", debug=True)
login.py
# Third-party libraries
from flask import Flask, redirect, request, url_for, Blueprint, render_template, abort
from flask_login import (
LoginManager,
current_user,
login_required,
login_user,
logout_user
)
from oauthlib.oauth2 import WebApplicationClient
import requests
from flask_cors import CORS
login_page = Blueprint('login_page', __name__)
CORS(login_page)
# Login route
#login_page.route('/login', methods=['GET'])
def login():
# Find out what URL to hit for Google login
google_provider_config = get_google_provider_config()
authorization_endpoint = google_provider_config["authorization_endpoint"]
# Use library to construct the request for Google login and provide
# scopes that let you retrieve user's profile from Google
request_uri = client.prepare_request_uri(
authorization_endpoint,
redirect_uri = request.base_url + "/callback",
scope = ["openid", "email", "profile"]
)
return redirect(request_uri)
From the documentation:
https://flask-cors.readthedocs.io/en/latest/api.html#using-cors-with-blueprints
Which seems to be what I am doing... But it's not working.
Edit:
React code:
authenticate = async () => {
console.log('authenticate called')
const response = await users.get('/login');
}
I added a test route to see if the way I was handling blue prints was incorrect with the flask-cors library as follows:
#login_page.route('/test')
def test():
print('test')
return 'test'
Sure enough, I was able to see the text print on the console. So this leaves me to believe it is something else preventing me from accessing Google's authentication servers.
Flask application is running on localhost:5000 and React application is running on localhost:3000. The string that gets passed into the redirect method in login is as follows:
https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=None&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2Flogin%2Fcallback&scope=openid+email+profile
However, this was working prior to working with React.
Chrome console error:
Access to XMLHttpRequest at '...' (redirected from 'http://localhost:3000/login') from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I have also added a proxy to my package.json file as follows:
"proxy": "http://localhost:5000"
Which I got from: https://blog.miguelgrinberg.com/post/how-to-create-a-react--flask-project/page/3
Update:
I have decided to go with the approach of solving this problem using Nginx since it seems to that flask-cors library is not suitable for this problem as no solution seems to be possible.
Nginx.conf
user www-data;
worker_processes 1;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 1024;
}
http {
upstream react-client {
server react-client;
}
upstream flask-backend {
server flask-backend;
}
server {
listen 80;
server_name localhost;
location / {
# From docker-compose, react-client port 80 is exposed
proxy_pass http://react-client;
}
# location /login/callback
# location /logout
}
server {
listen 3000;
server_name localhost;
location /login {
proxy_pass http://flask-backend;
}
}
}
docker-compose.yml:
version: '3'
services:
reverse-proxy:
image: nginx:1.17.10
container_name: reverse-proxy
depends_on:
- flask-backend
- react-client
volumes:
- ./reverse-proxy/nginx.conf:/etc/nginx/nginx.conf
ports:
- 80:80
react-client:
image: react-client
container_name: react-client
build:
context: ./client
depends_on:
- flask-backend
ports:
- 3000:3000
restart: on-failure
flask-backend:
image: flask-backend
container_name: flask-backend
build:
context: ./api
ports:
- 5000:5000
restart: on-failure
With the Nginx configuration and Docker files, I am able to go to http://localhost:80 which forwards me to the react client. This time, I am not getting the CORS errors, but I do get this message in my inspector, Failed to load resource: The network connection was lost.
My understanding is this:
http://localhost:80 -> http://localhost:3000, then when a button is pressed, it prompts the new route
http://localhost:3000/login -> http://localhost:5000/login
I have two server blocks because the web application is running in port 3000 and Nginx server on port 80.
Instead of CORS(login_page) try CORS(login_page, resources=r'/login')
Edit: To explain why this might work.
The error you're getting indicates that the /login route doesn't have CORS permitted. You're instantiating Flask-CORS correctly so I suspect if you tried delineating the specific route you want CORS to apply to you would fix the issue.
The docs make it seem like CORS(login_page) should automatically open up all routes to CORS but because that's not working trying the above answer might provide better results.
I am trying to make Flask-Socketio connection from AngularJS at client side to a Flask server.
Connecting with the Flask server works fine, but when I try to connect to socketio in my Angular controller:
var socket = io.connect('http://localhost:5000');
I see the following error on my browser console:
Failed to load
http://localhost:5000/socket.io/?EIO=3&transport=polling&t=1526477253000-2:
The value of the 'Access-Control-Allow-Origin' header in the response
must not be the wildcard '*' when the request's credentials mode is
'include'. Origin 'http://localhost:3000' is therefore not allowed
access. The credentials mode of requests initiated by the
XMLHttpRequest is controlled by the withCredentials attribute.
My client side (AngularJS) is running on port 3000 (gulp) and Flask server is running on port 5000.
I have tried including flask_cors with:
cors = CORS(app, resources={r"/*": {"origins": "*"}})
But still get the same issue.
Any help is appreciated.
Cheers.
cors = CORS(app, resources={r"/": {"origins": ""}})
instead of star mention you are host with port
I have an endpoint api named "gameApi"
I have an api called:
#ApiMethod(name = "startNewRound", path = "evaluateRound", httpMethod = HttpMethod.POST)
I'm trying to run the following task queue:
queue.add(
ofy().getTransaction(),
TaskOptions.Builder.withUrl("/_ah/api/gameApi/v1/evaluateRound")
.param("gameId", gameId.toString())
.method(TaskOptions.Method.POST)
.countdownMillis(5000));
I'm getting a 404 in the logs:
0.1.0.2 - - [14/Nov/2014:14:58:28 -0800] "POST /_ah/api/gameApi/v1/evaluateRound HTTP/1.1" 404 234 "https://some-appspot-123.appspot.com/_ah/spi/com.appspot.some_appspot_123.spi.GameAPI.playCard" "AppEngine-Google; (+http://code.google.com/appengine)" "some-appspot-123.appspot.com" ms=8 cpu_ms=21 cpm_usd=0.000026 queue_name=default task_name=62689306220576549071 instance=00c61b117c54ec2fb802c51c19fe26523ec51854 app_engine_release=1.9.16
It looks like it's hitting the HTTP and not the HTTPS page. Is there a way I can force it to use HTTPS?
In endpoints, HTTP 404 corresponds to com.google.api.server.spi.response.NotFoundException.
Is it possible that the method has not been defined in the API class, or that it doesn't have a correct annotation?
Also, it doesn't seem like it's hitting http, the trace clearly shows https as the protocol. I think it's only possible to use http on localhost.