8000 Merge pull request #412 from qiniu/fix/auth-qiniu-headers · qiniu/python-sdk@c1bfdf8 · GitHub
[go: up one dir, main page]

Skip to content {"props":{"docsUrl":"https://docs.github.com/get-started/accessibility/keyboard-shortcuts"}}

Commit c1bfdf8

Browse files
authored
Merge pull request #412 from qiniu/fix/auth-qiniu-headers
Fix auth qiniu headers
2 parents c160e08 + d9d890e commit c1bfdf8

File tree

6 files changed

+243
-43
lines changed

6 files changed

+243
-43
lines changed

qiniu/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,4 @@
2727
from .services.compute.qcos_api import QcosClient
2828
from .services.sms.sms import Sms
2929
from .services.pili.rtc_server_manager import RtcServer, get_room_token
30-
from .utils import urlsafe_base64_encode, urlsafe_base64_decode, etag, entry
30+
from .utils import urlsafe_base64_encode, urlsafe_base64_decode, etag, entry, canonical_mime_header_key

qiniu/auth.py

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from hashlib import sha1
66
from requests.auth import AuthBase
77
from .compat import urlparse, json, b
8-
from .utils import urlsafe_base64_encode
8+
from .utils import urlsafe_base64_encode, canonical_mime_header_key
99

1010
# 上传策略,参数规格详见
1111
# https://developer.qiniu.com/kodo/manual/1206/put-policy
@@ -58,6 +58,9 @@ def __init__(self, access_key, secret_key):
5858
def get_access_key(self):
5959
return self.__access_key
6060

