def publish(self, name=None, data=None, client_id=None, connection_key=None, messages=None, timeout=None): """Publishes a message on this channel. :Parameters: - `name`: the name for this message. - `data`: the data for this message. - `connection_key`: connection key from a realtime connection, when publishing on behalf of it. - `messages`: list of `Message` objects to be published. Specify this param OR `name` and `data`. :attention: You can publish using `name` and `data` OR `messages`, never all three. """ if not messages: messages = [Message(name, data, client_id, connection_key)] request_body_list = [] for m in messages: if m.client_id == '*': raise IncompatibleClientIdException( 'Wildcard client_id is reserved and cannot be used when publishing messages', 400, 40012) elif m.client_id is not None and not self.ably.auth.can_assume_client_id( m.client_id): raise IncompatibleClientIdException( 'Cannot publish with client_id \'{}\' as it is incompatible with the ' 'current configured client_id \'{}\''.format( m.client_id, self.ably.auth.client_id), 400, 40012) if self.cipher: m.encrypt(self.__cipher) request_body_list.append(m) if not self.ably.options.use_binary_protocol: if len(request_body_list) == 1: request_body = request_body_list[0].as_json() else: request_body = json.dumps(request_body_list, cls=MessageJSONEncoder) else: if len(request_body_list) == 1: request_body = request_body_list[0].as_msgpack() else: request_body = msgpack.packb([ message.as_dict(binary=True) for message in request_body_list ], use_bin_type=True) path = '/channels/%s/publish' % self.__name return self.ably.http.post(path, body=request_body, timeout=timeout)
def __publish_request_body(self, name=None, data=None, client_id=None, extras=None, messages=None): """ Helper private method, separated from publish() to test RSL1j """ if not messages: messages = [Message(name, data, client_id, extras=extras)] # Idempotent publishing if self.ably.options.idempotent_rest_publishing: # RSL1k1 if all(message.id is None for message in messages): base_id = base64.b64encode(os.urandom(12)).decode() for serial, message in enumerate(messages): message.id = u'{}:{}'.format(base_id, serial) request_body_list = [] for m in messages: if m.client_id == '*': raise IncompatibleClientIdException( 'Wildcard client_id is reserved and cannot be used when publishing messages', 400, 40012) elif m.client_id is not None and not self.ably.auth.can_assume_client_id( m.client_id): raise IncompatibleClientIdException( 'Cannot publish with client_id \'{}\' as it is incompatible with the ' 'current configured client_id \'{}\''.format( m.client_id, self.ably.auth.client_id), 400, 40012) if self.cipher: m.encrypt(self.__cipher) request_body_list.append(m) request_body = [ message.as_dict(binary=self.ably.options.use_binary_protocol) for message in request_body_list ] if len(request_body) == 1: request_body = request_body[0] return request_body
def _configure_client_id(self, new_client_id): # If new client ID from Ably is a wildcard, but preconfigured clientId is set, # then keep the existing clientId if self.client_id != '*' and new_client_id == '*': self.__client_id_validated = True return # If client_id is defined and not a wildcard, prevent it changing, this is not supported if self.client_id is not None and self.client_id != '*' and new_client_id != self.client_id: raise IncompatibleClientIdException( "Client ID is immutable once configured for a client. " "Client ID cannot be changed to '{}'".format(new_client_id), 400, 40012) self.__client_id_validated = True self.__client_id = new_client_id