Skip to content

Commit b214380

Browse files
ASGI support
1 parent 015ea20 commit b214380

File tree

13 files changed

+376
-16
lines changed

13 files changed

+376
-16
lines changed

examples/asgi/README.rst

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
Socket.IO aiohttp Examples
2+
==========================
3+
4+
This directory contains example Socket.IO applications that are compatible with
5+
asyncio and the aiohttp framework. These applications require Python 3.5 or
6+
later.
7+
8+
app.py
9+
------
10+
11+
A basic "kitchen sink" type application that allows the user to experiment
12+
with most of the available features of the Socket.IO server.
13+
14+
latency.py
15+
----------
16+
17+
A port of the latency application included in the official Engine.IO
18+
Javascript server. In this application the client sends *ping* messages to
19+
the server, which are responded by the server with a *pong*. The client
20+
measures the time it takes for each of these exchanges and plots these in real
21+
time to the page.
22+
23+
This is an ideal application to measure the performance of the different
24+
asynchronous modes supported by the Socket.IO server.
25+
26+
Running the Examples
27+
--------------------
28+
29+
To run these examples, create a virtual environment, install the requirements
30+
and then run::
31+
32+
$ python app.py
33+
34+
or::
35+
36+
$ python latency.py
37+
38+
You can then access the application from your web browser at
39+
``http://localhost:8080``.

examples/asgi/app.html

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<!DOCTYPE HTML>
2+
<html>
3+
<head>
4+
<title>python-socketio test</title>
5+
<script type="text/javascript" src="//code.jquery.com/jquery-2.1.4.min.js"></script>
6+
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.slim.js"></script>
7+
<script type="text/javascript" charset="utf-8">
8+
$(document).ready(function(){
9+
namespace = '/test';
10+
var socket = io.connect('http://' + document.domain + ':' + location.port + namespace);
11+
12+
socket.on('connect', function() {
13+
socket.emit('my event', {data: 'I\'m connected!'});
14+
});
15+
socket.on('disconnect', function() {
16+
$('#log').append('<br>Disconnected');
17+
});
18+
socket.on('my response', function(msg) {
19+
$('#log').append('<br>Received: ' + msg.data);
20+
});
21+
22+
// event handler for server sent data
23+
// the data is displayed in the "Received" section of the page
24+
// handlers for the different forms in the page
25+
// these send data to the server in a variety of ways
26+
$('form#emit').submit(function(event) {
27+
socket.emit('my event', {data: $('#emit_data').val()});
28+
return false;
29+
});
30+
$('form#broadcast').submit(function(event) {
31+
socket.emit('my broadcast event', {data: $('#broadcast_data').val()});
32+
return false;
33+
});
34+
$('form#join').submit(function(event) {
35+
socket.emit('join', {room: $('#join_room').val()});
36+
return false;
37+
});
38+
$('form#leave').submit(function(event) {
39+
socket.emit('leave', {room: $('#leave_room').val()});
40+
return false;
41+
});
42+
$('form#send_room').submit(function(event) {
43+
socket.emit('my room event', {room: $('#room_name').val(), data: $('#room_data').val()});
44+
return false;
45+
});
46+
$('form#close').submit(function(event) {
47+
socket.emit('close room', {room: $('#close_room').val()});
48+
return false;
49+
});
50+
$('form#disconnect').submit(function(event) {
51+
socket.emit('disconnect request');
52+
return false;
53+
});
54+
});
55+
</script>
56+
</head>
57+
<body>
58+
<h1>python-socketio test</h1>
59+
<h2>Send:</h2>
60+
<form id="emit" method="POST" action='#'>
61+
<input type="text" name="emit_data" id="emit_data" placeholder="Message">
62+
<input type="submit" value="Echo">
63+
</form>
64+
<form id="broadcast" method="POST" action='#'>
65+
<input type="text" name="broadcast_data" id="broadcast_data" placeholder="Message">
66+
<input type="submit" value="Broadcast">
67+
</form>
68+
<form id="join" method="POST" action='#'>
69+
<input type="text" name="join_room" id="join_room" placeholder="Room Name">
70+
<input type="submit" value="Join Room">
71+
</form>
72+
<form id="leave" method="POST" action='#'>
73+
<input type="text" name="leave_room" id="leave_room" placeholder="Room Name">
74+
<input type="submit" value="Leave Room">
75+
</form>
76+
<form id="send_room" method="POST" action='#'>
77+
<input type="text" name="room_name" id="room_name" placeholder="Room Name">
78+
<input type="text" name="room_data" id="room_data" placeholder="Message">
79+
<input type="submit" value="Send to Room">
80+
</form>
81+
<form id="close" method="POST" action="#">
82+
<input type="text" name="close_room" id="close_room" placeholder="Room Name">
83+
<input type="submit" value="Close Room">
84+
</form>
85+
<form id="disconnect" method="POST" action="#">
86+
<input type="submit" value="Disconnect">
87+
</form>
88+
<h2>Receive:</h2>
89+
<div><p id="log"></p></div>
90+
</body>
91+
</html>

