Skip to content

Commit ce56c4b

Browse files
committed
support bucket referer
1 parent 3156261 commit ce56c4b

File tree

4 files changed

+143
-17
lines changed

4 files changed

+143
-17
lines changed

qcloud_cos/cos_client.py

Lines changed: 115 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
class CosConfig(object):
3131
"""config类,保存用户相关信息"""
3232
def __init__(self, Appid=None, Region=None, SecretId=None, SecretKey=None, Token=None, Scheme=None, Timeout=None,
33-
Access_id=None, Access_key=None, Secret_id=None, Secret_key=None,
34-
Endpoint=None, IP=None, Port=None, Anonymous=None, UA=None, Proxies=None):
33+
Access_id=None, Access_key=None, Secret_id=None, Secret_key=None, Endpoint=None, IP=None, Port=None,
34+
Anonymous=None, UA=None, Proxies=None, Domain=None, ServiceDomain=None):
3535
"""初始化,保存用户的信息
3636
3737
:param Appid(string): 用户APPID.
@@ -51,18 +51,24 @@ def __init__(self, Appid=None, Region=None, SecretId=None, SecretKey=None, Token
5151
:param Anonymous(bool): 是否使用匿名访问COS
5252
:param UA(string): 使用自定义的UA来访问COS
5353
:param Proxies(dict): 使用代理来访问COS
54+
:param Domain(string): 使用自定义的域名来访问COS
55+
:param ServiceDomain(string): 使用自定义的域名来访问cos service
5456
"""
5557
self._appid = to_unicode(Appid)
5658
self._token = to_unicode(Token)
5759
self._timeout = Timeout
5860
self._region = Region
59-
self._endpoint = format_endpoint(Endpoint, Region)
61+
self._endpoint = Endpoint
6062
self._ip = to_unicode(IP)
6163
self._port = Port
6264
self._anonymous = Anonymous
6365
self._ua = UA
6466
self._proxies = Proxies
67+
self._domain = Domain
68+
self._service_domain = ServiceDomain
6569

70+
if self._domain is None:
71+
self._endpoint = format_endpoint(Endpoint, Region)
6672
if Scheme is None:
6773
Scheme = u'https'
6874
Scheme = to_unicode(Scheme)
@@ -83,21 +89,27 @@ def __init__(self, Appid=None, Region=None, SecretId=None, SecretKey=None, Token
8389
else:
8490
raise CosClientError('SecretId and SecretKey is Required!')
8591

86-
def uri(self, bucket, path=None, endpoint=None):
92+
def uri(self, bucket, path=None, endpoint=None, domain=None):
8793
"""拼接url
8894
8995
:param bucket(string): 存储桶名称.
9096
:param path(string): 请求COS的路径.
9197
:return(string): 请求COS的URL地址.
9298
"""
93-
bucket = format_bucket(bucket, self._appid)
9499
scheme = self._scheme
95-
if endpoint is None:
96-
endpoint = self._endpoint
97-
98100
# 拼接请求的url,默认使用bucket和endpoint拼接请求域名
99-
# 指定ip和port时,则使用ip:port方式访问
100-
url = u"{bucket}.{endpoint}".format(bucket=bucket, endpoint=endpoint)
101+
# 使用自定义域名时则使用自定义域名访问
102+
# 指定ip和port时,则使用ip:port方式访问,优先级最高
103+
if domain is None:
104+
domain = self._domain
105+
if domain is not None:
106+
url = domain
107+
else:
108+
bucket = format_bucket(bucket, self._appid)
109+
if endpoint is None:
110+
endpoint = self._endpoint
111+
112+
url = u"{bucket}.{endpoint}".format(bucket=bucket, endpoint=endpoint)
101113
if self._ip is not None:
102114
url = self._ip
103115
if self._port is not None:
@@ -211,8 +223,11 @@ def send_request(self, method, url, bucket, timeout=30, **kwargs):
211223
kwargs['headers']['User-Agent'] = 'cos-python-sdk-v' + __version__
212224
if self._conf._token is not None:
213225
kwargs['headers']['x-cos-security-token'] = self._conf._token
214-
if bucket is not None:
215-
kwargs['headers']['Host'] = self._conf.get_host(bucket)
226+
if self._conf._ip is not None: # 使用IP访问时需要设置请求host
227+
if self._conf._domain is not None:
228+
kwargs['headers']['Host'] = self._conf._domain
229+
elif bucket is not None:
230+
kwargs['headers']['Host'] = self._conf.get_host(bucket)
216231
kwargs['headers'] = format_values(kwargs['headers'])
217232
if 'data' in kwargs:
218233
kwargs['data'] = to_bytes(kwargs['data'])
@@ -2054,7 +2069,7 @@ def put_bucket_policy(self, Bucket, Policy, **kwargs):
20542069
body = Policy
20552070
policy_type = type(body)
20562071
if policy_type != str and policy_type != dict:
2057-
raise CosClientError("Policy must be a json foramt string or json format dict")
2072+
raise CosClientError("Policy must be a json format string or json format dict")
20582073
if policy_type == dict:
20592074
body = json.dumps(body)
20602075

@@ -2574,6 +2589,89 @@ def delete_bucket_tagging(self, Bucket, **kwargs):
25742589
params=params)
25752590
return None
25762591

