Git Product home page Git Product logo

django-socketio's Introduction

image

Created by Stephen McDonald

State of django-socketio

django-socketio is currently bound to socket.io 0.6, which is considerably out of date. It's fully functional, but some browsers now have newer implementations of WebSockets, and so alternative socket.io transports are fallen back to in these cases.

Work is currently underway to bring django-socketio up to date with the latest gevent-socktio, which has just recently started to support socket.io 0.8

Follow this thread for more info:

#19

Introduction

django-socketio is a BSD licensed Django application that brings together a variety of features that allow you to use WebSockets seamlessly with any Django project.

django-socketio was inspired by Cody Soyland's introductory blog post on using Socket.IO and gevent with Django, and made possible by the work of Jeffrey Gelens' gevent-websocket and gevent-socketio packages.

The features provided by django-socketio are:

  • Installation of required packages from PyPI
  • A management command for running gevent's pywsgi server with auto-reloading capabilities
  • A channel subscription and broadcast system that extends Socket.IO allowing WebSockets and events to be partitioned into separate concerns
  • A signals-like event system that abstracts away the various stages of a Socket.IO request
  • Support for out-of-band (non-event) broadcasts
  • The required views, urlpatterns, templatetags and tests for all the above

Upgrading

Prior to version 0.3, the message argument sent to each of the event handlers was always a Python list, regardless of the data type that was used for sending data. As of 0.3, the message argument matches the data type being sent via JavaScript.

Installation

Note that if you've never installed gevent, you'll first need to install the libevent development library. You may also need the Python development library if not installed. This can be achieved on Debian based sytems with the following commands:

$ sudo apt-get install python-dev
$ sudo apt-get install libevent-dev

or on OSX using Homebrew (with Xcode installed):

$ brew install libevent
$ export CFLAGS=-I/brew/include

or on OSX using `macports`:

$ sudo port install libevent
$ CFLAGS="-I /opt/local/include -L /opt/local/lib" pip install django-socketio

The easiest way to install django-socketio is directly from PyPi using pip by running the following command, which will also attempt to install the dependencies mentioned above:

$ pip install -U django-socketio

Otherwise you can download django-socketio and install it directly from source:

$ python setup.py install

Once installed you can then add django_socketio to your INSTALLED_APPS and django_socketio.urls to your url conf:

urlpatterns += [
    url("", include('django_socketio.urls')),
]

The client-side JavaScripts for Socket.IO and its extensions can then be added to any page with the socketio templatetag:

<head>
    {% load socketio_tags %}
    {% socketio %}
    <script>
        var socket = new io.Socket();
        socket.connect();
        // etc
    </script>
</head>

Running

The runserver_socketio management command is provided which will run gevent's pywsgi server which is required for supporting the type of long-running request a WebSocket will use:

$ python manage.py runserver_socketio host:port

Note that the host and port can also configured by defining the following settings in your project's settings module:

  • SOCKETIO_HOST - The host to bind the server to.
  • SOCKETIO_PORT - The numeric port to bind the server to.

These settings are only used when their values are not specified as arguments to the runserver_socketio command, which always takes precedence.

Note

On UNIX-like systems, in order for the flashsocket transport fallback to work, root privileges (eg by running the above command with sudo) are required when running the server. This is due to the Flash Policy Server requiring access to a low port (843). This isn't strictly required for everything to work correctly, as the flashsocket transport is only used as one of several fallbacks when WebSockets aren't supported by the browser.

When running the runserver_socketio command in production, you'll most likely want to use some form of process manager, like Supervisor or any of the other alternatives.

Channels

The WebSocket implemented by gevent-websocket provides two methods for sending data to other clients, socket.send which sends data to the given socket instance, and socket.broadcast which sends data to all socket instances other than itself.

A common requirement for WebSocket based applications is to divide communications up into separate channels. For example a chat site may have multiple chat rooms and rather than using broadcast which would send a chat message to all chat rooms, each room would need a reference to each of the connected sockets so that send can be called on each socket when a new message arrives for that room.

django-socketio extends Socket.IO both on the client and server to provide channels that can be subscribed and broadcast to.

To subscribe to a channel client-side in JavaScript use the socket.subscribe method:

var socket = new io.Socket();
socket.connect();
socket.on('connect', function() {
    socket.subscribe('my channel');
});

Once the socket is subscribed to a channel, you can then broadcast to the channel server-side in Python using the socket.broadcast_channel method:

socket.broadcast_channel("my message")

Broadcast and Send Methods

Each server-side socket instance contains a handful of methods for sending data. As mentioned above, the first two methods are implemented by gevent-socketio:

  • socket.send(message) - Sends the given message directly to the socket.
  • socket.broadcast(message) - Sends the given message to all other sockets.

The remaning methods are implemented by django-socketio.

  • socket.broadcast_channel(message, channel=None) - Sends the given message to all other sockets that are subscribed to the given channel. If no channel is given, all channels that the socket is subscribed to are used. the socket.
  • socket.send_and_broadcast(message) - Shortcut that sends the message to all sockets, including the sender.
  • socket.send_and_broadcast_channel(message, channel=None) - Shortcut that sends the message to all sockets for the given channel, including the sender.

The following methods can be imported directly from django_socketio for broadcasting and sending out-of-band (eg: not in response to a socket event). These methods map directly to the same methods on a socket instance, and in each case an appropriate connected socket will be chosen to use for sending the message, and the django_socketio.NoSocket exception will be raised if no connected sockets exist.

  • django_socketio.broadcast(message)
  • django_socketio.broadcast_channel(message, channel)
  • django_socketio.send(session_id, message)

