Reputation: 55
I am working on an Angular project that involves communicating with Flask via SocketIO. Unfortunately, I am a complete beginner at python and Flask though have tried all that I could understand. This far I have tried involving CORS as can be seen in the code and also Zachary Jacobi's solution mentioned in
Javascript - No 'Access-Control-Allow-Origin' header is present on the requested resource
However, I am still getting the errors
Access to XMLHttpRequest at 'http://localhost:5000/socket.io/?EIO=3&transport=polling&t=NDLi66V' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
GET http://localhost:5000/socket.io/?EIO=3&transport=polling&t=NDLi66V net::ERR_FAILED
The Flask code that I am using is
from flask import Flask, render_template
from flask_socketio import SocketIO
from flask_cors import CORS
from corsAlt import crossdomain
import json
app = Flask(__name__)
CORS(app)
#app.config['SECRET_KEY'] = 'vnkdjnfjknfl1232#'
socketio = SocketIO(app)
@app.route('/')
@crossdomain(origin='*')
def sessions():
return render_template('index.html')
def messageReceived(methods=['GET', 'POST']):
print('message was received!!!')
@socketio.on('my event')
def handle_my_custom_event(json, methods=['GET', 'POST']):
json["user_name"]='Asad'
json["user_input"]='My Server'
print('received my event: ' + str(json))
socketio.emit('my response', json, callback=messageReceived)
if __name__ == '__main__':
socketio.run(app, debug=True, host='localhost', port = 5000)
In the Angular side,
import { Sio2service } from '../sio2.service';
@Component({
selector: 'app-workout-options',
templateUrl: 'workout-options.component.html',
styleUrls: ['../app.component.css']
})
export class WorkoutOptionsComponent implements OnDestroy{
mymessage: string;
subscription: Subscription;
@Output() public childEvent = new EventEmitter();
constructor(private messageService: MessageService, private sio2: Sio2service) {
this.subscription = this.messageService.getMessage()
.subscribe(mymessage => {
this.mymessage = mymessage;
});
}
OnInit(){
this.sio2.messages.subscribe(msg => {
})
}
FupdateParent(exerName:string) {
this.sio2.sendMsg(exerName);
}
}
Where the SIO and SIO2 codes are
import { Injectable } from '@angular/core';
import * as io from 'socket.io-client';
import { Observable } from 'rxjs/Observable';
import * as Rx from 'rxjs/Rx';
import { environment } from '../environments/environment';
@Injectable({
providedIn: 'root'
})
export class Sioservice {
private socket;
constructor() { }
connect(): Rx.Subject<MessageEvent> {
// If you aren't familiar with environment variables then
// you can hard code `environment.ws_url` as `http://localhost:5000`
this.socket = io(environment.ws_url);
// We define our observable which will observe any incoming messages
// from our socket.io server.
let observable = new Observable(observer => {
this.socket.on('message', (data) => {
console.log("Received message from Websocket Server")
observer.next(data);
})
return () => {
this.socket.disconnect();
}
});
// We define our Observer which will listen to messages
// from our other components and send messages back to our
// socket server whenever the `next()` method is called.
let observer = {
next: (data: Object) => {
this.socket.emit('message', JSON.stringify(data));
},
};
// we return our Rx.Subject which is a combination
// of both an observer and observable.
return Rx.Subject.create(observer, observable);
}
}
import { Injectable } from '@angular/core';
import { Sioservice } from './sio.service';
import { Observable, Subject } from 'rxjs/Rx';
@Injectable({
providedIn: 'root'
})
export class Sio2service {
messages: Subject<any>;
// Our constructor calls our wsService connect method
constructor(private wsService: Sioservice) {
this.messages = <Subject<any>>wsService
.connect()
.map((response: any): any => {
return response;
})
}
// Our simplified interface for sending
// messages back to our socket.io server
sendMsg(msg) {
this.messages.next(msg);
}
}
Please note that the Angular app communicates smoothly with the app.js file as
let app = require("express")();
let http = require("http").Server(app);
let io = require("socket.io")(http);
io.on("connection", socket => {
// Log whenever a user connects
console.log("user connected");
// Log whenever a client disconnects from our websocket server
socket.on("disconnect", function() {
console.log("user disconnected");
});
// When we receive a 'message' event from our client, print out
// the contents of that message and then echo it back to our client
// using `io.emit()`
socket.on("message", message => {
console.log("Message Received: " + message);
io.emit("message", { type: "new-message", text: message });
});
});
// Initialize our websocket server on port 5000
http.listen(5000, () => {
console.log("started on port 5000");
});
But the problem I am having with that is that I cannot get it to communicate with app.js above as it seems to create its own server.
Upvotes: 0
Views: 842
Reputation: 812
You need three things in the response header to solve CORS issue:
response.headers.add("Access-Control-Allow-Origin", "*")
response.headers.add('Access-Control-Allow-Headers', "*")
response.headers.add('Access-Control-Allow-Methods', "*")
I am not aware of how Flask works but I can guess that you are only handling number 1 point:
crossdomain(origin='*')
Side note: Number 3 point is used in case of pre flight requests with OPTIONS verb.
To help you, I copied a part of code from the link of question you pasted in your question:
@app.after_request
def after_request(response):
response.headers.add('Access-Control-Allow-Origin', '*')
response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS')
return response
Upvotes: 0