Skip to content

Commit d47970b

Browse files
Add base headers in properties to signer_headers (#1610)
Include the headers defined in properties in the `signer_headers`. This is consistent with the behaviour of the default Java AWS signer: https://github.com/apache/iceberg/blob/e406e3db80d1735fe6c840ce99ecc300ae1dd763/aws/src/main/java/org/apache/iceberg/aws/s3/signer/S3V4RestSignerClient.java#L345. The headers in the auth session include the "base headers" which are those obtained from the catalog properties. --------- Co-authored-by: Thomas Powell <[email protected]>
1 parent 17e9110 commit d47970b

File tree

4 files changed

+16
-8
lines changed

4 files changed

+16
-8
lines changed

pyiceberg/catalog/rest.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@
7979
from pyiceberg.typedef import EMPTY_DICT, UTF8, IcebergBaseModel, Identifier, Properties
8080
from pyiceberg.types import transform_dict_value_to_str
8181
from pyiceberg.utils.deprecated import deprecation_message
82-
from pyiceberg.utils.properties import get_first_property_value, property_as_bool
82+
from pyiceberg.utils.properties import get_first_property_value, get_header_properties, property_as_bool
8383

8484
if TYPE_CHECKING:
8585
import pyarrow as pa
@@ -139,7 +139,6 @@ class IdentifierKind(Enum):
139139
SIGV4_SERVICE = "rest.signing-name"
140140
AUTH_URL = "rest.authorization-url"
141141
OAUTH2_SERVER_URI = "oauth2-server-uri"
142-
HEADER_PREFIX = "header."
143142

144143
NAMESPACE_SEPARATOR = b"\x1f".decode(UTF8)
145144

@@ -554,16 +553,13 @@ def _refresh_token(self, session: Optional[Session] = None, initial_token: Optio
554553
session.headers[AUTHORIZATION_HEADER] = f"{BEARER_PREFIX} {token}"
555554

556555
def _config_headers(self, session: Session) -> None:
557-
header_properties = self._extract_headers_from_properties()
556+
header_properties = get_header_properties(self.properties)
558557
session.headers.update(header_properties)
559558
session.headers["Content-type"] = "application/json"
560559
session.headers["X-Client-Version"] = ICEBERG_REST_SPEC_VERSION
561560
session.headers["User-Agent"] = f"PyIceberg/{__version__}"
562561
session.headers.setdefault("X-Iceberg-Access-Delegation", ACCESS_DELEGATION_DEFAULT)
563562

564-
def _extract_headers_from_properties(self) -> Dict[str, str]:
565-
return {key[len(HEADER_PREFIX) :]: value for key, value in self.properties.items() if key.startswith(HEADER_PREFIX)}
566-
567563
def _create_table(
568564
self,
569565
identifier: Union[str, Identifier],

pyiceberg/io/fsspec.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
OutputStream,
7979
)
8080
from pyiceberg.typedef import Properties
81-
from pyiceberg.utils.properties import get_first_property_value, property_as_bool
81+
from pyiceberg.utils.properties import get_first_property_value, get_header_properties, property_as_bool
8282

8383
logger = logging.getLogger(__name__)
8484

@@ -93,6 +93,7 @@ def s3v4_rest_signer(properties: Properties, request: "AWSRequest", **_: Any) ->
9393
signer_headers = {}
9494
if token := properties.get(TOKEN):
9595
signer_headers = {"Authorization": f"Bearer {token}"}
96+
signer_headers.update(get_header_properties(properties))
9697

9798
signer_body = {
9899
"method": request.method,

pyiceberg/utils/properties.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
from pyiceberg.typedef import Properties
2525
from pyiceberg.types import strtobool
2626

27+
HEADER_PREFIX = "header."
28+
2729

2830
def property_as_int(
2931
properties: Dict[str, str],
@@ -74,3 +76,10 @@ def get_first_property_value(
7476
if property_value := properties.get(property_name):
7577
return property_value
7678
return None
79+
80+
81+
def get_header_properties(
82+
properties: Properties,
83+
) -> Properties:
84+
header_prefix_len = len(HEADER_PREFIX)
85+
return {key[header_prefix_len:]: value for key, value in properties.items() if key.startswith(HEADER_PREFIX)}

tests/io/test_fsspec.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,7 @@ def test_s3v4_rest_signer(requests_mock: Mocker) -> None:
692692
"X-Amz-Security-Token": [
693693
"YQoJb3JpZ2luX2VjEDoaCXVzLXdlc3QtMiJGMEQCID/fFxZP5oaEgQmcwP6XhZa0xSq9lmLSx8ffaWbySfUPAiAesa7sjd/WV4uwRTO0S03y/MWVtgpH+/NyZQ4bZgLVriqrAggTEAEaDDAzMzQwNzIyMjE1OSIMOeFOWhZIurMmAqjsKogCxMCqxX8ZjK0gacAkcDqBCyA7qTSLhdfKQIH/w7WpLBU1km+cRUWWCudan6gZsAq867DBaKEP7qI05DAWr9MChAkgUgyI8/G3Z23ET0gAedf3GsJbakB0F1kklx8jPmj4BPCht9RcTiXiJ5DxTS/cRCcalIQXmPFbaJSqpBusVG2EkWnm1v7VQrNPE2Os2b2P293vpbhwkyCEQiGRVva4Sw9D1sKvqSsK10QCRG+os6dFEOu1kARaXi6pStvR4OVmj7OYeAYjzaFchn7nz2CSae0M4IluiYQ01eQAywbfRo9DpKSmDM/DnPZWJnD/woLhaaaCrCxSSEaFsvGOHFhLd3Rknw1v0jADMILUtJoGOp4BpqKqyMz0CY3kpKL0jfR3ykTf/ge9wWVE0Alr7wRIkGCIURkhslGHqSyFRGoTqIXaxU+oPbwlw/0w/nYO7qQ6bTANOWye/wgw4h/NmJ6vU7wnZTXwREf1r6MF72++bE/fMk19LfVb8jN/qrUqAUXTc8gBAUxL5pgy8+oT/JnI2BkVrrLS4ilxEXP9Ahm+6GDUYXV4fBpqpZwdkzQ/5Gw="
694694
],
695+
"X-Custom-Header": ["value"],
695696
},
696697
"extensions": {},
697698
},
@@ -714,7 +715,7 @@ def test_s3v4_rest_signer(requests_mock: Mocker) -> None:
714715
"retries": {"attempt": 1, "invocation-id": "75d143fb-0219-439b-872c-18213d1c8d54"},
715716
}
716717

717-
signed_request = s3v4_rest_signer({"token": "abc", "uri": TEST_URI}, request)
718+
signed_request = s3v4_rest_signer({"token": "abc", "uri": TEST_URI, "header.X-Custom-Header": "value"}, request)
718719

719720
assert signed_request.url == new_uri
720721
assert dict(signed_request.headers) == {
@@ -724,6 +725,7 @@ def test_s3v4_rest_signer(requests_mock: Mocker) -> None:
724725
"X-Amz-Date": "20221017T102940Z",
725726
"X-Amz-Security-Token": "YQoJb3JpZ2luX2VjEDoaCXVzLXdlc3QtMiJGMEQCID/fFxZP5oaEgQmcwP6XhZa0xSq9lmLSx8ffaWbySfUPAiAesa7sjd/WV4uwRTO0S03y/MWVtgpH+/NyZQ4bZgLVriqrAggTEAEaDDAzMzQwNzIyMjE1OSIMOeFOWhZIurMmAqjsKogCxMCqxX8ZjK0gacAkcDqBCyA7qTSLhdfKQIH/w7WpLBU1km+cRUWWCudan6gZsAq867DBaKEP7qI05DAWr9MChAkgUgyI8/G3Z23ET0gAedf3GsJbakB0F1kklx8jPmj4BPCht9RcTiXiJ5DxTS/cRCcalIQXmPFbaJSqpBusVG2EkWnm1v7VQrNPE2Os2b2P293vpbhwkyCEQiGRVva4Sw9D1sKvqSsK10QCRG+os6dFEOu1kARaXi6pStvR4OVmj7OYeAYjzaFchn7nz2CSae0M4IluiYQ01eQAywbfRo9DpKSmDM/DnPZWJnD/woLhaaaCrCxSSEaFsvGOHFhLd3Rknw1v0jADMILUtJoGOp4BpqKqyMz0CY3kpKL0jfR3ykTf/ge9wWVE0Alr7wRIkGCIURkhslGHqSyFRGoTqIXaxU+oPbwlw/0w/nYO7qQ6bTANOWye/wgw4h/NmJ6vU7wnZTXwREf1r6MF72++bE/fMk19LfVb8jN/qrUqAUXTc8gBAUxL5pgy8+oT/JnI2BkVrrLS4ilxEXP9Ahm+6GDUYXV4fBpqpZwdkzQ/5Gw=",
726727
"x-amz-content-sha256": "UNSIGNED-PAYLOAD",
728+
"X-Custom-Header": "value",
727729
}
728730

729731

0 commit comments

Comments
 (0)