Note that with the send method, the socket is identified by its session ID, accessible via socket.session.session_id. This is a WebSocket session ID and should not be confused with a Django session ID which is different.

Events

The django_socketio.events module provides a handful of events that can be subscribed to, very much like connecting receiver functions to Django signals. Each of these events are raised throughout the relevant stages of a Socket.IO request. These events represent the main approach for implementing your socket handling logic when using django-socketio.

Events are subscribed to by applying each event as a decorator to your event handler functions:

from django_socketio.events import on_message

@on_message
def my_message_handler(request, socket, context, message):
    ...

Where should these event handlers live in your Django project? They can go anywhere, so long as they're imported by Django at startup time. To ensure that your event handlers are always loaded, you can put them into a module called events.py in one of your apps listed in Django's INSTALLED_APPS setting. django-socketio looks for these modules, and will always import them to ensure your event handlers are loaded.

Each event handler takes at least three arguments: the current Django request, the Socket.IO socket the event occurred for, and a context, which is simply a dictionary that can be used to persist variables across all events throughout the life-cycle of a single WebSocket connection.

  • on_connect(request, socket, context) - occurs once when the WebSocket connection is first established.
  • on_message(request, socket, context, message) - occurs every time data is sent to the WebSocket. Takes an extra message argument which contains the data sent.
  • on_subscribe(request, socket, context, channel) - occurs when a channel is subscribed to. Takes an extra channel argument which contains the channel subscribed to.
  • on_unsubscribe(request, socket, context, channel) - occurs when a channel is unsubscribed from. Takes an extra channel argument which contains the channel unsubscribed from.
  • on_error(request, socket, context, exception) - occurs when an error is raised. Takes an extra exception argument which contains the exception for the error.
  • on_disconnect(request, socket, context) - occurs once when the WebSocket disconnects.
  • on_finish(request, socket, context) - occurs once when the Socket.IO request is finished.

Like Django signals, event handlers can be defined anywhere so long as they end up being imported. Consider adding them to their own module that gets imported by your urlconf, or even adding them to your views module since they're conceptually similar to views.

Binding Events to Channels

All events other than the on_connect event can also be bound to particular channels by passing a channel argument to the event decorator. The channel argument can contain a regular expression pattern used to match again multiple channels of similar function.

For example, suppose you implemented a chat site with multiple rooms. WebSockets would be the basis for users communicating within each chat room, however you may want to use them elsewhere throughout the site for different purposes, perhaps for a real-time admin dashboard. In this case there would be two distinct WebSocket uses, with the chat rooms each requiring their own individual channels.

Suppose each chat room user subscribes to a channel client-side using the room's ID:

var socket = new io.Socket();
var roomID = 42;
socket.connect();
socket.on('connect', function() {
    socket.subscribe('room-' + roomID);
});

Then server-side the different message handlers are bound to each type of channel:

@on_message(channel="dashboard")
def my_dashboard_handler(request, socket, context, message):
    ...

@on_message(channel="^room-")
def my_chat_handler(request, socket, context, message):
    ...

Logging

The following setting can be used to configure logging:

  • SOCKETIO_MESSAGE_LOG_FORMAT - A format string used for logging each message sent via a socket. The string is formatted using interpolation with a dictionary. The dictionary contains all the keys found in Django's request["META"], as well as TIME and MESSAGE keys which contain the time of the message and the message contents respectively. Set this setting to None to disable message logging.

Chat Demo

The "hello world" of WebSocket applications is naturally the chat room. As such django-socketio comes with a demo chat application that provides examples of the different events, channel and broadcasting features available. The demo can be found in the example_project directory of the django_socketio package. Note that Django 1.3 or higher is required for the demo as it makes use of Django 1.3's staticfiles app.

django-socketio's People

Contributors

0xflotus avatar blancheta avatar brianmckeever avatar chrisspen avatar codekoala avatar dxe4 avatar dzlabs avatar galuszkak avatar gmixo avatar nanonyme avatar pavillet avatar ravi77o avatar stephenmcd avatar thibaut-fatus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-socketio's Issues

Subscribe and unsubscribe events not being called?

I could quite possibly be doing something wrong as I have only been toying around a little so far.

I am adding a realtime component to an existing application and have defined an events.py with functions ready to process for all the different events. The problem is that the only events firing are the connect, disconnect and message events. Subscribe and unsubscribe aren't being called at all even though they are in the same events.py.

Is this an issue or is there some other way I should be binding the subscription events?

Another question, when I run my django app through apache on port 80 and have socketio connect to :8080, the cookies from :80 aren't available even though the cookies set from port :80 are available if I access the django view through :8080. This last question is not a big issue as I have ways around it, it's the first one that is my main concern.

Thanks very much for making this app available as it is filling a need for me very nicely.

django_socketio.broadcast_channel can't find clients

I'm trying to broadcast a message to all clients listening on a channel whenever a new db entry is created for a particular model. I've added a post save hook for the db model, but when trying to broadcast I get a NoSocket exception with the message:

There are no clients on the channel: ...

As far as I can tell this seems to be because the code runs on the normal server, not on the socketio server. Is there any way of dealing with this? The same error shows up when trying to use the system_message functionality in the example project.

Machine gun reloading

If you rapidly refresh with any browser, you'll eventually see something like this:

