socketio.namespace
¶
Namespace initialization¶
You can override this method:
Event flow¶
This is an attempt at catching the gotchas of the Socket.IO protocol, which, for historical reasons, sometimes have weird event flow.
The first function to fire is initialize()
, which will be called
only if there is an incoming packet for the Namespace. A successful
javascript call to io.connect()
is not sufficient for
gevent-socketio
to trigger the creation of a Namespace object.
Some event has to flow from the client to the server. The connection
will appear to have succeeded from the client’s side, but that is
because gevent-socketio
maintains the virtual socket up and running
before it hits your application. This is why it is a good pratice to
send a packet (often a login
, or subscribe
or connect
JSON
event, with io.emit()
in the browser).
If you’re using the GLOBAL_NS, the recv_connect()
will not fire on
your namespace, because when the connection is opened, there is no
such packet sent. The connect
packet is only sent over (and
explicitly sent) by the javascript client when it tries to communicate
with some “non-global” namespaces. That is why it is recommended to
always use namespaces, to avoid having a different behavior for your
different namespaces. It also makes things explicit in your
application, when you have something such as /chat
, or
/live_data
. Before a certain version of Socket.IO, there was only
a global namespace, and so this behavior was kept for backwards
compatibility.
Then flows the normal events, back and forth as described elsewhere (elsewhere??).
Upon disconnection, here is what happens: [INSERT HERE the details flow of disconnection handling, events fired, physical closing of the connection and ways to terminate a socket, when is the Namespace killed, the state of the spawn’d processes for each Namespace and each virtsocket. This really needs to be done, and I’d appreciate having people investigate this thoroughly]
There you go :)
Namespace instance properties¶
BaseNamespace.
session
¶The session is a simple
dict
that is created with eachSocket
instance, and is copied to each Namespace created under it. It is a general purpose store for any data you want to associated with an openSocket
.
BaseNamespace.
request
¶This is the
request
object (or really, any object) that you have passed as therequest
parameter to thesocketio_manage()
function.
BaseNamespace.
ns_name
¶The name of the namespace, like
/chat
or the empty string, for the “global” namespace.
BaseNamespace.
environ
¶The
environ
WSGI dictionary, as it was received upon reception of the first request that established the virtual Socket. This will never contain the subsequentenviron
for the next polling, so beware when using cookie-based sessions (like Beaker).
BaseNamespace.
socket
¶A reference to the
Socket
instance this namespace is attached to.
Sending data¶
Functions to send data through the socket:
Dealing with incoming data¶
BaseNamespace.
exception_handler_decorator
(fn)¶This method can be a static, class or bound method (that is, with
@staticmethod
,@classmethod
or without). It receives one single parameter, and that parameter will be the function the framework is trying to call because some information arrived from the remote client, for instance:on_*
andrecv_*
functions that you declared on your namespace.The decorator is also used to wrap called to
self.spawn(self.job_something)
, so that if anything happens after you’ve spawn’d a greenlet, it will still catch it and handle it.It should return a decorator with exception handling properly dealt with. For example:
import traceback, sys import logging def exception_handler_decorator(self, fn): def wrap(*args, **kwargs): try: return fn(*args, **kwargs) except Exception, e: stack = traceback.format_exception(*sys.exc_info()) db.Evtrack.write("socketio_exception", {"error": str(e), "trace": stack}, self.request.email) logging.getLogger('exc_logger').exception(e) return wrapYou would override this method only if you are not completely satisfied with the automatic dispatching to
on_
-prefixed methods. You could then implement your own dispatch. See the source code for inspiration.
Process management¶
Managing the different callbacks, greenlets and tasks you spawn from this namespace:
ACL system¶
The ACL system grants access to the different
on_*()
andrecv_*()
methods of your subclass.Developers will normally override
get_initial_acl()
to return a list of the functions they want to initially open. Usually, it will be anon_connect
event handler, that will perform authentication and/or authorization, set some variables on the Namespace, and then open up the rest of the Namespace usinglift_acl_restrictions()
or more granularly withadd_acl_method()
anddel_acl_method()
. It is also possible to check these things insideinitialize()
when, for example, you have authenticated a Global Namespace object, and you want to re-use those credentials or authentication infos in a new Namespace:# GLOBAL_NS = '' class MyNamespace(BaseNamespace): ... def initialize(self): self.my_auth = MyAuthObjet() if self.socket[GLOBAL_NS].my_auth.logged_in == True: self.my_auth.logged_in = TrueThe content of the ACL is a list of strings corresponding to the full name of the methods defined on your subclass, like:
"on_my_event"
or"recv_json"
.This function is used internally, but can be useful to the developer:
This is the attribute where the allowed methods are stored, as a list of strings, or a single
None
:.. autoattribute:: allowed_methods
Low-level methods¶
Packet dispatching methods. These functions are normally not overriden if you are satisfied with the normal dispatch behavior: