Skip to content

Commit 3800c52

Browse files
authored
Merge pull request #244 from jemygraw/master
add cdn related functions to python sdk
2 parents a039a63 + 0fe9277 commit 3800c52

File tree

9 files changed

+357
-25
lines changed

9 files changed

+357
-25
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ before_script:
2121
script:
2222
- if [[ "$TRAVIS_PYTHON_VERSION" != "2.6.9" ]]; then flake8 --show-source --max-line-length=160 .; fi
2323
- py.test --cov qiniu
24-
- ocular --data-file .coverage
24+
- if [[ "$TRAVIS_PYTHON_VERSION" != "2.6.9" ]]; then ocular --data-file .coverage; fi
2525
deploy:
2626
provider: pypi
2727
user: qiniusdk

examples/cdn_manager.py

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# -*- coding: utf-8 -*-
2+
import qiniu
3+
from qiniu import CdnManager
4+
from qiniu import create_timestamp_anti_leech_url
5+
import time
6+
7+
8+
# 演示函数调用结果
9+
def print_result(result):
10+
if result[0] is not None:
11+
print(type(result[0]))
12+
print(result[0])
13+
14+
print(type(result[1]))
15+
print(result[1])
16+
17+
18+
# 账户ak,sk
19+
access_key = '...'
20+
secret_key = '...'
21+
22+
auth = qiniu.Auth(access_key=access_key, secret_key=secret_key)
23+
cdn_manager = CdnManager(auth)
24+
25+
urls = [
26+
'http://if-pbl.qiniudn.com/qiniu.jpg',
27+
'http://if-pbl.qiniudn.com/qiniu2.jpg'
28+
]
29+
30+
# 注意链接最后的斜杠表示目录
31+
dirs = [
32+
'http://if-pbl.qiniudn.com/test1/',
33+
'http://if-pbl.qiniudn.com/test2/'
34+
]
35+
"""刷新文件,目录"""
36+
37+
# 刷新链接
38+
print('刷新文件')
39+
refresh_url_result = cdn_manager.refresh_urls(urls)
40+
print_result(refresh_url_result)
41+
42+
# 刷新目录需要联系七牛技术支持开通权限
43+
print('刷新目录')
44+
refresh_dir_result = cdn_manager.refresh_dirs(dirs)
45+
print_result(refresh_dir_result)
46+
47+
# 同时刷新文件和目录
48+
print('刷新文件和目录')
49+
refresh_all_result = cdn_manager.refresh_urls_and_dirs(urls, dirs)
50+
print_result(refresh_all_result)
51+
52+
"""预取文件"""
53+
54+
# 预取文件链接
55+
print('预取文件链接')
56+
prefetch_url_result = cdn_manager.prefetch_urls(urls)
57+
print_result(prefetch_url_result)
58+
59+
"""获取带宽和流量数据"""
60+
61+
domains = ['if-pbl.qiniudn.com', 'qdisk.qiniudn.com']
62+
63+
start_date = '2017-01-01'
64+
end_date = '2017-01-02'
65+
66+
# 5min or hour or day
67+
granularity = 'day'
68+
69+
# 获取带宽数据
70+
print('获取带宽数据')
71+
bandwidth_data = cdn_manager.get_bandwidth_data(domains, start_date, end_date, granularity)
72+
print_result(bandwidth_data)
73+
74+
# 获取流量数据
75+
print('获取流量数据')
76+
flux_data = cdn_manager.get_flux_data(domains, start_date, end_date, granularity)
77+
print_result(flux_data)
78+
79+
"""获取日志文件下载地址列表"""
80+
# 获取日志列表
81+
print('获取日志列表')
82+
log_date = '2017-01-01'
83+
log_data = cdn_manager.get_log_list_data(domains, log_date)
84+
print_result(log_data)
85+
86+
"""构建时间戳防盗链"""
87+
88+
# 构建时间戳防盗链
89+
print('构建时间戳防盗链')
90+
91+
# 时间戳防盗链密钥,后台获取
92+
encrypt_key = 'xxx'
93+
94+
# 原始文件名,必须是utf8编码
95+
test_file_name1 = '基本概括.mp4'
96+
test_file_name2 = '2017/01/07/test.png'
97+
98+
# 查询参数列表
99+
query_string_dict = {
100+
'name': '七牛',
101+
'year': 2017,
102+
'年龄': 28,
103+
}
104+
105+
# 带访问协议的域名
106+
host = 'http://video.example.com'
107+
108+
# unix时间戳
109+
deadline = int(time.time()) + 3600
110+
111+
# 带查询参数,中文文件名
112+
signed_url1 = create_timestamp_anti_leech_url(host, test_file_name1, query_string_dict, encrypt_key, deadline)
113+
print(signed_url1)
114+
115+
# 带查询参数,英文文件名
116+
signed_url2 = create_timestamp_anti_leech_url(host, test_file_name2, query_string_dict, encrypt_key, deadline)
117+
print(signed_url2)
118+
119+
# 不带查询参数,中文文件名
120+
signed_url3 = create_timestamp_anti_leech_url(host, test_file_name1, None, encrypt_key, deadline)
121+
print(signed_url3)
122+
123+
# 不带查询参数,英文文件名
124+
signed_url4 = create_timestamp_anti_leech_url(host, test_file_name2, None, encrypt_key, deadline)
125+
print(signed_url4)