Traceback (most recent call last):
  File "/srv/pyenv/costory/lib/python2.6/site-packages/gevent/greenlet.py", line 390, in run
    result = self._run(*self.args, **self.kwargs)
  File "/srv/pyenv/costory/lib/python2.6/site-packages/socketio/transports.py", line 211, in send_into_ws
    websocket.send(self.encode(message))
  File "/srv/pyenv/costory/lib/python2.6/site-packages/geventwebsocket/websocket.py", line 25, in send
    self.socket.sendall("\x00" + message + "\xFF")
  File "/srv/pyenv/costory/lib/python2.6/site-packages/gevent/socket.py", line 504, in sendall
    data_sent += self.send(_get_memory(data, data_sent), flags)
  File "/srv/pyenv/costory/lib/python2.6/site-packages/gevent/socket.py", line 478, in send
    return sock.send(data, flags)
error: [Errno 32] Broken pipe
<Greenlet at 0x107d3e518: send_into_ws> failed with error

Traceback (most recent call last):
  File "/srv/pyenv/costory/lib/python2.6/site-packages/gevent/greenlet.py", line 390, in run
    result = self._run(*self.args, **self.kwargs)
  File "/srv/pyenv/costory/lib/python2.6/site-packages/socketio/transports.py", line 215, in read_from_ws
    message = websocket.wait()
  File "/srv/pyenv/costory/lib/python2.6/site-packages/geventwebsocket/websocket.py", line 71, in wait
    frame_str = self.rfile.read(1)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/socket.py", line 377, in read
    data = self._sock.recv(left)
  File "/srv/pyenv/costory/lib/python2.6/site-packages/gevent/socket.py", line 418, in recv
    return sock.recv(*args)
error: [Errno 54] Connection reset by peer
<Greenlet at 0x107d3e490: read_from_ws> failed with error

This appears to prevent the on_finish event from executing.

Blocking code in event handlers

I'm pretty new to this, so I may be misunderstanding something here. With that in mind --

Looking at runserver_socketio.py and the example project, there's a fair amount of blocking code in here. For instance:

def message(request, socket, context, message):
    """
    Event handler for a room receiving a message. First validates a
    joining user's name and sends them the list of users.
    """
    message = message[0]
    room = get_object_or_404(ChatRoom, id=message["room"])
    if message["action"] == "start":
        user, created = room.users.get_or_create(name=strip_tags(message["name"]))
        if not created:
            socket.send({"action": "in-use"})
        else:
            context["user"] = user
            users = [u.name for u in room.users.exclude(id=user.id)]
            socket.send({"action": "started", "users": users})
            user.session = socket.session.session_id
            user.save()
            joined = {"action": "join", "name": user.name, "id": user.id}
            socket.send_and_broadcast_channel(joined)
    else:
        try:
            user = context["user"]
        except KeyError:
            return
        if message["action"] == "message":
            message["message"] = strip_tags(message["message"])
            message["name"] = user.name
            socket.send_and_broadcast_channel(message)

All of the ORM calls will block the entire gevent server, as far as I know. You could get around this by installing a greenlet-enabled db adapter (such as psycogreen), but this doesn't really feel seamless.

I'm not sure what the right solution is here. I feel like the problem comes from wanting to support bidirectional communication in the django functions.

A possible solution:

Allow event binding based on more criteria, such as message["action"] checking (a'la what's going on with channel checking). Then run each event handler in its own thread -- or, if they had celery enabled, run it as a celery task. The event handlers wouldn't, then, be able to communicate back (or maybe that would work fine?) So we could think of these as autonomous tasks?

I'm not sure how we'd implement the above message function in this scheme -- or if it's really even possible.

{% socketio %} path error

When I run "runserver_socketio" and I try to load a web page with a typical and basic code in their views.py file, like this:

def example(request):
return render_to_response('example.html')

I get this error:

VariableDoesNotExist at /app/example/
Failed lookup for key [MEDIA_URL] in u"[[{'DJANGO_SOCKETIO_PORT': '8000'}]]"

...

Error during template rendering

In template /local/lib/python2.7/site-packages/django_socketio/templates/socketio_scripts.html, error at line 1
(Could not get exception message)

<script src="{{ STATIC_URL|default:MEDIA_URL }}js/socket.io.js"></script> # This code segment is generated by {% socketio %} template tag

Then I check my settings.py and STATIC_URL = '/static/', and MEDIA_URL = '/media/'

Meanwhile, I have solved this error with not using {% socketio %} template tag, and calling directly the js script from template HTML code.

I'm using Django 1.4

NGINX as HTTP proxy

I want to use NGINX as a forward proxy with my public ip . Using this configuration i managed to proxy using my local ip but i want it to be a public proxy using my public ip address. How can i do that ? Do i need port forwarding or some changes in my configuration ?

here is my nginx.conf:
worker_processes 1;

events {
worker_connections 1024;
}

http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
gzip on;
server {
listen 8080;
location / {
resolver 8.8.8.8;
proxy_pass http://$http_host$uri$is_args$args;
}
}
}

Put on django-socketio readme: Not ready for production

Right now django-socketio it not ready for go to production :

the dependencies are out-update of the new implementation of moderm webbrowser

the setup.py said:

[1] gevent-socketio==0.2.1 out-updated this call a require:

install_requires=("gevent-websocket",), 

This install the last version of gevent-websocket> 0.3.X but gevent-socketio==0.2.1 not work with gevent-websocket last version need gevent-websocket==0.2.3

So installing work more less even so have issues.

gevent-websocket with the new websocket improvements(as Jeffrey Gelens said) have a issue: [2] [3]

For get the django-socketio need this require:

