Skip to content
This repository was archived by the owner on Aug 26, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The source code is contained in the `server.py` module, and can be [viewed here]
Clone the repository, then install the requirements and start the web server.

$ pip install -r requirements.txt
$ python ./server.py
$ gunicorn -k flask_sockets.worker server:app
* Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)

---
Expand Down Expand Up @@ -65,4 +65,4 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[core-api]: https://github.com/core-api/core-api
[flask]: http://flask.pocoo.org/
[server-source-code]: https://github.com/core-api/example-server/blob/master/server.py
[python-client]: https://github.com/core-api/python-client
[python-client]: https://github.com/core-api/python-client
5 changes: 4 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
requests
coreapi
flask
flask-sockets
gunicorn
jsonpatch
requests
49 changes: 49 additions & 0 deletions server.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
from collections import OrderedDict
from coreapi import Document, Link, Error, Field, dump
from flask import Flask, Response, request
from flask_sockets import Sockets
import json
import jsonpatch
import time
import uuid


app = Flask(__name__)
sockets = Sockets(app)
clients = []


# We store all the notes in a mapping of UUIDs to dictionary instances.
# In a real system we would be using a database or other persistent backend.
Expand Down Expand Up @@ -59,6 +66,7 @@ def note_list():
'description': str(data['description']),
'complete': False
}
notify_clients()

doc = get_notes()
accept = request.headers.get('Accept')
Expand All @@ -84,6 +92,7 @@ def note_detail(identifier):

if request.method == 'DELETE':
del notes[identifier]
notify_clients()
return Response(status=204)

elif request.method == 'PUT':
Expand All @@ -93,12 +102,52 @@ def note_detail(identifier):
note['description'] = str(data['description'])
if 'complete' in data:
note['complete'] = bool(data['complete'])
notify_clients()

doc = get_note(identifier)
accept = request.headers.get('Accept')
media_type, content = dump(doc, accept=accept)
return Response(content, mimetype=media_type)


# WebSockets

@sockets.route('/live')
def echo_socket(ws):
message = ws.receive()
doc = get_notes()
media_type, content = dump(doc, accept='application/vnd.coreapi+json')
data = json.loads(content)
ws.send('Content-Type: application/vnd.coreapi+json\n\n' + content)
clients.append((ws, data))
while True:
time.sleep(1)


def notify_clients():
global clients

if not clients:
return

doc = get_notes()

media_type, next_content = dump(doc, accept='application/vnd.coreapi+json')
next_data = json.loads(next_content)
new_clients = []
print 'Sending message to %d clients' % len(clients)
for (client, previous_data) in list(clients):
if next_data == previous_data:
continue
patch = jsonpatch.make_patch(previous_data, next_data).to_string()
try:
client.send(patch)
except:
print 'Client left'
else:
new_clients.append((client, next_data))
clients = new_clients


if __name__ == '__main__':
app.run(port=3000, debug=True)