qiniu/__init__.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616
from .config import set_default
1717
from .zone import Zone
1818

19-
from .services.storage.bucket import BucketManager, build_batch_copy, build_batch_rename, build_batch_move, build_batch_stat, build_batch_delete
19+
from .services.storage.bucket import BucketManager, build_batch_copy, build_batch_rename, build_batch_move, \
20+
build_batch_stat, build_batch_delete
2021
from .services.storage.uploader import put_data, put_file, put_stream
22+
from .services.cdn.manager import CdnManager, create_timestamp_anti_leech_url
2123
from .services.processing.pfop import PersistentFop
2224
from .services.processing.cmd import build_op, pipe_cmd, op_save
2325
from .services.compute.app import AccountClient

qiniu/http.py

+11-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import qiniu.auth
99
from . import __version__
1010

11-
1211
_sys_info = '{0}; {1}'.format(platform.system(), platform.machine())
1312
_python_ver = platform.python_version()
1413

@@ -35,12 +34,17 @@ def _init():
3534
_session = session
3635

3736

38-
def _post(url, data, files, auth):
37+
def _post(url, data, files, auth, headers=None):
3938
if _session is None:
4039
_init()
4140
try:
41+
post_headers = _headers
42+
if headers is not None:
43+
for k, v in headers.items():
44+
post_headers.update({k: v})
4245
r = _session.post(
43-
url, data=data, files=files, auth=auth, headers=_headers, timeout=config.get_default('connection_timeout'))
46+
url, data=data, files=files, auth=auth, headers=post_headers,
47+
timeout=config.get_default('connection_timeout'))
4448
except Exception as e:
4549
return None, ResponseInfo(None, e)
4650
return __return_wrapper(r)
@@ -77,8 +81,11 @@ def _post_with_auth(url, data, auth):
7781
return _post(url, data, None, qiniu.auth.RequestsAuth(auth))
7882

7983

80-
def _post_with_qiniu_mac(url, data, auth):
84+
def _post_with_auth_and_headers(url, data, auth, headers):
85+
return _post(url, data, None, qiniu.auth.RequestsAuth(auth), headers)
8186

87+
88+
def _post_with_qiniu_mac(url, data, auth):
8289
qn_auth = qiniu.auth.QiniuMacRequestsAuth(auth) if auth is not None else None
8390
timeout = config.get_default('connection_timeout')
8491

qiniu/services/cdn/__init__.py

Whitespace-only changes.

qiniu/services/cdn/manager.py