61+
def get_secret_key(self):
62+
return self.__secret_key
63+
6164
def __token(self, data):
6265
data = b(data)
6366
hashed = hmac.new(self.__secret_key, data, sha1)
@@ -265,15 +268,21 @@ def token_of_request(
265268
path_with_query = path
266269
if query != '':
267270
path_with_query = ''.join([path_with_query, '?', query])
268-
data = ''.join(["%s %s" %
269-
(method, path_with_query), "\n", "Host: %s" %
270-
host, "\n"])
271+
data = ''.join([
272+
"%s %s" % (method, path_with_query),
273+
"\n",
274+
"Host: %s" % host
275+
])
271276

272277
if content_type:
273-
data += "Content-Type: %s" % (content_type) + "\n"
278+
data += "\n"
279+
data += "Content-Type: %s" % content_type
280+
281+
if qheaders:
282+
data += "\n"
283+
data += qheaders
274284

275-
data += qheaders
276-
data += "\n"
285+
data += "\n\n"
277286

278287
if content_type and content_type != "application/octet-stream" and body:
279288
if isinstance(body, bytes):
@@ -283,11 +292,13 @@ def token_of_request(
283292
return '{0}:{1}'.format(self.__access_key, self.__token(data))
284293

285294
def qiniu_headers(self, headers):
286-
res = ""
287-
for key in headers:
288-
if key.startswith(self.qiniu_header_prefix):
289-
res += key + ": %s\n" % (headers.get(key))
290-
return res
295+
qiniu_fields = list(filter(
296+
lambda k: k.startswith(self.qiniu_header_prefix) and len(k) > len(self.qiniu_header_prefix),
297+
headers,
298+
))
299+
return "\n".join([
300+
"%s: %s" % (canonical_mime_header_key(key), headers.get(key)) for key in sorted(qiniu_fields)
301+
])
291302

292303
@staticmethod
293304
def __checkKey(access_key, secret_key):
@@ -300,6 +311,8 @@ def __init__(self, auth):
300311
self.auth = auth
301312

302313
def __call__(self, r):
314+
if r.headers.get('Content-Type', None) is None:
315+
r.headers['Content-Type'] = 'application/x-www-form-urlencoded'
303316
token = self.auth.token_of_request(
304317
r.method, r.headers.get('Host', None),
305318
r.url, self.auth.qiniu_headers(r.headers),

qiniu/http.py

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -76,16 +76,16 @@ def _get(url, params, auth, headers=None):
7676
if _session is None:
7777
_init()
7878
try:
79-
post_headers = _headers.copy()
79+
get_headers = _headers.copy()
8080
if headers is not None:
8181
for k, v in headers.items():
82-
post_headers.update({k: v})
82+
get_headers.update({k: v})
8383
r = _session.get(
8484
url,
8585
params=params,
8686
auth=auth,
8787
timeout=config.get_default('connection_timeout'),
88-
headers=post_headers)
88+
headers=get_headers)
8989
except Exception as e:
9090
return None, ResponseInfo(None, e)
9191
return __return_wrapper(r)
@@ -150,31 +150,16 @@ def _put_with_qiniu_mac_and_headers(url, data, auth, headers):
150150

151151
def _post_with_qiniu_mac(url, data, auth):
152152
qn_auth = qiniu.auth.QiniuMacRequestsAuth(
153-
auth) if auth is not None else None
154-
timeout = config.get_default('connection_timeout')
155-
try:
156-
r = requests.post(
157-
url,
158-
json=data,
159-
auth=qn_auth,
160-
timeout=timeout,
161-
headers=_headers)
162-
except Exception as e:
163-
return None, ResponseInfo(None, e)
164-
return __return_wrapper(r)
153+
auth
154+
) if auth is not None else None
155+
return _post(url, data, None, qn_auth)
165156

166157

167158
def _get_with_qiniu_mac(url, params, auth):
168-
try:
169-
r = requests.get(
170-
url,
171-
params=params,
172-
auth=qiniu.auth.QiniuMacRequestsAuth(auth) if auth is not None else None,
173-
timeout=config.get_default('connection_timeout'),
174-
headers=_headers)
175-
except Exception as e:
176-
return None, ResponseInfo(None, e)
177-
return __return_wrapper(r)
159+
qn_auth = qiniu.auth.QiniuMacRequestsAuth(
160+
auth
161+
) if auth is not None else None
162+
return _get(url, params, qn_auth)
178163

179164

180165
def _get_with_qiniu_mac_and_headers(url, params, auth, headers):

qiniu/services/storage/bucket.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: utf-8 -*-
22

3-
from qiniu import config
3+
from qiniu import config, QiniuMacAuth
44
from qiniu import http
55
from qiniu.utils import urlsafe_base64_encode, entry
66

@@ -17,6 +17,7 @@ class BucketManager(object):
1717

1818
def __init__(self, auth, zone=None):
1919
self.auth = auth
20+
self.mac_auth = QiniuMacAuth(auth.get_access_key(), auth.get_secret_key())
2021
if (zone is None):
2122
self.zone = config.get_default('default_zone')
2223
else:
@@ -387,10 +388,10 @@ def __server_do(self, host, operation, *args):
387388
return self.__post(url)
388389

389390
def __post(self, url, data=None):
390-
return http._post_with_auth(url, data, self.auth)
391+
return http._post_with_qiniu_mac(url, data, self.mac_auth)
391392

392393
def __get(self, url, params=None):
393-
return http._get_with_auth(url, params, self.auth)
394+
return http._get_with_qiniu_mac(url, params, self.mac_auth)
394395

395396

396397
def _build_op(*args):

qiniu/utils.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,35 @@ def rfc_from_timestamp(timestamp):
172172
last_modified_str = last_modified_date.strftime(
173173
'%a, %d %b %Y %H:%M:%S GMT')
174174
return last_modified_str
175+
176+
177+
def _valid_header_key_char(ch):
178+
is_token_table = [
179+
"!", "#", "$", "%", "&", "\\", "*", "+", "-", ".",
180+
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
181+
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
182+
"K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
183+
"U", "W", "V", "X", "Y", "Z",
184+
"^", "_", "`",
185+
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
186+
"k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
187+
"u", "v", "w", "x", "y", "z",
188+
"|", "~"]
189+
return 0 <= ord(ch) < 128 and ch in is_token_table
190+
191+
192+
def canonical_mime_header_key(field_name):
193+
for ch in field_name:
194+
if not _valid_header_key_char(ch):
195+
return field_name
196+
result = ""
197+
upper = True
198+
for ch in field_name:
199+
if upper and "a" <= ch <= "z":
200+
result += ch.upper()
201+
elif not upper and "A" <= ch <= "Z":
202+
result += ch.lower()
203+
else:
204+
result += ch
205+
upper = ch == "-"
206+
return result

0 commit comments

Comments
 (0)
0