def post(self, session_id): # Get session self.session = self._get_session(session_id) # Can not send messages to closed session or if preflight() failed if self.session.is_closed or not self.preflight(): raise HTTPError(401) # Socket.io always send data utf-8 encoded. data = self.request.body # IE XDomainRequest support if not data.startswith('d='): logging.error('Malformed JSONP POST request') raise HTTPError(403) # Grab data data = urllib.unquote(data[2:]).decode('utf-8') # If starts with double quote, it is json encoded (socket.io workaround) if data.startswith(u'"'): data = proto.json_load(data) # Process packets one by one packets = proto.decode_frames(data) for p in packets: try: self.session.raw_message(p) except Exception: # Close session if something went wrong self.session.close() self.set_header('Content-Type', 'text/plain; charset=UTF-8') self.finish()
def post(self, session_id): try: # Stats self.server.stats.connection_opened() # Get session self.session = self._get_session(session_id) # Can not send messages to closed session or if preflight() failed if self.session.is_closed or not self.preflight(): raise HTTPError(401) # Socket.io always send data utf-8 encoded. data = self.request.body # IE XDomainRequest support if not data.startswith('d='): logging.error('Malformed JSONP POST request') raise HTTPError(403) # Grab data data = urllib.unquote_plus(data[2:]).decode('utf-8') # If starts with double quote, it is json encoded (socket.io workaround) if data.startswith(u'"'): data = proto.json_load(data) # Process packets one by one packets = proto.decode_frames(data) # Tracking self.server.stats.on_packet_recv(len(packets)) for p in packets: try: self.session.raw_message(p) except Exception: # Close session if something went wrong self.session.close() self.set_header('Content-Type', 'text/plain; charset=UTF-8') self.finish() finally: self.server.stats.connection_closed()
def raw_message(self, msg): """Socket.IO message handler. `msg` Raw socket.io message to handle """ try: logging.debug('>>> ' + msg) parts = msg.split(':', 3) if len(parts) == 3: msg_type, msg_id, msg_endpoint = parts msg_data = None else: msg_type, msg_id, msg_endpoint, msg_data = parts # Packets that don't require valid endpoint if msg_type == proto.DISCONNECT: if not msg_endpoint: self.close() else: self.disconnect_endpoint(msg_endpoint) return elif msg_type == proto.CONNECT: if msg_endpoint: self.connect_endpoint(msg_endpoint) else: # TODO: Disconnect? logging.error('Invalid connect without endpoint') return # All other packets need endpoints conn = self.get_connection(msg_endpoint) if conn is None: logging.error('Invalid endpoint: %s' % msg_endpoint) return if msg_type == proto.HEARTBEAT: self._missed_heartbeats = 0 elif msg_type == proto.MESSAGE: # Handle text message conn.on_message(msg_data) if msg_id: self.send_message(proto.ack(msg_endpoint, msg_id)) elif msg_type == proto.JSON: # Handle json message conn.on_message(proto.json_load(msg_data)) if msg_id: self.send_message(proto.ack(msg_endpoint, msg_id)) elif msg_type == proto.EVENT: # Javascript event event = proto.json_load(msg_data) # TODO: Verify if args = event.get('args', []) won't be slower. args = event.get('args') if args is None: args = [] ack_response = None # It is kind of magic - if there's only one parameter # and it is dict, unpack dictionary. Otherwise, pass # in args if len(args) == 1 and isinstance(args[0], dict): # Fix for the http://bugs.python.org/issue4978 for older Python versions str_args = dict( (str(x), y) for x, y in args[0].iteritems()) ack_response = conn.on_event(event['name'], kwargs=str_args) else: ack_response = conn.on_event(event['name'], args=args) if msg_id: if msg_id.endswith('+'): msg_id = msg_id[:-1] self.send_message( proto.ack(msg_endpoint, msg_id, ack_response)) elif msg_type == proto.ACK: # Handle ACK ack_data = msg_data.split('+', 2) data = None if len(ack_data) > 1: data = proto.json_load(ack_data[1]) conn.deque_ack(int(ack_data[0]), data) elif msg_type == proto.ERROR: # TODO: Pass it to handler? logging.error('Incoming error: %s' % msg_data) elif msg_type == proto.NOOP: pass except Exception, ex: logging.exception(ex) # TODO: Add global exception callback? raise
def raw_message(self, msg): """Socket.IO message handler. `msg` Raw socket.io message to handle """ try: logging.debug('>>> ' + msg) parts = msg.split(':', 3) if len(parts) == 3: msg_type, msg_id, msg_endpoint = parts msg_data = None else: msg_type, msg_id, msg_endpoint, msg_data = parts # Packets that don't require valid endpoint if msg_type == proto.DISCONNECT: if not msg_endpoint: self.close() else: self.disconnect_endpoint(msg_endpoint) return elif msg_type == proto.CONNECT: if msg_endpoint: self.connect_endpoint(msg_endpoint) else: # TODO: Disconnect? logging.error('Invalid connect without endpoint') return # All other packets need endpoints conn = self.get_connection(msg_endpoint) if conn is None: logging.error('Invalid endpoint: %s' % msg_endpoint) return if msg_type == proto.HEARTBEAT: self._missed_heartbeats = 0 elif msg_type == proto.MESSAGE: # Handle text message conn.on_message(msg_data) if msg_id: self.send_message(proto.ack(msg_endpoint, msg_id)) elif msg_type == proto.JSON: # Handle json message conn.on_message(proto.json_load(msg_data)) if msg_id: self.send_message(proto.ack(msg_endpoint, msg_id)) elif msg_type == proto.EVENT: # Javascript event event = proto.json_load(msg_data) # TODO: Verify if args = event.get('args', []) won't be slower. args = event.get('args') if args is None: args = [] ack_response = None # It is kind of magic - if there's only one parameter # and it is dict, unpack dictionary. Otherwise, pass # in args if len(args) == 1 and isinstance(args[0], dict): # Fix for the http://bugs.python.org/issue4978 for older Python versions str_args = dict((str(x), y) for x, y in args[0].iteritems()) ack_response = conn.on_event(event['name'], kwargs=str_args) else: ack_response = conn.on_event(event['name'], args=args) if msg_id: if msg_id.endswith('+'): msg_id = msg_id[:-1] self.send_message(proto.ack(msg_endpoint, msg_id, ack_response)) elif msg_type == proto.ACK: # Handle ACK ack_data = msg_data.split('+', 2) data = None if len(ack_data) > 1: data = proto.json_load(ack_data[1]) conn.deque_ack(int(ack_data[0]), data) elif msg_type == proto.ERROR: # TODO: Pass it to handler? logging.error('Incoming error: %s' % msg_data) elif msg_type == proto.NOOP: pass except Exception, ex: logging.exception(ex) # TODO: Add global exception callback? raise
def raw_message(self, msg): """Socket.IO message handler. `msg` Raw socket.io message to process. """ try: logging.debug('>>> ' + msg) parts = msg.split(':', 3) if len(parts) == 3: msg_type, msg_id, msg_endpoint = parts msg_data = None else: msg_type, msg_id, msg_endpoint, msg_data = parts # Packets that don't require valid endpoint if msg_type == proto.DISCONNECT: if not msg_endpoint: self.close() else: self.disconnect_endpoint(msg_endpoint) return elif msg_type == proto.CONNECT: if msg_endpoint: self.connect_endpoint(msg_endpoint) else: # TODO: Disconnect? logging.error('Invalid connect without endpoint') return # All other packets need endpoints conn = self.get_connection(msg_endpoint) if conn is None: logging.error('Invalid endpoint: %s' % msg_endpoint) return if msg_type == proto.HEARTBEAT: self._missed_heartbeats = 0 elif msg_type == proto.MESSAGE: # Handle text message conn.on_message(msg_data) if msg_id: self.send_message(proto.ack(msg_endpoint, msg_id)) elif msg_type == proto.JSON: # Handle json message conn.on_message(proto.json_load(msg_data)) if msg_id: self.send_message(proto.ack(msg_endpoint, msg_id)) elif msg_type == proto.EVENT: # Javascript event event = proto.json_load(msg_data) args = event['args'] # It is kind of magic - if there's only one parameter # and it is dict, unpack dictionary. Otherwise, pass # as *args if len(args) == 1 and isinstance(args[0], dict): conn.on_event(event['name'], **args[0]) else: conn.on_event(event['name'], *args) if msg_id: self.send_message(proto.ack(msg_endpoint, msg_id)) elif msg_type == proto.ACK: # Handle ACK ack_data = msg_data.split('+', 2) # TODO: Support custom data sent from the server conn.deque_ack(int(ack_data[0])) elif msg_type == proto.ERROR: # TODO: Pass it to handler? logging.error('Incoming error: %s' % msg_data) elif msg_type == proto.NOOP: pass except Exception, ex: logging.exception(ex) # TODO: Add global exception callback? raise