gevent==0.13.8
gevent-socketio==0.2.1
gevent-websocket==0.2.3
django-socketio==0.3.8

then patch manually [2][3] and then it is working now.

Sorry dudes!!!
BUT:
I have 3 long nights of pain dealing with django-socketio trying to getting work.

Please put on the setup.py

install_requires=["gevent-socketio==0.2.1","gevent-websocket==0.2.3","gevent-socketio==0.2.1", "sphinx-me", "django>=1.4.8"],

The make the changes on [2] and [3] said and then the socketio works.

[1] https://github.com/abourget/gevent-socketio/blob/master/setup.py
[2] https://bitbucket.org/Jeffrey/gevent-websocket/issue/17/selfwebsocket_connection-not-defined-and
[3] https://bitbucket.org/Jeffrey/gevent-websocket/issue/11/keyerror-wsgiwebsocket

Keyword for finding bugs:

self.websocket_connection not defined
KeyError: 'wsgi.websocket

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 273: ordinal not in range(128)

Hi,

I use django-socketio in order to build a chat. The problem is when I send messages with special characters. At first, it didn't work. So I used the solution to this question: #2
It fixed my problem. But then, I don't know why, it didn't work anymore. Now, when I try to send a message with special characters, I get this error:

                  File "path/gevent/socket.py", line 503, in sendall
                  data = data.encode()

So I went to socket.py and I changed data.encode by data.encode('utf-8', 'replace'). I don't have an error anymore, the messages appear. But when I enter a special character, the last letter of my message disappear. If I enter 2 special characters, the two last characters disappear...

Any idea on how to fix that?

thank you.

Can not send Chinese

Hello error code appears when sending Chinese, I do not know why.
I sincerely thank you please help me

Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/gevent-0.13.8-py2.7-linux-x86_64.egg/gevent/greenlet.py", line 390, in run
result = self._run(_self.args, *_self.kwargs)
File "/usr/local/lib/python2.7/dist-packages/gevent_socketio-0.2.1-py2.7.egg/socketio/server.py", line 49, in handle
handler.handle()
File "/usr/local/lib/python2.7/dist-packages/gevent-0.13.8-py2.7-linux-x86_64.egg/gevent/pywsgi.py", line 180, in handle
result = self.handle_one_request()
File "/usr/local/lib/python2.7/dist-packages/gevent-0.13.8-py2.7-linux-x86_64.egg/gevent/pywsgi.py", line 314, in handle_one_request
self.handle_one_response()
File "/usr/local/lib/python2.7/dist-packages/gevent_socketio-0.2.1-py2.7.egg/socketio/handler.py", line 68, in handle_one_response
jobs = self.transport.connect(session, request_method)
File "/usr/local/lib/python2.7/dist-packages/gevent_socketio-0.2.1-py2.7.egg/socketio/transports.py", line 101, in connect
return self.handle_post_response(session)
File "/usr/local/lib/python2.7/dist-packages/gevent_socketio-0.2.1-py2.7.egg/socketio/transports.py", line 67, in handle_post_response
messages = self.decode(data)
File "/usr/local/lib/python2.7/dist-packages/gevent_socketio-0.2.1-py2.7.egg/socketio/transports.py", line 16, in decode
return self.handler.environ['socketio'].decode(data)
File "/usr/local/lib/python2.7/dist-packages/gevent_socketio-0.2.1-py2.7.egg/socketio/protocol.py", line 113, in decode
messages.append(json.loads(data[3:size]))
File "/usr/lib/python2.7/json/init.py", line 338, in loads
return _default_decoder.decode(s)
File "/usr/lib/python2.7/json/decoder.py", line 365, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib/python2.7/json/decoder.py", line 381, in raw_decode
obj, end = self.scan_once(s, idx)
ValueError: Unterminated string starting at: line 1 column 40 (char 39)
<Greenlet at 0x2b329b0: <bound method SocketIOServer.handle of <SocketIOServer at 0x28c4d90 fileno=3 address=127.0.0.1:9000>>(<socket at 0x2b36c50 fileno=[Errno 9] Bad file des, ('127.0.0.1', 48303))> failed with ValueError

on_message event not recognized

Firstly, thanks for creating this - I was on the brink of a Django + Node js solution and a considerable amount of unnecessary complexity before discovering your project.

It's likely this is user error but following the chat example fairly closely to get something up and running, and having trouble debugging.

Trying to send a simple message from Client A to Client B. Both clients call socket.subscribe() on doc ready, and I see the success event printed to the terminal. Client A then calls socket.send(), which also prints to the terminal, including the contents of the message. So far so good, except that the functions I have in my views module listening for on_message or on_subscribe events are never called. I'm not doing anything special, just:

@on_message
def message(request, socket, context):
    print 'message received'

I've been pouring over the example code, and can't see what I must be missing. I see there's logging settings, but didn't find a log file in django_socketio, gevent or geventwebsocket modules -- is there a file generated, and if so do you know where I could find it?

Exception when running ./manage.py runserver_socketio host:port command

I keep getting the exception below when I try to run the server:

SocketIOServer running on 0.0.0.0:8000