examples/asgi/app.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import asyncio
2+
3+
import uvicorn
4+
from uvicorn.loops.auto import auto_loop_setup
5+
6+
import socketio
7+
8+
sio = socketio.AsyncServer(async_mode='asgi')
9+
app = socketio.ASGIApp(sio, static_files={
10+
'/': {'content_type': 'text/html', 'filename': 'app.html'},
11+
})
12+
13+
14+
async def background_task():
15+
"""Example of how to send server generated events to clients."""
16+
count = 0
17+
while True:
18+
await sio.sleep(10)
19+
count += 1
20+
await sio.emit('my response', {'data': 'Server generated event'},
21+
namespace='/test')
22+
23+
24+
@sio.on('my event', namespace='/test')
25+
async def test_message(sid, message):
26+
await sio.emit('my response', {'data': message['data']}, room=sid,
27+
namespace='/test')
28+
29+
30+
@sio.on('my broadcast event', namespace='/test')
31+
async def test_broadcast_message(sid, message):
32+
await sio.emit('my response', {'data': message['data']}, namespace='/test')
33+
34+
35+
@sio.on('join', namespace='/test')
36+
async def join(sid, message):
37+
sio.enter_room(sid, message['room'], namespace='/test')
38+
await sio.emit('my response', {'data': 'Entered room: ' + message['room']},
39+
room=sid, namespace='/test')
40+
41+
42+
@sio.on('leave', namespace='/test')
43+
async def leave(sid, message):
44+
sio.leave_room(sid, message['room'], namespace='/test')
45+
await sio.emit('my response', {'data': 'Left room: ' + message['room']},
46+
room=sid, namespace='/test')
47+
48+
49+
@sio.on('close room', namespace='/test')
50+
async def close(sid, message):
51+
await sio.emit('my response',
52+
{'data': 'Room ' + message['room'] + ' is closing.'},
53+
room=message['room'], namespace='/test')
54+
await sio.close_room(message['room'], namespace='/test')
55+
56+
57+
@sio.on('my room event', namespace='/test')
58+
async def send_room_message(sid, message):
59+
await sio.emit('my response', {'data': message['data']},
60+
room=message['room'], namespace='/test')
61+
62+
63+
@sio.on('disconnect request', namespace='/test')
64+
async def disconnect_request(sid):
65+
await sio.disconnect(sid, namespace='/test')
66+
67+
68+
@sio.on('connect', namespace='/test')
69+
async def test_connect(sid, environ):
70+
await sio.emit('my response', {'data': 'Connected', 'count': 0}, room=sid,
71+
namespace='/test')
72+
73+
74+
@sio.on('disconnect', namespace='/test')
75+
def test_disconnect(sid):
76+
print('Client disconnected')
77+
78+
79+
if __name__ == '__main__':
80+
loop = auto_loop_setup()
81+
sio.start_background_task(background_task)
82+
uvicorn.run(app, '127.0.0.1', 5000, loop=loop)

