def create_token_request(self, token_params=None, key_name=None, key_secret=None, query_time=None): token_params = token_params or {} token_request = {} key_name = key_name or self.auth_options.key_name key_secret = key_secret or self.auth_options.key_secret if not key_name or not key_secret: log.debug('key_name or key_secret blank') raise AblyException( "No key specified: no means to generate a token", 401, 40101) token_request['key_name'] = key_name if token_params.get('timestamp'): token_request['timestamp'] = token_params['timestamp'] else: if query_time is None: query_time = self.auth_options.query_time if query_time: token_request['timestamp'] = self.ably.time() else: token_request['timestamp'] = self._timestamp() token_request['timestamp'] = int(token_request['timestamp']) ttl = token_params.get('ttl') if ttl is not None: if isinstance(ttl, timedelta): ttl = ttl.total_seconds() * 1000 token_request['ttl'] = int(ttl) capability = token_params.get('capability') if capability is not None: token_request['capability'] = six.text_type(Capability(capability)) token_request["client_id"] = (token_params.get('client_id') or self.client_id) # Note: There is no expectation that the client # specifies the nonce; this is done by the library # However, this can be overridden by the client # simply for testing purposes token_request["nonce"] = token_params.get( 'nonce') or self._random_nonce() token_request = TokenRequest(**token_request) if token_params.get('mac') is None: # Note: There is no expectation that the client # specifies the mac; this is done by the library # However, this can be overridden by the client # simply for testing purposes. token_request.sign_request(key_secret.encode('utf8')) else: token_request.mac = token_params['mac'] return token_request
def make_request(self, method, path, headers=None, body=None, skip_auth=False, timeout=None, raise_on_error=True): if body is not None and type(body) not in (bytes, str): body = self.dump_body(body) if body: all_headers = HttpUtils.default_post_headers( self.options.use_binary_protocol, self.__ably.variant) else: all_headers = HttpUtils.default_get_headers( self.options.use_binary_protocol, self.__ably.variant) if not skip_auth: if self.auth.auth_mechanism == Auth.Method.BASIC and self.preferred_scheme.lower() == 'http': raise AblyException( "Cannot use Basic Auth over non-TLS connections", 401, 40103) all_headers.update(self.auth._get_auth_headers()) if headers: all_headers.update(headers) timeout = (self.http_open_timeout, self.http_request_timeout) http_max_retry_duration = self.http_max_retry_duration requested_at = time.time() hosts = self.get_rest_hosts() for retry_count, host in enumerate(hosts): base_url = "%s://%s:%d" % (self.preferred_scheme, host, self.preferred_port) url = urljoin(base_url, path) request = requests.Request(method, url, data=body, headers=all_headers) prepped = self.__session.prepare_request(request) try: response = self.__session.send(prepped, timeout=timeout) except Exception as e: # Need to catch `Exception`, see: # https://github.com/kennethreitz/requests/issues/1236#issuecomment-133312626 # if last try or cumulative timeout is done, throw exception up time_passed = time.time() - requested_at if retry_count == len(hosts) - 1 or \ time_passed > http_max_retry_duration: raise e else: try: if raise_on_error: AblyException.raise_for_response(response) # Keep fallback host for later (RSC15f) if retry_count > 0 and host != self.options.get_rest_host(): self.__host = host self.__host_expires = time.time() + (self.options.fallback_retry_timeout / 1000.0) return Response(response) except AblyException as e: if not e.is_server_error: raise e
def parse_key(self, key): try: key_name, key_secret = key.split(':') return key_name, key_secret except ValueError: raise AblyException("key of not len 2 parameters: {0}" .format(key.split(':')), 401, 40101)
def __unpad(self, data): padding_size = six.indexbytes(data, -1) if padding_size > len(data): # Too short raise AblyException('invalid-padding', 0, 0) if padding_size == 0: # Missing padding raise AblyException('invalid-padding', 0, 0) for i in range(padding_size): # Invalid padding bytes if padding_size != six.indexbytes(data, -i - 1): raise AblyException('invalid-padding', 0, 0) return data[:-padding_size]
def get_cipher(cipher_params): if cipher_params is None: params = get_default_params() elif isinstance(cipher_params, CipherParams): params = cipher_params else: raise AblyException("ChannelOptions not supported", 400, 40000) return CbcChannelCipher(params)
def as_dict(self, binary=False): data = self.data data_type = None encoding = self._encoding_array[:] if isinstance(data, dict) or isinstance(data, list): encoding.append('json') data = json.dumps(data) elif isinstance(data, six.text_type) and not binary: # text_type is always a unicode string pass elif (not binary and isinstance(data, bytearray) or # bytearray is always bytes isinstance(data, six.binary_type) and six.binary_type != str): # in py3k we will understand <class 'bytes'> as bytes data = base64.b64encode(data).decode('ascii') encoding.append('base64') elif isinstance(data, CipherData): encoding.append(data.encoding_str) data_type = data.type if not binary: data = base64.b64encode(data.buffer).decode('ascii') encoding.append('base64') else: data = data.buffer elif binary and isinstance(data, bytearray): data = six.binary_type(data) if not (isinstance(data, (six.binary_type, six.text_type, list, dict, bytearray)) or data is None): raise AblyException("Invalid data payload", 400, 40011) request_body = { 'name': self.name, 'data': data, 'timestamp': self.timestamp or int(time.time() * 1000.0), } request_body = { k: v for (k, v) in request_body.items() if v is not None } # None values aren't included if encoding: request_body['encoding'] = '/'.join(encoding).strip('/') if data_type: request_body['type'] = data_type if self.client_id: request_body['clientId'] = self.client_id if self.id: request_body['id'] = self.id if self.connection_id: request_body['connectionId'] = self.connection_id return request_body
def set_key(self, key): if key is None: return try: key_name, key_secret = key.split(':') self.auth_options['key_name'] = key_name self.auth_options['key_secret'] = key_secret except ValueError: raise AblyException( "key of not len 2 parameters: {0}".format(key.split(':')), 401, 40101)
def as_dict(self, binary=False): data = self.data data_type = None encoding = self._encoding_array[:] if isinstance(data, (dict, list)): encoding.append('json') data = json.dumps(data) data = str(data) elif isinstance(data, str) and not binary: pass elif not binary and isinstance(data, (bytearray, bytes)): data = base64.b64encode(data).decode('ascii') encoding.append('base64') elif isinstance(data, CipherData): encoding.append(data.encoding_str) data_type = data.type if not binary: data = base64.b64encode(data.buffer).decode('ascii') encoding.append('base64') else: data = data.buffer elif binary and isinstance(data, bytearray): data = bytes(data) if not (isinstance(data, (bytes, str, list, dict, bytearray)) or data is None): raise AblyException("Invalid data payload", 400, 40011) request_body = { 'name': self.name, 'data': data, 'timestamp': self.timestamp or None, 'type': data_type or None, 'clientId': self.client_id or None, 'id': self.id or None, 'connectionId': self.connection_id or None, 'connectionKey': self.connection_key or None, 'extras': self.extras, } if encoding: request_body['encoding'] = '/'.join(encoding).strip('/') # None values aren't included request_body = {k: v for k, v in request_body.items() if v is not None} return request_body
def raise_ably_exception(*args, **kwargs): raise AblyException(message="", status_code=500, code=50000)
def as_dict(self, binary=False): data = self.data data_type = None encoding = self._encoding_array[:] if isinstance(data, six.binary_type) and six.binary_type == str: # If using python 2, assume str payloads are intended as strings # if they decode to unicode. If it doesn't, treat as a binary try: data = six.text_type(data) except UnicodeDecodeError: pass if isinstance(data, dict) or isinstance(data, list): encoding.append('json') data = json.dumps(data) data = six.text_type(data) elif isinstance(data, six.text_type) and not binary: # text_type is always a unicode string pass elif (not binary and (isinstance(data, bytearray) or # bytearray is always bytes isinstance(data, six.binary_type))): # at this point binary_type is either a py3k bytes or a py2 # str that failed to decode to unicode data = base64.b64encode(data).decode('ascii') encoding.append('base64') elif isinstance(data, CipherData): encoding.append(data.encoding_str) data_type = data.type if not binary: data = base64.b64encode(data.buffer).decode('ascii') encoding.append('base64') else: data = data.buffer elif binary and isinstance(data, bytearray): data = six.binary_type(data) if not (isinstance(data, (six.binary_type, six.text_type, list, dict, bytearray)) or data is None): raise AblyException("Invalid data payload", 400, 40011) request_body = { u'name': self.name, u'data': data, u'timestamp': self.timestamp or int(time.time() * 1000.0), } request_body = { k: v for (k, v) in request_body.items() if v is not None } # None values aren't included if encoding: request_body[u'encoding'] = u'/'.join(encoding).strip(u'/') if data_type: request_body[u'type'] = data_type if self.client_id: request_body[u'clientId'] = self.client_id if self.id: request_body[u'id'] = self.id if self.connection_id: request_body[u'connectionId'] = self.connection_id if self.connection_key: request_body['connectionKey'] = self.connection_key if self.extras: request_body['extras'] = self.extras return request_body
def make_request(self, method, path, headers=None, body=None, native_data=None, skip_auth=False, timeout=None): fallback_hosts = Defaults.get_fallback_rest_hosts(self.__options) if fallback_hosts: fallback_hosts.insert(0, self.preferred_host) fallback_hosts = itertools.cycle(fallback_hosts) if native_data is not None and body is not None: raise ValueError("make_request takes either body or native_data") elif native_data is not None: body = self.dump_body(native_data) if body: all_headers = HttpUtils.default_post_headers( self.options.use_binary_protocol) else: all_headers = HttpUtils.default_get_headers( self.options.use_binary_protocol) if not skip_auth: if self.auth.auth_mechanism == Auth.Method.BASIC and self.preferred_scheme.lower() == 'http': raise AblyException( "Cannot use Basic Auth over non-TLS connections", 401, 40103) all_headers.update(self.auth._get_auth_headers()) if headers: all_headers.update(headers) http_open_timeout = self.http_open_timeout http_request_timeout = self.http_request_timeout if fallback_hosts: http_max_retry_count = self.http_max_retry_count else: http_max_retry_count = 1 http_max_retry_duration = self.http_max_retry_duration requested_at = time.time() for retry_count in range(http_max_retry_count): host = next(fallback_hosts) if fallback_hosts else self.preferred_host if self.options.environment: host = self.options.environment + '-' + host base_url = "%s://%s:%d" % (self.preferred_scheme, host, self.preferred_port) url = urljoin(base_url, path) request = requests.Request(method, url, data=body, headers=all_headers) prepped = self.__session.prepare_request(request) try: response = self.__session.send( prepped, timeout=(http_open_timeout, http_request_timeout)) except Exception as e: # Need to catch `Exception`, see: # https://github.com/kennethreitz/requests/issues/1236#issuecomment-133312626 # if last try or cumulative timeout is done, throw exception up time_passed = time.time() - requested_at if retry_count == http_max_retry_count - 1 or \ time_passed > http_max_retry_duration: raise e else: try: AblyException.raise_for_response(response) return Response(response) except AblyException as e: if not e.is_server_error: raise e
async def make_request(self, method, path, headers=None, body=None, skip_auth=False, timeout=None, raise_on_error=True): if body is not None and type(body) not in (bytes, str): body = self.dump_body(body) if body: all_headers = HttpUtils.default_post_headers( self.options.use_binary_protocol) else: all_headers = HttpUtils.default_get_headers( self.options.use_binary_protocol) if not skip_auth: if self.auth.auth_mechanism == Auth.Method.BASIC and self.preferred_scheme.lower( ) == 'http': raise AblyException( "Cannot use Basic Auth over non-TLS connections", 401, 40103) auth_headers = await self.auth._get_auth_headers() all_headers.update(auth_headers) if headers: all_headers.update(headers) timeout = (self.http_open_timeout, self.http_request_timeout) http_max_retry_duration = self.http_max_retry_duration requested_at = time.time() hosts = self.get_rest_hosts() for retry_count, host in enumerate(hosts): base_url = "%s://%s:%d" % (self.preferred_scheme, host, self.preferred_port) url = urljoin(base_url, path) request = self.__client.build_request( method=method, url=url, content=body, headers=all_headers, timeout=timeout, ) try: response = await self.__client.send(request) except Exception as e: # if last try or cumulative timeout is done, throw exception up time_passed = time.time() - requested_at if retry_count == len( hosts) - 1 or time_passed > http_max_retry_duration: raise e else: try: if raise_on_error: AblyException.raise_for_response(response) # Keep fallback host for later (RSC15f) if retry_count > 0 and host != self.options.get_rest_host( ): self.__host = host self.__host_expires = time.time() + ( self.options.fallback_retry_timeout / 1000.0) return Response(response) except AblyException as e: if not e.is_server_error: raise e # if last try or cumulative timeout is done, throw exception up time_passed = time.time() - requested_at if retry_count == len( hosts ) - 1 or time_passed > http_max_retry_duration: raise e