Traceback (most recent call last):
File "./manage.py", line 14, in
execute_manager(settings)
File "/home/sky/development/py_environs/socket/local/lib/python2.7/site-packages/django/core/management/init.py", line 438, in execute_manager
utility.execute()
File "/home/sky/development/py_environs/socket/local/lib/python2.7/site-packages/django/core/management/init.py", line 379, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/sky/development/py_environs/socket/local/lib/python2.7/site-packages/django/core/management/base.py", line 191, in run_from_argv
self.execute(_args, *_options.dict)
File "/home/sky/development/py_environs/socket/local/lib/python2.7/site-packages/django/core/management/base.py", line 220, in execute
output = self.handle(_args, *_options)
File "/home/sky/development/py_environs/socket/local/lib/python2.7/site-packages/django_socketio/management/commands/runserver_socketio.py", line 57, in handle
server = SocketIOServer(bind, handler, resource="socket.io")
File "/home/sky/development/py_environs/socket/local/lib/python2.7/site-packages/socketio/server.py", line 22, in init
self.namespace = kwargs.pop('namespace')
KeyError: 'namespace'
Unhandled exception in thread started by <function reload_watcher at 0xa4c9a04>
Traceback (most recent call last):
File "/home/sky/development/py_environs/socket/local/lib/python2.7/site-packages/django_socketio/management/commands/runserver_socketio.py", line 24, in reload_watcher
RELOAD = code_changed()
TypeError: 'NoneType' object is not callable

I notice that when I do the install stage I get:

Downloading/unpacking django-socketio
Downloading django-socketio-0.3.1.tar.gz (43Kb): 43Kb downloaded
Running setup.py egg_info for package django-socketio

file django_socketio.py (for module django_socketio) not found
Downloading/unpacking gevent-socketio (from django-socketio)

I'm not sure if this has anything to do with it.

AttributeError at /socket.io/ 'NoneType' object has no attribute 'session_id'

I added 'django_socketio' to my INSTALLED_APPS, and url("", include("django_socketio.urls")), to my urlpatterns. Other than that it's a pretty vanilla django 1.3 project.

Traceback


Environment:


Request Method: GET
Request URL: http://localhost:8000/socket.io/

Django Version: 1.3.1
Python Version: 2.7.1
Installed Applications:
['django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.admin',
 'django.contrib.admindocs',
 'django_socketio']
Installed Middleware:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware')


Traceback:
File "/Users/rbalfanz/.virtualenvs/django-ws/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  111.                         response = callback(request, *callback_args, **callback_kwargs)
File "/Users/rbalfanz/.virtualenvs/django-ws/lib/python2.7/site-packages/django_socketio/views.py" in socketio
  45.     CLIENTS[socket.session.session_id] = (request, socket, context)

Exception Type: AttributeError at /socket.io/
Exception Value: 'NoneType' object has no attribute 'session_id'

Fix: Error importing SocketIOServer

Hello,

First of all, thank you very much for this framework. It's been saving my life over and over again.

I had it installed in my old Mac and I didn't have the chance to update it, but I bought a new computer and when I tried to run my server using the package I just downloaded, I got stuck in the following error:

"ImportError: cannot import name SocketIOServer"

So, I took a look and figured how to fix it. The error is in the command file runserver_socketio.py located in the folder site-packages/django_socketio/management/commands/

In the line 13 it says:

"from socketio import SocketIOServer"

Then I fixed it to:

"from socketio.server import SocketIOServer"

Hope it helps.

How to proxy with nginx?

Hi, i have a next problem:
80 port is listened by nginx. Opera doesn't support CORS. So when i proxy to SocketIOServer Opera doesn't work. First i thought to redirect to 9000 port for chat room, but now i need socketio on entire site. So how to deal nginx with SocketIOServer.

P.S. One more thing. /socket.io/lib/vendor/web-socket-js/WebSocketMain.swf doesn't load - the same problem as in Issue #7. I changed WEB_SOCKET_SWF_LOCATION to http://cdn.socket.io/stable/WebSocketMain.swf, but it didn't resolve the problem with opera. I heard that WebSocketInsecure.swf could solve the problem with CORS but how to configure it?

Thank you.

edit to __init__.py

Hi.
I'm not the greatest programmer but I was playing around with django-socketio. I was having some trouble "pushing" from the server side when using djangosocket.send().

Should the code in the init.py file read (about lines 10 - 20)

def send(session_id, message):
"""
Send a message to the socket for the given session ID.
"""
from django_socketio.views import CLIENTS # I HAD TO ADD THIS LINE
try:
socket = CLIENTS[session_id][1]
except KeyError:
raise NoSocket("There is no socket with the session ID: " + session_id)
socket.send(message)

I had to put it in anyway to get it working for me.
Thanks.

Templates and static not copied during build

Hi Steve,

During build, running setup.py or during a pip install, neither templates or static directories are copied into the relevant location along with all the other files (everything else can confirm works flawlessly on set up). This means the {% socketio %} tag fails with a template error.

Copying the folders to my packages folder manually resolved the issue completely.

Cheers
Andrew

As I can create another thread to send messages?

..
from multiprocessing import Process
import os
...

def info(title):
print title
print 'module name:', name
if hasattr(os, 'getppid'): # only available on Unix
print 'parent process:', os.getppid()
print 'process id:', os.getpid()

def f(socket,session_id):
info('function f')
route = {"action": "buzz", 'foo':'bar'}
for i in range(1,5):
socked.send(route)
django_socketio.broadcast_channel(route, 'navigation')
django_socketio.send(session_id, route)

@events.on_message(channel="navigation")
def navigation(request, socket, context, message):
if message['action'] == 'theread':
try:
p = Process(target=f, args=(socket,socket.session.session_id))
p.start()
except:
print "Unexpected error thread:", sys.exc_info()[0]
...

socket.session.session_id is the same in thread that in main thread.
Why nothing is send to socket o brodcast_channel?

P.S. I need create other thread, becouse in my program i have large operation in loop.

Thanks