2592+
def put_bucket_referer(self, Bucket, RefererConfiguration={}, **kwargs):
2593+
"""设置bucket的防盗链规则
2594+
2595+
:param Bucket(string): 存储桶名称.
2596+
:param RefererConfiguration(dict): Bucket的防盗链规则
2597+
:param kwargs(dict): 设置请求headers.
2598+
:return: None.
2599+
2600+
.. code-block:: python
2601+
2602+
config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象
2603+
client = CosS3Client(config)
2604+
# 设置bucket标签
2605+
referer_config = {
2606+
'Status': 'Enabled',
2607+
'RefererType': 'White-List',
2608+
'EmptyReferConfiguration': 'Allow',
2609+
'DomainList': {
2610+
'Domain': [
2611+
'*.qq.com',
2612+
'*.qcloud.com'
2613+
]
2614+
}
2615+
}
2616+
response = client.put_bucket_referer(
2617+
Bucket='bucket',
2618+
RefererConfiguration=referer_config
2619+
)
2620+
"""
2621+
lst = ['<Domain>', '</Domain>'] # 类型为list的标签
2622+
xml_config = format_xml(data=RefererConfiguration, root='RefererConfiguration', lst=lst)
2623+
headers = mapped(kwargs)
2624+
headers['Content-MD5'] = get_md5(xml_config)
2625+
headers['Content-Type'] = 'application/xml'
2626+
params = {'referer': ''}
2627+
url = self._conf.uri(bucket=Bucket)
2628+
logger.info("put bucket referer, url=:{url} ,headers=:{headers}".format(
2629+
url=url,
2630+
headers=headers))
2631+
rt = self.send_request(
2632+
method='PUT',
2633+
url=url,
2634+
bucket=Bucket,
2635+
data=xml_config,
2636+
auth=CosS3Auth(self._conf, params=params),
2637+
headers=headers,
2638+
params=params)
2639+
return None
2640+
2641+
def get_bucket_referer(self, Bucket, **kwargs):
2642+
"""获取bucket防盗链规则
2643+
2644+
:param Bucket(string): 存储桶名称.
2645+
:param kwargs(dict): 设置请求headers.
2646+
:return(dict): Bucket对应的防盗链规则.
2647+
2648+
.. code-block:: python
2649+
2650+
config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token) # 获取配置对象
2651+
client = CosS3Client(config)
2652+
# 获取bucket标签
2653+
response = client.get_bucket_referer(
2654+
Bucket='bucket'
2655+
)
2656+
"""
2657+
headers = mapped(kwargs)
2658+
params = {'referer': ''}
2659+
url = self._conf.uri(bucket=Bucket)
2660+
logger.info("get bucket referer, url=:{url} ,headers=:{headers}".format(
2661+
url=url,
2662+
headers=headers))
2663+
rt = self.send_request(
2664+
method='GET',
2665+
url=url,
2666+
bucket=Bucket,
2667+
auth=CosS3Auth(self._conf, params=params),
2668+
headers=headers,
2669+
params=params)
2670+
data = xml_to_dict(rt.content)
2671+
if 'DomainList' in data:
2672+
format_dict(data['DomainList'], ['Domain'])
2673+
return data
2674+
25772675
# service interface begin
25782676
def list_buckets(self, **kwargs):
25792677
"""列出所有bucket
@@ -2590,7 +2688,9 @@ def list_buckets(self, **kwargs):
25902688
)
25912689
"""
25922690
headers = mapped(kwargs)
2593-
url = 'http://service.cos.myqcloud.com/'
2691+
url = 'https://service.cos.myqcloud.com/'
2692+
if self._conf._service_domain is not None:
2693+
url = 'https://{domain}/'.format(domain=self._conf._service_domain)
25942694
rt = self.send_request(
25952695
method='GET',
25962696
url=url,
@@ -2809,7 +2909,7 @@ def _inner_head_object(self, CopySource):
28092909
params = {}
28102910
if versionid != '':
28112911
params['versionId'] = versionid
2812-
url = self._conf.uri(bucket=bucket, path=path, endpoint=endpoint)
2912+
url = u"{scheme}://{bucket}.{endpoint}/{path}".format(scheme=self._conf._scheme, bucket=bucket, endpoint=endpoint, path=path)
28132913
rt = self.send_request(
28142914
method='HEAD',
28152915
url=url,

qcloud_cos/cos_comm.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,8 @@ def get_copy_source_info(CopySource):
309309
endpoint = format_endpoint(endpoint, region)
310310
if 'Key' in CopySource:
311311
path = to_unicode(CopySource['Key'])
312+
if path and path[0] == '/':
313+
path = path[1:]
312314
else:
313315
raise CosClientError('CopySource Need Parameter Key')
314316
if 'VersionId' in CopySource:

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def long_description():
1616

1717
setup(
1818
name='cos-python-sdk-v5',
19-
version='1.7.6',
19+
version='1.7.7',
2020
url='https://www.qcloud.com/',
2121
license='MIT',
2222
author='tiedu, lewzylu, channingliu',

ut/test.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1031,6 +1031,29 @@ def _test_put_get_delete_bucket_origin():
10311031
)
10321032

10331033

1034+
def test_put_get_bucket_referer():
1035+
"""测试设置获取bucket防盗链规则"""
1036+
referer_config = {
1037+
'Status': 'Enabled',
1038+
'RefererType': 'White-List',
1039+
'EmptyReferConfiguration': 'Allow',
1040+
'DomainList': {
1041+
'Domain': [
1042+
'*.qq.com',
1043+
'*.qcloud.com'
1044+
]
1045+
}
1046+
}
1047+
response = client.put_bucket_referer(
1048+
Bucket=test_bucket,
1049+
RefererConfiguration=referer_config
1050+
)
1051+
time.sleep(4)
1052+
response = client.get_bucket_referer(
1053+
Bucket=test_bucket,
1054+
)
1055+
1056+
10341057
if __name__ == "__main__":
10351058
setUp()
10361059
"""
@@ -1051,6 +1074,7 @@ def _test_put_get_delete_bucket_origin():
10511074
test_put_get_bucket_policy()
10521075
test_put_file_like_object()
10531076
test_put_chunked_object()
1054-
"""
10551077
test_put_get_delete_bucket_inventory()
1078+
"""
1079+
test_put_get_bucket_referer()
10561080
tearDown()

0 commit comments

Comments
 (0)