examples/asgi/latency.html

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<title>Socket.IO Latency</title>
5+
<link rel="stylesheet" href="/static/style.css" />
6+
</head>
7+
<body>
8+
<h1>Socket.IO Latency <span id="latency"></span></h1>
9+
<h2 id="transport">(connecting)</h2>
10+
<canvas id="chart" height="200"></canvas>
11+
12+
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js"></script>
13+
<script src="//cdnjs.cloudflare.com/ajax/libs/smoothie/1.27.0/smoothie.js"></script>
14+
<script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.slim.js"></script>
15+
<script>
16+
// socket
17+
var socket = io.connect('http://' + document.domain + ':' + location.port);
18+
var char = $('chart').get(0);
19+
socket.on('connect', function() {
20+
if (chart.getContext) {
21+
render();
22+
window.onresize = render;
23+
}
24+
send();
25+
});
26+
socket.on('pong_from_server', function() {
27+
var latency = new Date - last;
28+
$('#latency').text(latency + 'ms');
29+
if (time)
30+
time.append(+new Date, latency);
31+
setTimeout(send, 100);
32+
});
33+
socket.on('disconnect', function() {
34+
if (smoothie)
35+
smoothie.stop();
36+
$('#transport').text('(disconnected)');
37+
});
38+
39+
var last;
40+
function send() {
41+
last = new Date;
42+
socket.emit('ping_from_client');
43+
$('#transport').text(socket.io.engine.transport.name);
44+
}
45+
46+
// chart
47+
var smoothie;
48+
var time;
49+
function render() {
50+
if (smoothie)
51+
smoothie.stop();
52+
chart.width = document.body.clientWidth;
53+
smoothie = new SmoothieChart();
54+
smoothie.streamTo(chart, 1000);
55+
time = new TimeSeries();
56+
smoothie.addTimeSeries(time, {
57+
strokeStyle: 'rgb(255, 0, 0)',
58+
fillStyle: 'rgba(255, 0, 0, 0.4)',
59+
lineWidth: 2
60+
});
61+
}
62+
</script>
63+
</body>
64+
</html>

examples/asgi/latency.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import uvicorn
2+
3+
import socketio
4+
5+
sio = socketio.AsyncServer(async_mode='asgi')
6+
app = socketio.ASGIApp(sio, static_files={
7+
'/': {'content_type': 'text/html', 'filename': 'latency.html'},
8+
'/static/style.css': {'content_type': 'text/css',
9+
'filename': 'static/style.css'},
10+
})
11+
12+
13+
@sio.on('ping_from_client')
14+
async def ping(sid):
15+
await sio.emit('pong_from_server', room=sid)
16+
17+
18+
if __name__ == '__main__':
19+
uvicorn.run(app, '127.0.0.1', 5000)

examples/asgi/requirements.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
aiohttp==1.3.1
2+
async-timeout==1.1.0
3+
chardet==2.3.0
4+
multidict==2.1.4
5+
python-engineio
6+
python_socketio
7+
six==1.10.0
8+
yarl==0.9.2

examples/asgi/static/style.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
body { margin: 0; padding: 0; font-family: Helvetica Neue; }
2+
h1 { margin: 100px 100px 10px; }
3+
h2 { color: #999; margin: 0 100px 30px; font-weight: normal; }
4+
#latency { color: red; }

examples/wsgi/app.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
sio = socketio.Server(logger=True, async_mode=async_mode)
1111
app = Flask(__name__)
12-
app.wsgi_app = socketio.Middleware(sio, app.wsgi_app)
12+
app.wsgi_app = socketio.WSGIApp(sio, app.wsgi_app)
1313
app.config['SECRET_KEY'] = 'secret!'
1414
thread = None
1515

examples/wsgi/django_example/django_example/wsgi.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010
import os
1111

1212
from django.core.wsgi import get_wsgi_application
13-
from socketio import Middleware
13+
import socketio
1414

1515
from socketio_app.views import sio
1616

1717
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_example.settings")
1818

1919
django_app = get_wsgi_application()
20-
application = Middleware(sio, django_app)
20+
application = socketio.WSGIApp(sio, django_app)

examples/wsgi/latency.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
sio = socketio.Server(async_mode=async_mode)
1010
app = Flask(__name__)
11-
app.wsgi_app = socketio.Middleware(sio, app.wsgi_app)
11+
app.wsgi_app = socketio.WSGIApp(sio, app.wsgi_app)
1212

1313

1414
@app.route('/')

0 commit comments

Comments
 (0)