Django-socketio with Redis.

Hi,

I'm trying to implement Redis with django-socketio in a chat. So here is what I did:

def listener(self):
    r = redis.StrictRedis()
    r = r.pubsub()

    r.subscribe('chat')

    for m in r.listen():
        message = m['data']
        socket.send_and_broadcast_channel(message)

@events.on_message()
def messages(request, socket, context, message):
    r = redis.Redis()
    r.publish('chat', message)

But in order redis to work with gevent, we have to start a Greenlet when the user subscribes.
So we need to add something like that:

def on_subscribe(self, *args, **kwargs):
        self.spawn(self.listener)

I tried to do that with django-socketio but I didn't figured how to do it.

Would you have any idea on how can I do the equivalent with django-socketio?

Thank you very much for your help.

Feature request: Socket.io callbacks

Socket.io provides the method: socket.emit(event_name, params, callback) where callback is a function that received data sent by the server with the ack message. This is used by backbone.iosync to populate backbone.js collections and models from the server over a socket.io connection. As far as I can tell, callbacks are not supported by django-socketio, making it unusable with backbone.iosync.

None of the signals in django_socketio.events fire, ever

I've setup the libraries as instructed (installed the Ubuntu dependencies, installed django_socketio via PIP, added in the URLconf, put django_socketio into my settings.py's INSTALLED_APPS and run manage.py collectstatic). I'm not a Django notice and I've worked with socket.io before, but I'm utterly stumped!

