Reputation: 2087
I have created a web service using flask. Now, it turns out that I have to support some socket connections in the same app.
I tried using a specific url and then read from
request.stream
where request is
from flask import request
The data is there but I get code 400, message Bad request
.
Is there anything I can do to fix that? or maybe ideas to do something else.
Upvotes: 0
Views: 2731
Reputation: 5107
You can use flask-socketio: https://flask-socketio.readthedocs.io/en/latest/
from flask import Flask, render_template
from flask_socketio import SocketIO
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
if __name__ == '__main__':
socketio.run(app)
It must serve a page to the client:
<script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js" integrity="sha256-yr4fRk/GU1ehYJPAs8P4JlTgu0Hdsp4ZKrx8bDEDC3I=" crossorigin="anonymous"></script>
<script type="text/javascript" charset="utf-8">
var socket = io();
socket.on('connect', function() {
socket.emit('my event', {data: 'I\'m connected!'});
});
</script>
Then handle the data via an event:
@socketio.on('my event')
def handle_my_custom_event(json):
print('received json: ' + str(json))
# send(json, json=True) # send data back to client
# emit('my response', json) # another way to send data back to client
# emit('my response', ('foo', 'bar', json)) # multiple arguments via tuple
return 'one', 2 # yet another way to send data back to client
When defining your event, you can also receive plain string data, have arguments, etc.
@socketio.on('my_event')
def handle_my_custom_event(arg1, arg2, arg3):
print('received args: ' + arg1 + arg2 + arg3)
If the server needs to broadcast a message without a precipitating request:
def some_function():
socketio.emit('some event', {'data': 42})
You can also create rooms to group clients.
from flask_socketio import join_room, leave_room
@socketio.on('join')
def on_join(data):
username = data['username']
room = data['room']
join_room(room)
send(username + ' has entered the room.', room=room)
@socketio.on('leave')
def on_leave(data):
username = data['username']
room = data['room']
leave_room(room)
send(username + ' has left the room.', room=room)
And there are built-in connection events:
from flask_socketio import ConnectionRefusedError
@socketio.on('connect')
def test_connect():
emit('my response', {'data': 'Connected'})
@socketio.on('disconnect')
def test_disconnect():
print('Client disconnected')
@socketio.on('connect')
def connect():
if not self.authenticate(request.args):
raise ConnectionRefusedError('unauthorized!')
And logging/exception handling:
socketio = SocketIO(logger=True, engineio_logger=True)
@socketio.on_error() # Handles the default namespace
def error_handler(e):
pass
@socketio.on_error('/chat') # handles the '/chat' namespace
def error_handler_chat(e):
pass
@socketio.on_error_default # handles all namespaces without an explicit error handler
def default_error_handler(e):
print(request.event["message"]) # "my error event"
print(request.event["args"]) # (data,)
Upvotes: 0
Reputation: 2254
As far as I can tell from your comment you want to listen to a socket? You should not use flask for that, it will attempt to parse HTTP headers and body (if applicable), which explains the 400 bad request.
You should take a look at the SocsketServer module.
Upvotes: 1