+198
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from qiniu import http
4+
import json
5+
6+
from qiniu.compat import is_py2
7+
from qiniu.compat import is_py3
8+
9+
import hashlib
10+
11+
12+
def urlencode(str):
13+
if is_py2:
14+
import urllib2
15+
return urllib2.quote(str)
16+
elif is_py3:
17+
import urllib.parse
18+
return urllib.parse.quote(str)
19+
20+
21+
class CdnManager(object):
22+
def __init__(self, auth):
23+
self.auth = auth
24+
self.server = 'http://fusion.qiniuapi.com'
25+
26+
def refresh_urls(self, urls):
27+
"""
28+
刷新文件列表,文档 http://developer.qiniu.com/article/fusion/api/refresh.html
29+
30+
Args:
31+
urls: 待刷新的文件外链列表
32+
33+
Returns:
34+
一个dict变量和一个ResponseInfo对象
35+
参考代码 examples/cdn_manager.py
36+
"""
37+
return self.refresh_urls_and_dirs(urls, None)
38+
39+
def refresh_dirs(self, dirs):
40+
"""
41+
刷新目录,文档 http://developer.qiniu.com/article/fusion/api/refresh.html
42+
43+
Args:
44+
urls: 待刷新的目录列表
45+
46+
Returns:
47+
一个dict变量和一个ResponseInfo对象
48+
参考代码 examples/cdn_manager.py
49+
"""
50+
return self.refresh_urls_and_dirs(None, dirs)
51+
52+
def refresh_urls_and_dirs(self, urls, dirs):
53+
"""
54+
刷新文件目录,文档 http://developer.qiniu.com/article/fusion/api/refresh.html
55+
56+
Args:
57+
urls: 待刷新的目录列表
58+
dirs: 待刷新的文件列表
59+
60+
Returns:
61+
一个dict变量和一个ResponseInfo对象
62+
参考代码 examples/cdn_manager.py
63+
"""
64+
req = {}
65+
if urls is not None and len(urls) > 0:
66+
req.update({"urls": urls})
67+
if dirs is not None and len(dirs) > 0:
68+
req.update({"dirs": dirs})
69+
70+
body = json.dumps(req)
71+
url = '{0}/v2/tune/refresh'.format(self.server)
72+
return self.__post(url, body)
73+
74+
def prefetch_urls(self, urls):
75+
"""
76+
预取文件列表,文档 http://developer.qiniu.com/article/fusion/api/prefetch.html
77+
78+
Args:
79+
urls: 待预取的文件外链列表
80+
81+
Returns:
82+
一个dict变量和一个ResponseInfo对象
83+
参考代码 examples/cdn_manager.py
84+
"""
85+
req = {}
86+
req.update({"urls": urls})
87+
88+
body = json.dumps(req)
89+
url = '{0}/v2/tune/prefetch'.format(self.server)
90+
return self.__post(url, body)
91+
92+
def get_bandwidth_data(self, domains, start_date, end_date, granularity):
93+
"""
94+
预取带宽数据,文档 http://developer.qiniu.com/article/fusion/api/traffic-bandwidth.html
95+
96+
Args:
97+
domains: 域名列表
98+
start_date: 起始日期
99+
end_date: 结束日期
100+
granularity: 数据间隔
101+
102+
Returns:
103+
一个dict变量和一个ResponseInfo对象
104+
参考代码 examples/cdn_manager.py
105+
"""
106+
req = {}
107+
req.update({"domains": ';'.join(domains)})
108+
req.update({"startDate": start_date})
109+
req.update({"endDate": end_date})
110+
req.update({"granularity": granularity})
111+
112+
body = json.dumps(req)
113+
url = '{0}/v2/tune/bandwidth'.format(self.server)
114+
return self.__post(url, body)
115+
116+
def get_flux_data(self, domains, start_date, end_date, granularity):
117+
"""
118+
预取流量数据,文档 http://developer.qiniu.com/article/fusion/api/traffic-bandwidth.html
119+
120+
Args:
121+
domains: 域名列表
122+
start_date: 起始日期
123+
end_date: 结束日期
124+
granularity: 数据间隔
125+
126+
Returns:
127+
一个dict变量和一个ResponseInfo对象
128+
参考代码 examples/cdn_manager.py
129+
"""
130+
req = {}
131+
req.update({"domains": ';'.join(domains)})
132+
req.update({"startDate": start_date})
133+
req.update({"endDate": end_date})
134+
req.update({"granularity": granularity})
135+
136+
body = json.dumps(req)
137+
url = '{0}/v2/tune/flux'.format(self.server)
138+
return self.__post(url, body)
139+
140+
def get_log_list_data(self, domains, log_date):
141+
"""
142+
获取日志下载链接,文档 http://developer.qiniu.com/article/fusion/api/log.html
143+
144+
Args:
145+
domains: 域名列表
146+
log_date: 日志日期
147+
148+
Returns:
149+
一个dict变量和一个ResponseInfo对象
150+
参考代码 examples/cdn_manager.py
151+
"""
152+
req = {}
153+
req.update({"domains": ';'.join(domains)})
154+
req.update({"startDate": log_date})
155+
156+
body = json.dumps(req)
157+
url = '{0}/v2/tune/log/list'.format(self.server)
158+
return self.__post(url, body)
159+
160+
def __post(self, url, data=None):
161+
headers = {'Content-Type': 'application/json'}
162+
return http._post_with_auth_and_headers(url, data, self.auth, headers)
163+
164+
165+
def create_timestamp_anti_leech_url(host, file_name, query_string_dict, encrypt_key, deadline):
166+
"""
167+
创建时间戳防盗链
168+
169+
Args:
170+
host: 带访问协议的域名
171+
file_name: 原始文件名,不需要urlencode
172+
query_string_dict: 查询参数,不需要urlencode
173+
encrypt_key: 时间戳防盗链密钥
174+
deadline: 链接有效期时间戳(以秒为单位)
175+
176+
Returns:
177+
带时间戳防盗链鉴权访问链接
178+
"""
179+
if query_string_dict is not None and len(query_string_dict) > 0:
180+
query_string_items = []
181+
for k, v in query_string_dict.items():
182+
query_string_items.append('{0}={1}'.format(urlencode(str(k)), urlencode(str(v))))
183+
query_string = '&'.join(query_string_items)
184+
url_to_sign = '{0}/{1}?{2}'.format(host, urlencode(file_name), query_string)
185+
else:
186+
url_to_sign = '{0}/{1}'.format(host, urlencode(file_name))
187+
188+
path = '/{0}'.format(urlencode(file_name))
189+
expire_hex = str(hex(deadline))[2:]
190+
str_to_sign = '{0}{1}{2}'.format(encrypt_key, path, expire_hex).encode()
191+
sign_str = hashlib.md5(str_to_sign).hexdigest()
192+
193+
if query_string_dict is not None and len(query_string_dict) > 0:
194+
signed_url = '{0}&sign={1}&t={2}'.format(url_to_sign, sign_str, expire_hex)
195+
else:
196+
signed_url = '{0}?sign={1}&t={2}'.format(url_to_sign, sign_str, expire_hex)
197+
198+
return signed_url

0 commit comments

Comments
 (0)