fix: sign /upload with empty body — API skips body parsing for streams
The upload endpoint streams the request body in chunks without buffering, so raw_body stays empty on the server side. The HMAC must sign against an empty body string to match. _sign_from_disk (which hashed file contents) produced signatures the server could never verify — every upload got 401.
This commit is contained in:
parent
c3072c2a6e
commit
94166be988
1 changed files with 5 additions and 16 deletions
|
|
@ -41,32 +41,21 @@ def _sign_body(secret_key, timestamp, method, path, body_bytes):
|
||||||
return h.hexdigest()
|
return h.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
def _sign_from_disk(secret_key, timestamp, method, path, file_path):
|
|
||||||
"""Incremental HMAC-SHA256 matching un._sign_request but reading from disk.
|
|
||||||
|
|
||||||
Produces: HMAC(key, "ts:METHOD:path:" + <file contents>)
|
|
||||||
"""
|
|
||||||
h = hmac.new(secret_key.encode(), digestmod=hashlib.sha256)
|
|
||||||
h.update(f"{timestamp}:{method}:{path}:".encode())
|
|
||||||
with open(file_path, "rb") as f:
|
|
||||||
while True:
|
|
||||||
chunk = f.read(_READ_CHUNK)
|
|
||||||
if not chunk:
|
|
||||||
break
|
|
||||||
h.update(chunk)
|
|
||||||
return h.hexdigest()
|
|
||||||
|
|
||||||
|
|
||||||
def _upload_file(file_path, filename, public_key, secret_key):
|
def _upload_file(file_path, filename, public_key, secret_key):
|
||||||
"""Upload a file via POST /upload (streaming, constant memory).
|
"""Upload a file via POST /upload (streaming, constant memory).
|
||||||
|
|
||||||
Returns the upload_id string.
|
Returns the upload_id string.
|
||||||
|
|
||||||
|
Note: the API skips body parsing for /upload (body streams in chunks),
|
||||||
|
so the HMAC signs against an empty body — not the file content.
|
||||||
"""
|
"""
|
||||||
timestamp = int(time.time())
|
timestamp = int(time.time())
|
||||||
method = "POST"
|
method = "POST"
|
||||||
path = "/upload"
|
path = "/upload"
|
||||||
|
|
||||||
signature = _sign_from_disk(secret_key, timestamp, method, path, file_path)
|
# API doesn't buffer upload bodies for HMAC — sign with empty body
|
||||||
|
signature = _sign_body(secret_key, timestamp, method, path, "")
|
||||||
|
|
||||||
headers = {
|
headers = {
|
||||||
"Authorization": f"Bearer {public_key}",
|
"Authorization": f"Bearer {public_key}",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue