Skip to content

Commit 2b42e66

Browse files
add test case
1 parent d595859 commit 2b42e66

File tree

2 files changed

+61
-2
lines changed

2 files changed

+61
-2
lines changed

pyiceberg/catalog/rest/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ class IdentifierKind(Enum):
216216
SIGV4 = "rest.sigv4-enabled"
217217
SIGV4_REGION = "rest.signing-region"
218218
SIGV4_SERVICE = "rest.signing-name"
219+
EMPTY_BODY_SHA256: str = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
219220
OAUTH2_SERVER_URI = "oauth2-server-uri"
220221
SNAPSHOT_LOADING_MODE = "snapshot-loading-mode"
221222
AUTH = "auth"
@@ -565,7 +566,7 @@ def add_headers(self, request: PreparedRequest, **kwargs: Any) -> None: # pylin
565566
# For empty bodies, explicitly set the content hash header to the SHA256 of an empty string
566567
body = request.body
567568
if body in (None, b"", ""):
568-
request.headers["x-amz-content-sha256"] = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
569+
request.headers["x-amz-content-sha256"] = EMPTY_BODY_SHA256
569570

570571
aws_request = AWSRequest(
571572
method=request.method, url=url, params=params, data=request.body, headers=dict(request.headers)

tests/catalog/test_rest.py

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@
2222
from unittest import mock
2323

2424
import pytest
25+
from requests import Request
26+
from requests.adapters import HTTPAdapter
2527
from requests.exceptions import HTTPError
2628
from requests_mock import Mocker
2729

2830
import pyiceberg
2931
from pyiceberg.catalog import PropertiesUpdateSummary, load_catalog
30-
from pyiceberg.catalog.rest import DEFAULT_ENDPOINTS, OAUTH2_SERVER_URI, SNAPSHOT_LOADING_MODE, Capability, RestCatalog
32+
from pyiceberg.catalog.rest import DEFAULT_ENDPOINTS, EMPTY_BODY_SHA256, OAUTH2_SERVER_URI, SNAPSHOT_LOADING_MODE, Capability, RestCatalog
3133
from pyiceberg.exceptions import (
3234
AuthorizationExpiredError,
3335
NamespaceAlreadyExistsError,
@@ -451,6 +453,62 @@ def test_list_tables_200_sigv4(rest_mock: Mocker) -> None:
451453
assert rest_mock.called
452454

453455

456+
def test_sigv4_sign_request_without_body(rest_mock: Mocker) -> None:
457+
existing_token = "existing_token"
458+
459+
catalog = RestCatalog(
460+
"rest",
461+
**{
462+
"uri": TEST_URI,
463+
"token": existing_token,
464+
"rest.sigv4-enabled": "true",
465+
"rest.signing-region": "us-west-2",
466+
"client.access-key-id": "id",
467+
"client.secret-access-key": "secret",
468+
},
469+
)
470+
471+
prepared = catalog._session.prepare_request(Request("GET", f"{TEST_URI}v1/config"))
472+
adapter = catalog._session.adapters[catalog.uri]
473+
assert isinstance(adapter, HTTPAdapter)
474+
adapter.add_headers(prepared)
475+
476+
assert prepared.headers["Authorization"].startswith("AWS4-HMAC-SHA256")
477+
assert prepared.headers["Original-Authorization"] == f"Bearer {existing_token}"
478+
assert prepared.headers["x-amz-content-sha256"] == EMPTY_BODY_SHA256
479+
480+
481+
def test_sigv4_sign_request_with_body(rest_mock: Mocker) -> None:
482+
existing_token = "existing_token"
483+
484+
catalog = RestCatalog(
485+
"rest",
486+
**{
487+
"uri": TEST_URI,
488+
"token": existing_token,
489+
"rest.sigv4-enabled": "true",
490+
"rest.signing-region": "us-west-2",
491+
"client.access-key-id": "id",
492+
"client.secret-access-key": "secret",
493+
},
494+
)
495+
496+
prepared = catalog._session.prepare_request(
497+
Request(
498+
"POST",
499+
f"{TEST_URI}v1/namespaces",
500+
data={"namespace": "asdfasd"},
501+
)
502+
)
503+
adapter = catalog._session.adapters[catalog.uri]
504+
assert isinstance(adapter, HTTPAdapter)
505+
adapter.add_headers(prepared)
506+
507+
assert prepared.headers["Authorization"].startswith("AWS4-HMAC-SHA256")
508+
assert prepared.headers["Original-Authorization"] == f"Bearer {existing_token}"
509+
assert prepared.headers.get("x-amz-content-sha256") != EMPTY_BODY_SHA256
510+
511+
454512
def test_list_tables_404(rest_mock: Mocker) -> None:
455513
namespace = "examples"
456514
rest_mock.get(

0 commit comments

Comments
 (0)