Client-side things seem to be OK: a socket connection is established and the connect event is called; same for `disconnect, however no events fire at all on the server side.

In my models.py file, I've hooked up a function to the on_connect, on_subscribe and on_message events and none of them run (I've discovered this by setting up logging. A log entry is written and output to the console that confirms the code is being run that hooks up the events, but nothing ever happens when the events take place).

Is this an issue with latter versions of the Websockets protocol as mentioned in your docs? I'm running the socket server as sudo (tried in daemon and shell mode), but I get nothing either way.

Any ideas?
Thanks!

client_end bug

this iteration(clients.py):

Actually unsubscribe to cleanup channel data.

for channel in socket.channels:
socket.unsubscribe(channel)
and this line in unsubscribe(channels.py)
self.channels.remove(channel)
it makes the iteration to skip some channels, because its uses the same list. I fixed this making a copy of channels
channels = socket.channels[:]
for channel in channels:
socket.unsubscribe(channel)

runserver_socketio deployment webfaction

Hi,

I am trying to deploy a project that uses django-socketio in cloud provider webfaction. I have already managed to start the app using python manage.py runserver_socketio in the terminal. The problem is, when I logout, no longer the server broadcasts the messages, so the application stops working.

Maybe is something that I need to configure in httpd.conf of the apache server?

Thanks in advance,

Rodrigo Gil.

Encoding problem in chat example

I'm using the chat example, and I'm getting some problems in the encoding. Specifically, if I use the letter "á" in a message inside a room, the connection drops.

To reproduce the error, use the example along with

sudo python manage.py runserver_socketio 127.0.0.1:9000

I just start using it, so I don't have so much experience to tackle the error. Nevertheless, I hope the attached log from the socket_io helps.

127.0.0.1 - - [2013-11-04 15:36:33] "Socket.IO message: {u'action': u'start', u'room': 3, u'name': u'test_subject'}"
Traceback (most recent call last):
  File "/Users/user1/env/lib/python2.7/site-packages/gevent/greenlet.py", line 390, in run
    result = self._run(*self.args, **self.kwargs)
  File "/Users/user1/env/lib/python2.7/site-packages/socketio/server.py", line 49, in handle
    handler.handle()
  File "/Users/user1/env/lib/python2.7/site-packages/gevent/pywsgi.py", line 180, in handle
    result = self.handle_one_request()
  File "/Users/user1/env/lib/python2.7/site-packages/gevent/pywsgi.py", line 314, in handle_one_request
    self.handle_one_response()
  File "/Users/user1/env/lib/python2.7/site-packages/socketio/handler.py", line 68, in handle_one_response
    jobs = self.transport.connect(session, request_method)
  File "/Users/user1/env/lib/python2.7/site-packages/socketio/transports.py", line 101, in connect
    return self.handle_post_response(session)
  File "/Users/user1/env/lib/python2.7/site-packages/socketio/transports.py", line 67, in handle_post_response
    messages = self.decode(data)
  File "/Users/user1/env/lib/python2.7/site-packages/socketio/transports.py", line 16, in decode
    return self.handler.environ['socketio'].decode(data)
  File "/Users/user1/env/lib/python2.7/site-packages/socketio/protocol.py", line 113, in decode
    messages.append(json.loads(data[3:size]))
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 326, in loads
    return _default_decoder.decode(s)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 366, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 382, in raw_decode
    obj, end = self.scan_once(s, idx)
ValueError: Expecting object: line 1 column 83 (char 83)
<Greenlet at 0x1027cd5f0: <bound method SocketIOServer.handle of <SocketIOServer at 0x10270e2d0 fileno=3 address=127.0.0.1:9000>>(<socket at 0x10275f450 fileno=[Errno 9] Bad file d, ('127.0.0.1', 57567))> failed with ValueError

DJANGO_SOCKETIO_PORT error in example project

  1. Install django-socketio via setup.py install (latest HEAD)
  2. Run python manage.py runserver_socketio in one terminal
  3. Run python manage.py runserver in another
  4. Navigate to http://127.0.0.1:8000/
  5. Create a room

The error Caught KeyError while rendering: 'DJANGO_SOCKETIO_PORT' appears.

It looks like it's not in the environment (why would it be?) Maybe I'm missing something here, though. A simple fix (?) is to do:

from django_socketio import settings as socketio_settings

then set it to socketio_settings.PORT.

Chat -- authentication?

Hey gang, sorry to bother!

I really appreciate all this work, it was super easy to setup and use. I'm confused on the best practices of setting up some kind of auth also. I'm making a chat/partner finder for online games, people login and there's a Terminal you can chat with other users at.

It would be totally fine if I could only force WebSocket (no long polling stuff or anything) so I can send cookies, right?

Updating django-socketio to use the latest socketio client (0.8.5)

I am working on a web app using django and socket.io, and have been trying to use django-socketio to connect the two. I noticed that the the socketio client packaged with the app was using xhr-multipart and xhr-polling on the latest FireFox (10.0.2) and Chrome (17.0.963.56), respectively. I tried replacing the client library with the latest version (0.8.5) but now I get an error on the server side:

 Traceback (most recent call last):
  File "/home/taa/env/lib/python2.6/site-packages/gevent/pywsgi.py", line 438, in handle_one_response
    self.run_application()
  File "/home/taa/env/lib/python2.6/site-packages/gevent/pywsgi.py", line 425, in run_application
    self.process_result()
  File "/home/taa/env/lib/python2.6/site-packages/gevent/pywsgi.py", line 416, in process_result
    self.write(data)
  File "/home/taa/env/lib/python2.6/site-packages/gevent/pywsgi.py", line 373, in write
    self.socket.sendall(msg)
  File "/home/taa/env/lib/python2.6/site-packages/gevent/socket.py", line 504, in sendall
    data_sent += self.send(_get_memory(data, data_sent), flags)
  File "/home/taa/env/lib/python2.6/site-packages/gevent/socket.py", line 490, in send
    return sock.send(data, flags)
error: [Errno 32] Broken pipe
<SocketIOServer fileno=3 address=0.0.0.0:8182>: Failed to handle request:
  request = GET /socket.io/1/?t=1330535867416 HTTP/1.1 from ('216.16.232.86', 1154)
  application = <django.contrib.staticfiles.handlers.StaticFilesHandler object at 0x2d0b950>

x.x.x.x - - [2012-02-29 11:17:52] "GET /socket.io/1/?t=1330535867416 HTTP/1.1" 500 0 0.384851

Any idea what the issue may be? And any plans to upgrade the socketio client library packaged with the app or make the app compatible or socketio-client v0.8.5?

I don't know much about the WebSocket protocol, but I'm willing to help however I can, such as testing different browsers and what not.

unexpected keyword argument 'call_wsgi_app'

  1. I'm running windows and I'm having this strange behaviour trying to run the sample chat app. The first attempts to runserver_socketio always give me the following error:
self.handle_one_response(call_wsgi_app=False)
TypeError: handle_one_response() got an unexpected keyword argument 'call_wsgi_app'
<Greenlet at 0x2824260: <bound method SocketIOServer.handle of <SocketIOServer a
t 0x27a7930 fileno=164 address=127.0.0.1:9000>>(<socket at 0x28bd650 fileno=[Err
no 9] Bad file des, ('127.0.0.1', 7480))> failed with TypeError

After several attempts all runs fine without exceptions. When I restart my computer, the same thing happens again. I'm looking for a more stable solution.

  1. My project partner, who is running mac osx, isn't able to run the chat app as well. He can never run the app completely. Every time he joins a room, the page is blank and he gets this error:
Internal Server Error: /socket.io/xhr-polling//1378592279609
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site
 packages/django/core/handlers/base.py", line 115, in get_response
    response = callback(request, *callback_args, **callback_kwargs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django_socketio/views.py",     line 19, in socketio
    socket = SocketIOChannelProxy(request.environ["socketio"])
KeyError: 'socketio'
127.0.0.1 - - [2013-09-08 00:17:59] "GET /socket.io/xhr-polling//1378592279609 HTTP/1.1" 500 49818 0.152489 

broadcasting, or sending any message from shell does not work

I have a client connected.

Then I go and run ./manage.py shell
import django_socketio
django_socketio.broadcast('test')

After this, I always get:
NoSocket: There are no clients.

even though there clearly are.

Is this expected behavior? Can I not call any of these methods from outside the special socket io server? Is there any way to bypass this? It is not very useful to me if I can't interact with it from the "normal" HTTP server.

Thanks

Cross Origin Problem

Hey guys, I'm having trouble to run my server correctly.

I'm running my django server through the port 8088 and the socketio server in the port 9000. My connections are being logged in the socketio correctly:

"127.0.0.1 - - [2012-11-06 15:15:05] "GET /socket.io/websocket HTTP/1.1" 500 52474 0.120885
127.0.0.1 - - [2012-11-06 15:15:10] "GET /socket.io/xhr-polling//1352222110658 HTTP/1.1" 500 50095 0.051357"

But Chrome is having a cross origin problem:

"XMLHttpRequest cannot load http://localhost:9000/socket.io/xhr-polling//1352221950619. Origin http://localhost:8088 is not allowed by Access-Control-Allow-Origin."

So, please, I need some help to solve this.

Probably it's as simple as telling my SocketIO server too allow connections from anywhere, but I couldn't figure it out.

broadcast_channel will only send to channels that the socket is subscribed to.

The implementation of broadcast_channel limits the socket to only sending to channels that it is currently subscribed to. This limitation looks like as if it was was deliberately added, but I can't see a reason for not letting the socket send to channels it hasn't subscribed to. Admittedly, I may be missing something. Thoughts?

def broadcast_channel(self, message, channel=None):
    """
    Send the given message to all subscribers for the channel
    given. If no channel is given, send to the subscribers for
    all the channels that this socket is subscribed to.
    """
    if channel in self.channels:
        channels = [channel]
    else:
        channels = self.channels
    .......

Deploying on webfaction

How to run it on webfaction without using runserver_socketio? (successfully run it using runserver_socketio)

Enable compatibility with Django 1.3

Hi,
We've been using this project on django 1.3. It works really well, thanks.

The only thing we had to tweak was an import in the packages root urls.py to make it compatible with 1.3:

  • django_socketio/urls.py
# Patch for django 1.3 compatibility
try:
    from django.conf.urls import patterns, url
except ImportError:
    from django.conf.urls.defaults import patterns, url

Would you consider merging this fix in and updating the release on pypi?

Thanks,

John

How to get channel inside function decorated by @on_message(channel="^room-") ?

Hi!

Is there any chance to get channel inside function decorated by:


@on_message(channel="^room-")
def my_chat_handler(request, socket, context, message):
    # TODO: How can I get channel
    ...

I can get all channels connected with socket - but I just need this one, which sends message.

Currently I'm sending channel in message directly from JavaScript in my client - but I want to secure communication, by channel recognition on server.

I searched a lot but found nothing (Maybe I'm asking google wrong questions?). Maybe answer is very simple and obwious to You.

Please, help me. What can I do?

How to use django-socketio functions outside of events.py

Hi (sorry for my poor english):

I try to broadcast messages with "broadcast" function in a Django command management file, but always I get an exception (NoSocket, "There are no clients") and in the client-side I not get any message.

In my command management file I wrote:

from django_socketio import NoSocket, broadcast
from time import sleep

while True:
    try:
        broadcast({'message': 'Hello World'})
    except NoSocket, e:
        print e

    sleep(15)

And in my template file I wrote:

{% load socketio_tags %}

{% socketio %}

<script type="text/javascript">
    var socket = new io.Socket();
    socket.connect();

    socket.on('message', function(data) {
        console.log(data.message);
    });
</script>

Meanwhile, when I use the same python script inside events.py file with an "@on_connect" decorator, there are no problems.

I use Django 1.4.1 and django-socketio 0.3.5

Thanks for any help you can give me.

Bug in .travis.yml

The apt-get command is mistakenly as before_script when it should be before_install. This causes the headers not to be available when pip is run which causes pip to fail.

Adding django-socketio to existing Apache/mod_wsgi/Django site

Hi,
I've read the docs and google around a lot, but I'm still confused as to how to extend an existing Apache/mod_wsgi/Django site to include some django-socketio functionality.

Can the runserver_socketio command run in parallel to Apache and just use a different port? Or does the custom server need to handle all requests?

I imagine many devs would be interested in adding this to an existing traditional project, so a tutorial would be really helpful.

BTW, I've also posted this question at stackoverflow.

Thanks very much,
Chris

[Errno 13] Permission denied: ('0.0.0.0', 843)

hi i got this error when running your chat application.

python manage.py runserver_socketio 

SocketIOServer running on 127.0.0.1:9000

FAILED to start flash policy server: [Errno 13] Permission denied: ('0.0.0.0', 843)

is this because i am running this inside a virtualenv?

Messages aren't being sent in example project

  1. Install django-socketio via setup.py install (latest HEAD)
    a. Fix django-socketio as described in ticket #15.
  2. Run python manage.py runserver_socketio in one terminal
  3. Run python manage.py runserver in another
  4. Navigate to http://127.0.0.1:8000/
  5. Create a room
  6. Type something into the text box and press enter.

Result: nothing happens. No output in either terminal.

When adding a room I see this:

127.0.0.1 - - [2012-02-01 20:22:25] "Socket.IO message: ['subscribe', 'room-11']"

I see an error about a missing file -- a request to /socket.io/lib/vendor/web-socket-js/WebSocketMain.swf. (should that also be fixed?)

I fix (I think?) the swf issue by downloading that WebSocketMain.swf file from https://github.com/LearnBoost/socket.io-client and just hard-coding the path into the socket.io.js file.

After 'fixing' the swf issue, when I type something into the chat box and press enter I see, in the socketio server log:

127.0.0.1 - - [2012-02-01 20:40:39] "Socket.IO message: [{u'action': u'start', u'room': 9, u'name': u'this is a message typed into the chat box'}]"

I might be missing something obvious here. Tested in FF and Chrome latest.

The connection always is disconnected automatically by server in 60seconds.

I wanna deploy my app with django_socketio on the nginx. I refer this article http://www.stephendiehl.com/?p=309. It is great.Anything is fine.
I run it on Firefox 11.0 debian squezze.
BUT, the connection will be disconnected automatically by server in 60seconds. whatever, I loop to send a check message to server, and let server return a message in each 5s 10s 15s 30s. Anyway, the server always disconnects in 60 seconds. I saw it connects with xhr-mulitpart in FF. And It's good with xhr-polling in chrome.
What's problem for this? BTW, it runs fine in development env.

Apache

Hi Stephenmcd ,

Do you have documentation to put socket.io django in production with the Apache Server?

Best Regards,
Eduardo Lujan

Language change

I just noticed that when I run 'runserver_socketio', my language setting of my settings.py is not respected anymore. The language is back to english.

Do you have any idea on how I can change it?

Thank you for your help.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.