def testDoubleConvert(self): """ Checks the beheavior after a second call to to_jabsorb """ value = {"list": [1, 2, 3], "tuple": (1, 2, 3), "set": {1, 2, 3}, "dict": {"a": "b", "c": "d"}, "int": 42, "float": 3.14, None: None, 3.10: 51} # Double conversion: no modification on second pass first = jabsorb.to_jabsorb(value) second = jabsorb.to_jabsorb(first) self.assertDictEqual(second, first) # Double revert revert_second = jabsorb.from_jabsorb(second) revert_first = jabsorb.from_jabsorb(revert_second) # Check results self.assertDictEqual(revert_second, value) self.assertDictEqual(revert_first, value)
def wrapped_call(*args, **kwargs): """ Wrapped call """ # Get the method from the proxy method = getattr(proxy, "{0}.{1}".format(self.__name, name)) # Convert arguments args = [jabsorb.to_jabsorb(arg) for arg in args] kwargs = dict((key, jabsorb.to_jabsorb(value)) for key, value in kwargs.items()) result = method(*args, **kwargs) return jabsorb.from_jabsorb(result)
def __send_message(self, msgtype, target, message, parent_uid=None): """ Prepares and sends a message over XMPP :param msgtype: Kind of message (chat or groupchat) :param target: Target JID or MUC room :param message: Herald message bean :param parent_uid: UID of the message this one replies to (optional) """ # Convert content to JSON if message.subject in herald.SUBJECTS_RAW: content = to_str(message.content) else: content = json.dumps(jabsorb.to_jabsorb(message.content), default=utils.json_converter) # Prepare an XMPP message, based on the Herald message xmpp_msg = self._bot.make_message(mto=target, mbody=content, msubject=message.subject, mtype=msgtype) xmpp_msg['thread'] = message.uid if parent_uid: xmpp_msg['parent_thread'] = parent_uid # Store message content self._probe.store( herald.PROBE_CHANNEL_MSG_CONTENT, {"uid": message.uid, "content": content} ) # Send it, using the 1-thread pool, and wait for its execution future = self.__pool.enqueue(xmpp_msg.send) return future.result()
def to_json(msg): """ Returns a JSON string representation of this message """ result = {} # herald specification version #result[herald.MESSAGE_HERALD_VERSION] = herald.HERALD_SPECIFICATION_VERSION # headers result[herald.MESSAGE_HEADERS] = {} if msg.headers is not None: for key in msg.headers: result[herald.MESSAGE_HEADERS][key] = msg.headers.get(key) or None # subject result[herald.MESSAGE_SUBJECT] = msg.subject # content if msg.content is not None: if isinstance(msg.content, str): # string content result[herald.MESSAGE_CONTENT] = msg.content else: # jaborb content result[herald.MESSAGE_CONTENT] = jabsorb.to_jabsorb(msg.content) # metadata result[herald.MESSAGE_METADATA] = {} if msg.metadata is not None: for key in msg.metadata: result[ herald.MESSAGE_METADATA][key] = msg.metadata.get(key) or None return json.dumps(result, default=herald.utils.json_converter)
def to_json(msg): """ Returns a JSON string representation of this message """ result = {} # herald specification version #result[herald.MESSAGE_HERALD_VERSION] = herald.HERALD_SPECIFICATION_VERSION # headers result[herald.MESSAGE_HEADERS] = {} if msg.headers is not None: for key in msg.headers: result[herald.MESSAGE_HEADERS][key] = msg.headers.get(key) or None # subject result[herald.MESSAGE_SUBJECT] = msg.subject # content if msg.content is not None: if isinstance(msg.content, str): # string content result[herald.MESSAGE_CONTENT] = msg.content else: # jaborb content result[herald.MESSAGE_CONTENT] = jabsorb.to_jabsorb(msg.content) # metadata result[herald.MESSAGE_METADATA] = {} if msg.metadata is not None: for key in msg.metadata: result[herald.MESSAGE_METADATA][key] = msg.metadata.get(key) or None return json.dumps(result, default=herald.utils.json_converter)
def testMirror(self): """ Tests the result of to_jabsorb + from_jabsorb """ value = { "list": [1, 2, 3], "tuple": (1, 2, 3), "set": set((1, 2, 3)), "dict": { "a": "b", "c": "d" }, "int": 42, "float": 3.14, None: None, 3.10: 51 } # Convert to Jabsorb jabsorb_value = jabsorb.to_jabsorb(value) # ... back to "normal" Python revert_value = jabsorb.from_jabsorb(jabsorb_value) # Check content self.assertDictEqual(revert_value, value)
def do_POST(self, request, response): """ Handle a POST request :param request: The HTTP request bean :param request: The HTTP response handler """ # Get the request JSON content data = jsonrpclib.loads(to_str(request.read_data())) # Convert from Jabsorb data = jabsorb.from_jabsorb(data) # Dispatch try: result = self._unmarshaled_dispatch(data, self._simple_dispatch) except NoMulticallResult: # No result (never happens, but who knows...) result = None if result is not None: # Convert result to Jabsorb if 'result' in result: result['result'] = jabsorb.to_jabsorb(result['result']) # Store JSON result = jsonrpclib.jdumps(result) else: # It was a notification result = '' # Send the result response.send_content(200, result, 'application/json-rpc')
def __prepare_message(self, message, parent_uid=None): """ Prepares a HTTP request. :param message: The Message bean to send :param parent_uid: UID of the message this one replies to (optional) :return: A (headers, content) tuple """ # Prepare headers headers = {'content-type': CONTENT_TYPE_JSON, 'herald-subject': message.subject, 'herald-uid': message.uid, 'herald-sender-uid': self.__peer_uid, 'herald-timestamp': int(time.time() * 1000), 'herald-port': self.__access_port, 'herald-path': self.__access_path} if parent_uid: headers['herald-reply-to'] = parent_uid if message.subject in herald.SUBJECTS_RAW: content = to_str(message.content) else: # Convert content to JSON jabsorb_content = jabsorb.to_jabsorb(message.content) content = json.dumps(jabsorb_content, default=utils.json_converter) return headers, content
def testCustomClass(self): """ Tests the conversion of a custom class """ # Basic class class Custom(object): javaClass = "test.Custom" def __init__(self): self.value = str(uuid.uuid4()) self._value = str(uuid.uuid4()) self.__value = str(uuid.uuid4()) # Convert it value = Custom() jabsorb_value = jabsorb.to_jabsorb(value) revert = jabsorb.from_jabsorb(jabsorb_value) # Check Jabsorb public value self.assertEqual(jabsorb_value[jabsorb.JAVA_CLASS], Custom.javaClass) self.assertEqual(jabsorb_value['value'], value.value) # Check absence of private value self.assertNotIn('_value', jabsorb_value) self.assertNotIn('__value', jabsorb_value) self.assertNotIn('_Custom__value', jabsorb_value) # Check revert value self.assertEqual(revert[jabsorb.JAVA_CLASS], Custom.javaClass) self.assertEqual(revert['value'], value.value) self.assertEqual(revert.javaClass, Custom.javaClass) self.assertEqual(revert.value, value.value)
def herald_message(self, herald_svc, message): """ Received a message from Herald :param herald_svc: The Herald service :param message: A message bean """ result = self._dispatcher.dispatch(message.content) herald_svc.reply(message, jabsorb.to_jabsorb(result), SUBJECT_REPLY)
def __call__(self, *args, **kwargs): """ Method is being called """ # Forge the request if args: args = [jabsorb.to_jabsorb(arg) for arg in args] elif kwargs: kwargs = {key: jabsorb.to_jabsorb(value) for key, value in kwargs.items()} request = jsonrpclib.dumps(args or kwargs, self.__name, encoding='utf-8') # Send it reply_message = self.__send(self.__peer, self.__subject, request) # Parse the reply and check for errors result = jabsorb.from_jabsorb(jsonrpclib.loads(reply_message.content)) jsonrpclib.jsonrpc.check_for_errors(result) return result['result']
def do_GET(self, _, response): """ Handles a GET request: sends the description of the local peer :param _: The HTTP request bean :param response: The HTTP response handler """ # pylint: disable=C0103 peer_dump = self._directory.get_local_peer().dump() jabsorb_content = jabsorb.to_jabsorb(peer_dump) content = json.dumps(jabsorb_content, default=utils.json_converter) response.send_content(200, content, CONTENT_TYPE_JSON)
def do_GET(self, request, response): """ Handles a GET request: sends the description of the local peer :param request: The HTTP request bean :param response: The HTTP response handler """ # pylint: disable=C0103 peer_dump = self._directory.get_local_peer().dump() jabsorb_content = jabsorb.to_jabsorb(peer_dump) content = json.dumps(jabsorb_content, default=utils.json_converter) response.send_content(200, content, CONTENT_TYPE_JSON)
def __call__(self, *args, **kwargs): """ Method is being called """ # Forge the request if args: args = [jabsorb.to_jabsorb(arg) for arg in args] elif kwargs: kwargs = { key: jabsorb.to_jabsorb(value) for key, value in kwargs.items() } request = jsonrpclib.dumps(args or kwargs, self.__name, encoding='utf-8') # Send it reply_message = self.__send(self.__peer, self.__subject, request) # Parse the reply and check for errors result = jabsorb.from_jabsorb(jsonrpclib.loads(reply_message.content)) jsonrpclib.jsonrpc.check_for_errors(result) return result['result']
def testJsonAndJavaClass(self): """ Tests the conservation of the __jsonclass__ attribute """ for has_json in (True, False): for has_java in (True, False): if not any((has_json, has_java)): # Out of the scope of this test continue # Prepare a fake bean value = { "list": [1, 2, 3], "tuple": (1, 2, 3), "set": set((1, 2, 3)), "dict": { "a": "b", "c": "d" }, "int": 42, "float": 3.14, None: None, 3.10: 51 } if has_json: value[jabsorb.JSON_CLASS] = [1, 2, 3, [4, 5]] if has_java: value[jabsorb.JAVA_CLASS] = 'test.Bean' # Convert it jabsorb_value = jabsorb.to_jabsorb(value) # Check the value of the JSON class if has_json: self.assertEqual(jabsorb_value[jabsorb.JSON_CLASS], value[jabsorb.JSON_CLASS]) if has_java: self.assertEqual(jabsorb_value[jabsorb.JAVA_CLASS], value[jabsorb.JAVA_CLASS]) # Revert revert = jabsorb.from_jabsorb(jabsorb_value) self.assertDictEqual(revert, value)
def testJsonAndJavaClass(self): """ Tests the conservation of the __jsonclass__ attribute """ for has_json in (True, False): for has_java in (True, False): if not any((has_json, has_java)): # Out of the scope of this test continue # Prepare a fake bean value = {"list": [1, 2, 3], "tuple": (1, 2, 3), "set": {1, 2, 3}, "dict": {"a": "b", "c": "d"}, "int": 42, "float": 3.14, None: None, 3.10: 51} if has_json: value[jabsorb.JSON_CLASS] = [1, 2, 3, [4, 5]] if has_java: value[jabsorb.JAVA_CLASS] = 'test.Bean' # Convert it jabsorb_value = jabsorb.to_jabsorb(value) # Check the value of the JSON class if has_json: self.assertEqual(jabsorb_value[jabsorb.JSON_CLASS], value[jabsorb.JSON_CLASS]) if has_java: self.assertEqual(jabsorb_value[jabsorb.JAVA_CLASS], value[jabsorb.JAVA_CLASS]) # Revert revert = jabsorb.from_jabsorb(jabsorb_value) self.assertDictEqual(revert, value)
def testMirror(self): """ Tests the result of to_jabsorb + from_jabsorb """ value = {"list": [1, 2, 3], "tuple": (1, 2, 3), "set": {1, 2, 3}, "dict": {"a": "b", "c": "d"}, "int": 42, "float": 3.14, None: None, 3.10: 51} # Convert to Jabsorb jabsorb_value = jabsorb.to_jabsorb(value) # ... back to "normal" Python revert_value = jabsorb.from_jabsorb(jabsorb_value) # Check content self.assertDictEqual(revert_value, value)
def __prepare_message(self, message, parent_uid=None): """ Prepares a HTTP request. :param message: The Message bean to send :param parent_uid: UID of the message this one replies to (optional) :return: A (headers, content) tuple """ # Prepare headers headers = {'herald-subject': message.subject, 'herald-uid': message.uid, 'herald-sender-uid': self.__peer_uid, 'herald-timestamp': int(time.time() * 1000), 'herald-port': self.__access_port, 'herald-path': self.__access_path} if parent_uid: headers['herald-reply-to'] = parent_uid # Convert content to JSON jabsorb_content = jabsorb.to_jabsorb(message.content) content = json.dumps(jabsorb_content, default=utils.json_converter) return headers, content
def do_POST(self, request, response): """ Handles a POST request, i.e. the reception of a message :param request: The HTTP request bean :param response: The HTTP response handler """ # pylint: disable=C0103 # Default code and content code = 200 content = "" # Extract headers """ content_type = request.get_header('content-type') subject = request.get_header('herald-subject') uid = request.get_header('herald-uid') reply_to = request.get_header('herald-reply-to') timestamp = request.get_header('herald-timestamp') sender_uid = request.get_header('herald-sender-uid') """ content_type = request.get_header('content-type') subject = None uid = None reply_to = None timestamp = None sender_uid = None raw_content = to_unicode(request.read_data()) # Client information host = utils.normalize_ip(request.get_client_address()[0]) message = None if content_type != CONTENT_TYPE_JSON: # Raw message uid = str(uuid.uuid4()) subject = herald.SUBJECT_RAW #msg_content = raw_content msg_content = raw_content port = -1 extra = {'host': host, 'raw': True} # construct a new Message bean message = herald.beans.MessageReceived(uid, subject, msg_content, None, None, ACCESS_ID, None, extra) else: # Herald message try: received_msg = utils.from_json(raw_content) except Exception as ex: _logger.exception("DoPOST ERROR:: %s", ex) msg_content = received_msg.content subject = received_msg.subject uid = received_msg.uid reply_to = received_msg.reply_to timestamp = received_msg.timestamp sender_uid = received_msg.sender if not uid or not subject: # Raw message uid = str(uuid.uuid4()) subject = herald.SUBJECT_RAW #msg_content = raw_content msg_content = raw_content port = -1 extra = {'host': host, 'raw': True} # construct a new Message bean message = herald.beans.MessageReceived(uid, subject, msg_content, None, None, ACCESS_ID, None, extra) else: # Store sender information try: port = int( received_msg.get_header( herald.transports.http.MESSAGE_HEADER_PORT)) except (KeyError, ValueError, TypeError): port = 80 path = None if herald.transports.http.MESSAGE_HEADER_PATH in received_msg.headers: path = received_msg.get_header( herald.transports.http.MESSAGE_HEADER_PATH) extra = { 'host': host, 'port': port, 'path': path, 'parent_uid': uid } try: # Check the sender UID port # (not perfect, but can avoid spoofing) if not self._http_directory.check_access( sender_uid, host, port): # Port doesn't match: invalid UID sender_uid = "<invalid>" except ValueError: # Unknown peer UID: keep it as is pass # Prepare the bean received_msg.add_header(herald.MESSAGE_HEADER_SENDER_UID, sender_uid) received_msg.set_access(ACCESS_ID) received_msg.set_extra(extra) message = received_msg # Log before giving message to Herald self._probe.store( herald.PROBE_CHANNEL_MSG_RECV, { "uid": message.uid, "timestamp": time.time(), "transport": ACCESS_ID, "subject": message.subject, "source": sender_uid, "repliesTo": reply_to or "", "transportSource": "[{0}]:{1}".format(host, port) }) if subject.startswith(peer_contact.SUBJECT_DISCOVERY_PREFIX): # Handle discovery message self.__contact.herald_message(self._core, message) else: # All other messages are given to Herald Core self._core.handle_message(message) # Convert content (Python 3) if content: content = jabsorb.to_jabsorb(content) content = to_bytes(content) # Send response response.send_content(code, content, CONTENT_TYPE_JSON)
def do_POST(self, request, response): """ Handles a POST request, i.e. the reception of a message :param request: The HTTP request bean :param response: The HTTP response handler """ # pylint: disable=C0103 # Default code and content code = 200 content = "" # Extract headers """ content_type = request.get_header('content-type') subject = request.get_header('herald-subject') uid = request.get_header('herald-uid') reply_to = request.get_header('herald-reply-to') timestamp = request.get_header('herald-timestamp') sender_uid = request.get_header('herald-sender-uid') """ content_type = request.get_header('content-type') subject = None uid = None reply_to = None timestamp = None sender_uid = None raw_content = to_unicode(request.read_data()) # Client information host = utils.normalize_ip(request.get_client_address()[0]) message = None if content_type != CONTENT_TYPE_JSON: # Raw message uid = str(uuid.uuid4()) subject = herald.SUBJECT_RAW #msg_content = raw_content msg_content = raw_content port = -1 extra = {'host': host, 'raw': True} # construct a new Message bean message = herald.beans.MessageReceived(uid, subject, msg_content, None, None, ACCESS_ID, None, extra) else: # Herald message try: received_msg = utils.from_json(raw_content) except Exception as ex: _logger.exception("DoPOST ERROR:: %s", ex) msg_content = received_msg.content subject = received_msg.subject uid = received_msg.uid reply_to = received_msg.reply_to timestamp = received_msg.timestamp sender_uid = received_msg.sender if not uid or not subject: # Raw message uid = str(uuid.uuid4()) subject = herald.SUBJECT_RAW #msg_content = raw_content msg_content = raw_content port = -1 extra = {'host': host, 'raw': True} # construct a new Message bean message = herald.beans.MessageReceived(uid, subject, msg_content, None, None, ACCESS_ID, None, extra) else: # Store sender information try: port = int(received_msg.get_header(herald.transports.http.MESSAGE_HEADER_PORT)) except (KeyError, ValueError, TypeError): port = 80 path = None if herald.transports.http.MESSAGE_HEADER_PATH in received_msg.headers: path = received_msg.get_header(herald.transports.http.MESSAGE_HEADER_PATH) extra = {'host': host, 'port': port, 'path': path, 'parent_uid': uid} try: # Check the sender UID port # (not perfect, but can avoid spoofing) if not self._http_directory.check_access( sender_uid, host, port): # Port doesn't match: invalid UID sender_uid = "<invalid>" except ValueError: # Unknown peer UID: keep it as is pass # Prepare the bean received_msg.add_header(herald.MESSAGE_HEADER_SENDER_UID, sender_uid) received_msg.set_access(ACCESS_ID) received_msg.set_extra(extra) message = received_msg # Log before giving message to Herald self._probe.store( herald.PROBE_CHANNEL_MSG_RECV, {"uid": message.uid, "timestamp": time.time(), "transport": ACCESS_ID, "subject": message.subject, "source": sender_uid, "repliesTo": reply_to or "", "transportSource": "[{0}]:{1}".format(host, port)}) if subject.startswith(peer_contact.SUBJECT_DISCOVERY_PREFIX): # Handle discovery message self.__contact.herald_message(self._core, message) else: # All other messages are given to Herald Core self._core.handle_message(message) # Convert content (Python 3) if content: content = jabsorb.to_jabsorb(content) content = to_bytes(content) # Send response response.send_content(code, content, CONTENT_TYPE_JSON)
def do_POST(self, request, response): """ Handles a POST request, i.e. the reception of a message :param request: The HTTP request bean :param response: The HTTP response handler """ # pylint: disable=C0103 # Default code and content code = 200 content = "" # Extract headers content_type = request.get_header('content-type') subject = request.get_header('herald-subject') uid = request.get_header('herald-uid') reply_to = request.get_header('herald-reply-to') timestamp = request.get_header('herald-timestamp') sender_uid = request.get_header('herald-sender-uid') raw_content = to_unicode(request.read_data()) # Client information host = utils.normalize_ip(request.get_client_address()[0]) if not uid or not subject or content_type != CONTENT_TYPE_JSON: # Raw message uid = str(uuid.uuid4()) subject = herald.SUBJECT_RAW msg_content = raw_content port = -1 extra = {'host': host, 'raw': True} else: # Herald message msg_content = jabsorb.from_jabsorb(json.loads(raw_content)) # Store sender information port = int(request.get_header('herald-port', 80)) extra = {'host': host, 'port': port, 'path': request.get_header('herald-path'), 'parent_uid': uid} try: # Check the sender UID port # (not perfect, but can avoid spoofing) if not self._http_directory.check_access( sender_uid, host, port): # Port doesn't match: invalid UID sender_uid = "<invalid>" except ValueError: # Unknown peer UID: keep it as is pass # Prepare the bean message = herald.beans.MessageReceived(uid, subject, msg_content, sender_uid, reply_to, ACCESS_ID, timestamp, extra) # Log before giving message to Herald self._probe.store( herald.PROBE_CHANNEL_MSG_RECV, {"uid": message.uid, "timestamp": time.time(), "transport": ACCESS_ID, "subject": message.subject, "source": sender_uid, "repliesTo": reply_to or "", "transportSource": "[{0}]:{1}".format(host, port)}) if subject.startswith(peer_contact.SUBJECT_DISCOVERY_PREFIX): # Handle discovery message self.__contact.herald_message(self._core, message) else: # All other messages are given to Herald Core self._core.handle_message(message) # Convert content (Python 3) if content: content = jabsorb.to_jabsorb(content) content = to_bytes(content) # Send response response.send_content(code, content, CONTENT_TYPE_JSON)
def do_POST(self, request, response): """ Handles a POST request, i.e. the reception of a message :param request: The HTTP request bean :param response: The HTTP response handler """ # pylint: disable=C0103 # Default code and content code = 200 content = "" # Check content type content_type = request.get_header('content-type') if content_type not in (None, CONTENT_TYPE_JSON): # Unknown content type -> Error 412 "Precondition failed" _logger.critical("Bad content type: %s", content_type) code, content = _make_json_result(412, "Unknown content type") else: # Extract headers subject = request.get_header('herald-subject') uid = request.get_header('herald-uid') reply_to = request.get_header('herald-reply-to') timestamp = request.get_header('herald-timestamp') sender_uid = request.get_header('herald-sender-uid') json_content = to_unicode(request.read_data()) msg_content = jabsorb.from_jabsorb(json.loads(json_content)) # Store sender information host = request.get_client_address()[0] port = int(request.get_header('herald-port', 80)) extra = {'host': host, 'port': port, 'path': request.get_header('herald-path'), 'parent_uid': uid} try: # Check the sender UID port # (not perfect, but can avoid spoofing) if not self._http_directory.check_access(sender_uid, host, port): # Port doesn't match: invalid UID sender_uid = "<invalid>" except ValueError as ex: # Unknown peer UID: keep it as is pass # Let Herald handle the message message = herald.beans.MessageReceived(uid, subject, msg_content, sender_uid, reply_to, ACCESS_ID, timestamp, extra) self._core.handle_message(message) # Convert content (Python 3) if content: content = jabsorb.to_jabsorb(content) content = to_bytes(content) # Send response response.send_content(code, content, CONTENT_TYPE_JSON)
def do_POST(self, request, response): """ Handles a POST request, i.e. the reception of a message :param request: The HTTP request bean :param response: The HTTP response handler """ # pylint: disable=C0103 # Default code and content code = 200 content = "" # Check content type content_type = request.get_header('content-type') if content_type not in (None, CONTENT_TYPE_JSON): # Unknown content type -> Error 412 "Precondition failed" _logger.critical("Bad content type: %s", content_type) code, content = _make_json_result(412, "Unknown content type") else: # Extract headers subject = request.get_header('herald-subject') uid = request.get_header('herald-uid') reply_to = request.get_header('herald-reply-to') timestamp = request.get_header('herald-timestamp') sender_uid = request.get_header('herald-sender-uid') json_content = to_unicode(request.read_data()) msg_content = jabsorb.from_jabsorb(json.loads(json_content)) # Store sender information host = request.get_client_address()[0] port = int(request.get_header('herald-port', 80)) extra = { 'host': host, 'port': port, 'path': request.get_header('herald-path'), 'parent_uid': uid } try: # Check the sender UID port # (not perfect, but can avoid spoofing) if not self._http_directory.check_access( sender_uid, host, port): # Port doesn't match: invalid UID sender_uid = "<invalid>" except ValueError as ex: # Unknown peer UID: keep it as is pass # Let Herald handle the message message = herald.beans.MessageReceived(uid, subject, msg_content, sender_uid, reply_to, ACCESS_ID, timestamp, extra) self._core.handle_message(message) # Convert content (Python 3) if content: content = jabsorb.to_jabsorb(content) content = to_bytes(content) # Send response response.send_content(code, content, CONTENT_TYPE_JSON)
def __init__(self): self.list = jabsorb.to_jabsorb([1, 2, 3]) self.tuple = jabsorb.to_jabsorb((1, 2, 3)) self.set = jabsorb.to_jabsorb(set((1, 2, 3)))