11

I have the following scenario I would like to implement:

  • User surfs to our website
  • User enters a bitcoin address.
  • A websocket is created to the server, passing the address.
  • The server registers a callback with Blocktrail
  • When the callback is triggered (a payment was seen by Blocktrail) we send a message back to the browser.
  • The page the user is browsing is updated to show the message recieved

I'm using webhooks from the Blocktrail API to "listen" to an event, being the reception of coins on an address.

Now, when the event happens, the API does a POST to my URL. This should send a message to the browser that is connected to my server with socket.io (such as 'payment seen on blockchain')

So the question is,

How can I send a message from a route to a socket using flask-socketio

Pseudo code:

@app.route('/callback/<address>')
def callback(id):
    socketio.send('payment seen on blockchain')

@socketio.on('address',address)
def socketlisten(address):
    registerCallback(address)
DDecoene
  • 7,184
  • 7
  • 30
  • 43
  • 1
    Could you please describe a litte bit more clear how, what, in which order something should happen. May also look into this http://stackoverflow.com/questions/11498508/socket-emit-vs-socket-send for examples. – wenzul Oct 08 '15 at 09:00
  • It is quite a difficult problem to explain but I will try to edit my question te elaborate more. Thank you for the feedback. – DDecoene Oct 08 '15 at 11:28
  • I edited the question. – DDecoene Oct 08 '15 at 11:40

1 Answers1

8

I'm going to describe how to solve this using Flask-SocketIO beta version 1.0b1. You can also do this with the 0.6 release, but it is a bit more complicated, the 1.0 release makes addressing individual clients easier.

Each client of a socket connection gets assigned a session id that uniquely identifies it, the so called sid. Within a socket function handler, you can access it as request.sid. Also, upon connection, each client is assigned to a private room, named with the session id.

I assume the metadata that you receive with the callback allows you to identify the user. What you need is to obtain the sid of that user. Once you have it, you can send your alert to the corresponding room.

Example (with some hand-waving regarding how you attach a sid to an address):

@app.route('/callback/<address>')
def callback(address):
    sid = get_sid_from_address(address)
    socketio.send('payment seen on blockchain', room=sid)

@socketio.on('address')
def socketlisten(address):
    associate_address_with_sid(address, request.sid)
Miguel Grinberg
  • 65,299
  • 14
  • 133
  • 152
  • As promised I've tried this solution. I THINK it will work. Only trouble is I run the flask app with mod_wsgi on apache. I don't want to do socketio.run(app) with reverse proxy because I hate "manually" started processes on a production server. So I'm stuck on deployment to our testserver for now. Because other sites are running on this server as apache virtual hosts, I cannot just switch to other webserver software either. So maybe it's time for this app's dedicated server... – DDecoene Oct 20 '15 at 15:43
  • @DennisDecoene if you use Apache/mod_wsgi you have bigger problems than `socketio.run()`. My understanding is that mod_wsgi does not play along well with coroutine frameworks, I think you will not be able to use eventlet or gevent if you deploy that way. I'm also unclear on what support mod_wsgi has for WebSocket, I believe it does not support it. – Miguel Grinberg Oct 20 '15 at 18:10
  • Well, I am testing now with a standalone 'socket.run()' and i upgraded to 1.0b4 on the server and 0.9.16 on the client but I'm giving up because I now get 'Uncaught TypeError: Cannot read property 'onClose' of null' on the client. this is the client connect: var socket = io.connect('http://' + document.domain + ':' + location.port, {resource:'socket.io'}); – DDecoene Oct 20 '15 at 19:31
  • You need to use 1.3.x on the client. See the [documentation](https://github.com/miguelgrinberg/Flask-SocketIO/blob/v1.0/docs/index.rst#upgrading-to-flask-socketio-1x-from-older-releases). – Miguel Grinberg Oct 21 '15 at 04:11
  • Oh, of course, since I left the whole wsgi thing, I don't need 0.9.16 no more!!! [takes pistol, aims at brain, fires :D] – DDecoene Oct 21 '15 at 11:21