Exclude content-length header from request signature

Despite of SberCloud sample for python, content-length header is not accounted for
when calculating signature.

Signed-off-by: Vladimir Domnich <v.domnich@yadro.com>
This commit is contained in:
Vladimir Domnich 2022-08-22 15:45:43 +04:00 committed by Vladimir Domnich
parent 9454c5eb95
commit 590a5cfb0e

View file

@ -60,21 +60,26 @@ class SberCloudAuthRequests:
self.secret_key = secret_key self.secret_key = secret_key
def get(self, path: str, query: Optional[dict] = None) -> requests.Response: def get(self, path: str, query: Optional[dict] = None) -> requests.Response:
return self._send_request("GET", path, query, content="") return self._send_request("GET", path, query, data=None)
def post(self, path: str, query: Optional[dict] = None, def post(self, path: str, query: Optional[dict] = None,
data: Optional[dict] = None) -> requests.Response: data: Optional[dict] = None) -> requests.Response:
content = json.dumps(data) if data else "" return self._send_request("POST", path, query, data)
return self._send_request("POST", path, query, content)
def _send_request(self, method: str, path: str, query: Optional[dict], def _send_request(self, method: str, path: str, query: Optional[dict],
content: str) -> requests.Response: data: Optional[dict]) -> requests.Response:
body = content.encode(self.ENCODING)
if self.base_path: if self.base_path:
path = self.base_path + path path = self.base_path + path
timestamp = datetime.strftime(datetime.utcnow(), self.TIMESTAMP_FORMAT) timestamp = datetime.strftime(datetime.utcnow(), self.TIMESTAMP_FORMAT)
headers = self._build_original_headers(timestamp, body) headers = self._build_original_headers(timestamp)
content = ""
if data:
# At the moment we support json content only
content = json.dumps(data)
headers["Content-Type"] = "application/json"
body = content.encode(self.ENCODING)
signed_headers = self._build_signed_headers(headers) signed_headers = self._build_signed_headers(headers)
canonical_request = self._build_canonical_request(method, path, query, body, headers, canonical_request = self._build_canonical_request(method, path, query, body, headers,
@ -91,16 +96,11 @@ class SberCloudAuthRequests:
f"response={response.text})") f"response={response.text})")
return response return response
def _build_original_headers(self, timestamp: str, body: bytes) -> dict[str, str]: def _build_original_headers(self, timestamp: str) -> dict[str, str]:
headers = {} return {
headers["X-Sdk-Date"] = timestamp "X-Sdk-Date": timestamp,
headers["host"] = self.endpoint "host": self.endpoint,
}
if body:
headers["Content-Type"] = "application/json"
headers["content-length"] = str(len(body))
return headers
def _build_signed_headers(self, headers: dict[str, str]) -> list[str]: def _build_signed_headers(self, headers: dict[str, str]) -> list[str]:
return sorted(header_name.lower() for header_name in headers) return sorted(header_name.lower() for header_name in headers)
@ -127,7 +127,7 @@ class SberCloudAuthRequests:
normalized_key = key.lower() normalized_key = key.lower()
normalized_value = value.strip() normalized_value = value.strip()
normalized_headers[normalized_key] = normalized_value normalized_headers[normalized_key] = normalized_value
# Re-encode header in request itself # Re-encode header in request itself (iso-8859-1 comes from HTTP 1.1 standard)
headers[key] = normalized_value.encode(self.ENCODING).decode("iso-8859-1") headers[key] = normalized_value.encode(self.ENCODING).decode("iso-8859-1")
# Join headers in the same order as they are sorted in signed_headers list # Join headers in the same order as they are sorted in signed_headers list