def test_parse_host_port(self): """test about parse host port""" # test default port for http endpoint = "1.2.3.4" default_protocol = baidubce.protocol.HTTP ret_protocol, host, port = utils.parse_host_port( endpoint, default_protocol) self.assertEqual(ret_protocol, baidubce.protocol.HTTP) self.assertEqual(host, endpoint) self.assertEqual(port, default_protocol.default_port) # test default port for https endpoint = "1.2.3.4" default_protocol = baidubce.protocol.HTTPS ret_protocol, host, port = utils.parse_host_port( endpoint, default_protocol) self.assertEqual(ret_protocol, baidubce.protocol.HTTPS) self.assertEqual(host, endpoint) self.assertEqual(port, default_protocol.default_port) # test specific port endpoint = "1.2.3.4:8080" default_protocol = baidubce.protocol.HTTP ret_protocol, host, port = utils.parse_host_port( endpoint, default_protocol) self.assertEqual(ret_protocol, baidubce.protocol.HTTP) self.assertEqual(host, "1.2.3.4") self.assertEqual(port, 8080) # test value error endpoint = "1.2.3.4:abcd" default_protocol = baidubce.protocol.HTTP self.assertRaises(ValueError, utils.parse_host_port, endpoint, default_protocol) # protocol unsupported endpoint = "ftp://1.2.3.4" default_protocol = baidubce.protocol.HTTP self.assertRaises(ValueError, utils.parse_host_port, endpoint, default_protocol) # test of endpoint dominates the protocol endpoint = "http://1.2.3.4:8080" default_protocol = baidubce.protocol.HTTPS ret_protocol, host, port = utils.parse_host_port( endpoint, default_protocol) self.assertEqual(ret_protocol, baidubce.protocol.HTTP) self.assertEqual(host, "1.2.3.4") self.assertEqual(port, 8080)
def _read_endpoints_from_file(self, endpoints_path): content = [] try: with open(endpoints_path) as f: content = f.readlines() endpoints = [l.strip() for l in content] except Exception as e: raise BceClientError("failed read endpoints from %s, error: %s" % (endpoints_path, e)) for endpoint in content: if len(endpoint) < MIN_ENDPOINT_LENGTH: continue protocol, host, port = utils.parse_host_port( endpoint, baidubce.protocol.HTTP) if port != protocol.default_port: host_and_port = host + ':' + str(port) else: host_and_port = host endpoint = SingleEndpoint(protocol, host, port, host_and_port) endpoint.set_id(self._valid_min_endpoint_id) self._endpoint_head = self._insert_endpoint_to_head( self._endpoint_head, endpoint) self._num_of_active_endpoint += 1
def _update_endpoint(self, response): if not response.contents: return False head = None endpoints_num = 0 for rgw in response.contents: endpoint_str = rgw.ip + ':' + rgw.port protocol, host, port = utils.parse_host_port( endpoint_str, baidubce.protocol.HTTP) host_and_port = host if port != protocol.default_port: host_and_port += ':' + str(port) _logger.debug('** insert %s to active list', host_and_port) endpoint = SingleEndpoint(protocol, host, port, host_and_port) head = self._insert_endpoint_to_head(head, endpoint) endpoints_num += 1 if endpoints_num <= 0: return False with self._mutex: for i in range(0, endpoints_num): head.set_id(self._valid_min_endpoint_id + 1) head = head.next # update current active endpoints self._endpoint_head = head # _valid_min_endpoint_id must be protected by lock self._valid_min_endpoint_id += 1 self._num_of_active_endpoint = endpoints_num # clear balcklist self._blacklist.clear() return True
def generate_pre_signed_url(self, bucket_name, key, timestamp=0, expiration_in_seconds=1800, headers=None, params=None, headers_to_sign=None, protocol=None, config=None): """ Get an authorization url with expire time :type timestamp: int :param timestamp: None :type expiration_in_seconds: int :param expiration_in_seconds: None :type options: dict :param options: None :return: **URL string** """ config = self._merge_config(config) headers = headers or {} params = params or {} # specified protocol > protocol in endpoint > default protocol endpoint_protocol, endpoint_host, endpoint_port = \ utils.parse_host_port(config.endpoint, config.protocol) protocol = protocol or endpoint_protocol full_host = endpoint_host if endpoint_port != config.protocol.default_port: full_host += ':' + str(endpoint_port) headers[http_headers.HOST] = full_host path = self._get_path(config, bucket_name, key) params[http_headers.AUTHORIZATION.lower()] = bce_v1_signer.sign( config.credentials, http_methods.GET, path, headers, params, timestamp, expiration_in_seconds, headers_to_sign) return "%s://%s%s?%s" % (protocol.name, full_host, path, utils.get_canonical_querystring(params, False))
def send_request(config, sign_function, response_handler_functions, http_method, path, body, headers, params): """ Send request to BCE services. :param config :type config: baidubce.BceClientConfiguration :param sign_function: :param response_handler_functions: :type response_handler_functions: list :param request: :type request: baidubce.internal.InternalRequest :return: :rtype: baidubce.BceResponse """ _logger.debug(b'%s request start: %s %s, %s, %s', http_method, path, headers, params, body) headers = headers or {} user_agent = 'bce-sdk-python/%s/%s/%s' % (compat.convert_to_string( baidubce.SDK_VERSION), sys.version, sys.platform) user_agent = user_agent.replace('\n', '') user_agent = compat.convert_to_bytes(user_agent) headers[http_headers.USER_AGENT] = user_agent should_get_new_date = False if http_headers.BCE_DATE not in headers: should_get_new_date = True headers[http_headers.HOST] = config.endpoint if isinstance(body, str): body = body.encode(baidubce.DEFAULT_ENCODING) if not body: headers[http_headers.CONTENT_LENGTH] = 0 elif isinstance(body, bytes): headers[http_headers.CONTENT_LENGTH] = len(body) elif http_headers.CONTENT_LENGTH not in headers: raise ValueError(b'No %s is specified.' % http_headers.CONTENT_LENGTH) # store the offset of fp body offset = None if hasattr(body, "tell") and hasattr(body, "seek"): offset = body.tell() protocol, host, port = utils.parse_host_port(config.endpoint, config.protocol) headers[http_headers.HOST] = host if port != config.protocol.default_port: headers[http_headers.HOST] += b':' + compat.convert_to_bytes(port) headers[http_headers.AUTHORIZATION] = sign_function( config.credentials, http_method, path, headers, params) encoded_params = utils.get_canonical_querystring(params, False) if len(encoded_params) > 0: uri = path + b'?' + encoded_params else: uri = path check_headers(headers) retries_attempted = 0 errors = [] while True: conn = None try: # restore the offset of fp body when retrying if should_get_new_date is True: headers[http_headers.BCE_DATE] = utils.get_canonical_time() headers[http_headers.AUTHORIZATION] = sign_function( config.credentials, http_method, path, headers, params) if retries_attempted > 0 and offset is not None: body.seek(offset) conn = _get_connection(protocol, host, port, config.connection_timeout_in_mills) _logger.debug( 'request args:method=%s, uri=%s, headers=%s,patams=%s, body=%s', http_method, uri, headers, params, body) http_response = _send_http_request(conn, http_method, uri, headers, body, config.send_buf_size) headers_list = http_response.getheaders() # on py3 ,values of headers_list is decoded with ios-8859-1 from # utf-8 binary bytes # headers_list[*][0] is lowercase on py2 # headers_list[*][0] is raw value py3 if compat.PY3 and isinstance(headers_list, list): temp_heads = [] for k, v in headers_list: k = k.encode('latin-1').decode('utf-8') v = v.encode('latin-1').decode('utf-8') k = k.lower() temp_heads.append((k, v)) headers_list = temp_heads _logger.debug('request return: status=%d, headers=%s' % (http_response.status, headers_list)) response = BceResponse() response.set_metadata_from_headers(dict(headers_list)) for handler_function in response_handler_functions: if handler_function(http_response, response): break return response except Exception as e: if conn is not None: conn.close() # insert ">>>>" before all trace back lines and then save it errors.append('\n'.join( '>>>>' + line for line in traceback.format_exc().splitlines())) if config.retry_policy.should_retry(e, retries_attempted): delay_in_millis = config.retry_policy.get_delay_before_next_retry_in_millis( e, retries_attempted) time.sleep(delay_in_millis / 1000.0) else: raise BceHttpClientError( 'Unable to execute HTTP request. Retried %d times. ' 'All trace backs:\n%s' % (retries_attempted, '\n'.join(errors)), e) retries_attempted += 1
def send_request( self, config, sign_function, response_handler_functions, http_method, path, body, headers, params, special=False): """ Send request to BCE services. :param config :type config: baidubce.BceClientConfiguration :param sign_function: :param response_handler_functions: :type response_handler_functions: list :param request: :type request: baidubce.internal.InternalRequest :return: :rtype: baidubce.BceResponse """ t = int(time.time()) _logger.debug('%s request start: %s %s, %s, %s, %d', http_method, path, headers, params, body, t) headers = headers or {} user_agent = 'bce-sdk-python/%s/%s/%s' % ( baidubce.SDK_VERSION, sys.version, sys.platform) user_agent = user_agent.replace('\n', '') headers[http_headers.USER_AGENT] = user_agent should_get_new_date = False headers[http_headers.HOST] = config.endpoint if isinstance(body, str): body = body.encode(baidubce.DEFAULT_ENCODING) if not body: headers[http_headers.CONTENT_LENGTH] = 0 elif isinstance(body, str): headers[http_headers.CONTENT_LENGTH] = len(body) elif http_headers.CONTENT_LENGTH not in headers: raise ValueError('No %s is specified.' % http_headers.CONTENT_LENGTH) offset = None if hasattr(body, "tell") and hasattr(body, "seek"): offset = body.tell() protocol, host, port = utils.parse_host_port(config.endpoint, config.protocol) path = quote(path) headers[http_headers.HOST] = host if port != config.protocol.default_port: headers[http_headers.HOST] += ':' + str(port) headers[http_headers.AUTHORIZATION] = sign_function( config.credentials, http_method, path, headers, params, headers_to_sign=["host", "content-type"]) encoded_params = utils.get_canonical_querystring(params, False) if len(encoded_params) > 0: uri = path + '?' + encoded_params else: uri = path bce_http_client.check_headers(headers) retries_attempted = 0 errors = [] while True: conn = None try: if should_get_new_date is True: headers[http_headers.BCE_DATE] = utils.get_canonical_time() headers[http_headers.AUTHORIZATION] = sign_function( config.credentials, http_method, path, headers, params, headers_to_sign=["host", "content-type"]) if retries_attempted > 0 and offset is not None: body.seek(offset) conn = bce_http_client._get_connection(protocol, host, port, config.connection_timeout_in_mills) http_response = bce_http_client._send_http_request( conn, http_method, uri, headers, body, config.send_buf_size) headers_list = http_response.getheaders() _logger.debug( 'request return: status=%d, headers=%s' % (http_response.status, headers_list)) if special: return http_response response = bce_http_client.BceResponse() response.set_metadata_from_headers(dict(headers_list)) for handler_function in response_handler_functions: if handler_function(http_response, response): break return response except Exception as e: if conn is not None: conn.close() # insert ">>>>" before all trace back lines and then save it errors.append('\n'.join('>>>>' + line for line in traceback.format_exc(). splitlines())) if config.retry_policy.should_retry(e, retries_attempted): delay_in_millis = config.retry_policy.get_delay_before_next_retry_in_millis( e, retries_attempted) time.sleep(delay_in_millis / 1000.0) else: raise bce_http_client.BceHttpClientError('Unable to execute HTTP request. ' 'Retried %d times. All trace backs:\n' '%s' % (retries_attempted, '\n'.join(errors)), e)
def send_request( config, sign_function, response_handler_functions, http_method, path, body, headers, params): """ Send request to BCE services. :param config :type config: baidubce.BceClientConfiguration :param sign_function: :param response_handler_functions: :type response_handler_functions: list :param request: :type request: baidubce.internal.InternalRequest :return: :rtype: baidubce.BceResponse """ _logger.debug('%s request start: %s %s, %s, %s', http_method, path, headers, params, body) headers = headers or {} user_agent = 'bce-sdk-python/%s/%s/%s' % ( baidubce.SDK_VERSION, sys.version, sys.platform) user_agent = user_agent.replace('\n', '') headers[http_headers.USER_AGENT] = user_agent should_get_new_date = False if http_headers.BCE_DATE not in headers: should_get_new_date = True headers[http_headers.HOST] = config.endpoint if isinstance(body, unicode): body = body.encode(baidubce.DEFAULT_ENCODING) if not body: headers[http_headers.CONTENT_LENGTH] = 0 elif isinstance(body, str): headers[http_headers.CONTENT_LENGTH] = len(body) elif http_headers.CONTENT_LENGTH not in headers: raise ValueError('No %s is specified.' % http_headers.CONTENT_LENGTH) # store the offset of fp body offset = None if hasattr(body, "tell") and hasattr(body, "seek"): offset = body.tell() protocol, host, port = utils.parse_host_port(config.endpoint, config.protocol) headers[http_headers.HOST] = host if port != config.protocol.default_port: headers[http_headers.HOST] += ':' + str(port) headers[http_headers.AUTHORIZATION] = sign_function( config.credentials, http_method, path, headers, params) encoded_params = utils.get_canonical_querystring(params, False) if len(encoded_params) > 0: uri = path + '?' + encoded_params else: uri = path check_headers(headers) retries_attempted = 0 errors = [] while True: conn = None try: # restore the offset of fp body when retrying if should_get_new_date is True: headers[http_headers.BCE_DATE] = utils.get_canonical_time() headers[http_headers.AUTHORIZATION] = sign_function( config.credentials, http_method, path, headers, params) if retries_attempted > 0 and offset is not None: body.seek(offset) conn = _get_connection(protocol, host, port, config.connection_timeout_in_mills) http_response = _send_http_request( conn, http_method, uri, headers, body, config.send_buf_size) headers_list = http_response.getheaders() _logger.debug( 'request return: status=%d, headers=%s' % (http_response.status, headers_list)) response = BceResponse() response.set_metadata_from_headers(dict(headers_list)) for handler_function in response_handler_functions: if handler_function(http_response, response): break return response except Exception as e: if conn is not None: conn.close() # insert ">>>>" before all trace back lines and then save it errors.append('\n'.join('>>>>' + line for line in traceback.format_exc().splitlines())) if config.retry_policy.should_retry(e, retries_attempted): delay_in_millis = config.retry_policy.get_delay_before_next_retry_in_millis( e, retries_attempted) time.sleep(delay_in_millis / 1000.0) else: raise BceHttpClientError('Unable to execute HTTP request. Retried %d times. ' 'All trace backs:\n%s' % (retries_attempted, '\n'.join(errors)), e) retries_attempted += 1