@@ -62,7 +62,12 @@ static HTTPHeaders create_s3_header(string url, string query, string host, strin
62
62
res[" x-amz-server-side-encryption-aws-kms-key-id" ] = auth_params.kms_key_id ;
63
63
}
64
64
65
- string signed_headers = " " ;
65
+ bool use_requester_pays = auth_params.requester_pays ;
66
+ if (use_requester_pays) {
67
+ res[" x-amz-request-payer" ] = " requester" ;
68
+ }
69
+
70
+ string signed_headers = " " ;
66
71
hash_bytes canonical_request_hash;
67
72
hash_str canonical_request_hash_str;
68
73
if (content_type.length () > 0 ) {
@@ -75,7 +80,10 @@ static HTTPHeaders create_s3_header(string url, string query, string host, strin
75
80
if (use_sse_kms) {
76
81
signed_headers += " ;x-amz-server-side-encryption;x-amz-server-side-encryption-aws-kms-key-id" ;
77
82
}
78
- auto canonical_request = method + " \n " + S3FileSystem::UrlEncode (url) + " \n " + query;
83
+ if (use_requester_pays) {
84
+ signed_headers += " ;x-amz-request-payer" ;
85
+ }
86
+ auto canonical_request = method + " \n " + S3FileSystem::UrlEncode (url) + " \n " + query;
79
87
if (content_type.length () > 0 ) {
80
88
canonical_request += " \n content-type:" + content_type;
81
89
}
@@ -87,6 +95,9 @@ static HTTPHeaders create_s3_header(string url, string query, string host, strin
87
95
canonical_request += " \n x-amz-server-side-encryption:aws:kms" ;
88
96
canonical_request += " \n x-amz-server-side-encryption-aws-kms-key-id:" + auth_params.kms_key_id ;
89
97
}
98
+ if (use_requester_pays) {
99
+ canonical_request += " \n x-amz-request-payer:requester" ;
100
+ }
90
101
91
102
canonical_request += " \n\n " + signed_headers + " \n " + payload_hash;
92
103
sha256 (canonical_request.c_str (), canonical_request.length (), canonical_request_hash);
@@ -143,6 +154,7 @@ void AWSEnvironmentCredentialsProvider::SetAll() {
143
154
this ->SetExtensionOptionValue (" s3_endpoint" , DUCKDB_ENDPOINT_ENV_VAR);
144
155
this ->SetExtensionOptionValue (" s3_use_ssl" , DUCKDB_USE_SSL_ENV_VAR);
145
156
this ->SetExtensionOptionValue (" s3_kms_key_id" , DUCKDB_KMS_KEY_ID_ENV_VAR);
157
+ this ->SetExtensionOptionValue (" s3_requester_pays" , DUCKDB_REQUESTER_PAYS_ENV_VAR);
146
158
}
147
159
148
160
S3AuthParams AWSEnvironmentCredentialsProvider::CreateParams () {
@@ -156,6 +168,7 @@ S3AuthParams AWSEnvironmentCredentialsProvider::CreateParams() {
156
168
params.endpoint = DUCKDB_ENDPOINT_ENV_VAR;
157
169
params.kms_key_id = DUCKDB_KMS_KEY_ID_ENV_VAR;
158
170
params.use_ssl = DUCKDB_USE_SSL_ENV_VAR;
171
+ params.requester_pays = DUCKDB_REQUESTER_PAYS_ENV_VAR;
159
172
160
173
return params;
161
174
}
@@ -181,6 +194,8 @@ S3AuthParams S3AuthParams::ReadFrom(optional_ptr<FileOpener> opener, FileOpenerI
181
194
secret_reader.TryGetSecretKeyOrSetting (" kms_key_id" , " s3_kms_key_id" , result.kms_key_id );
182
195
secret_reader.TryGetSecretKeyOrSetting (" s3_url_compatibility_mode" , " s3_url_compatibility_mode" ,
183
196
result.s3_url_compatibility_mode );
197
+ secret_reader.TryGetSecretKeyOrSetting (" requester_pays" , " s3_requester_pays" ,
198
+ result.requester_pays );
184
199
185
200
// Endpoint and url style are slightly more complex and require special handling for gcs and r2
186
201
auto endpoint_result = secret_reader.TryGetSecretKeyOrSetting (" endpoint" , " s3_endpoint" , result.endpoint );
@@ -219,6 +234,7 @@ unique_ptr<KeyValueSecret> CreateSecret(vector<string> &prefix_paths_p, string &
219
234
return_value->secret_map [" use_ssl" ] = params.use_ssl ;
220
235
return_value->secret_map [" kms_key_id" ] = params.kms_key_id ;
221
236
return_value->secret_map [" s3_url_compatibility_mode" ] = params.s3_url_compatibility_mode ;
237
+ return_value->secret_map [" requester_pays" ] = params.requester_pays ;
222
238
223
239
// ! Set redact keys
224
240
return_value->redact_keys = {" secret" , " session_token" };
@@ -531,9 +547,21 @@ void S3FileSystem::ReadQueryParams(const string &url_query_param, S3AuthParams &
531
547
}
532
548
query_params.erase (found_param);
533
549
}
550
+ auto found_requester_pays_param = query_params.find (" s3_requester_pays" );
551
+ if (found_requester_pays_param != query_params.end ()) {
552
+ if (found_requester_pays_param->second == " true" ) {
553
+ params.requester_pays = true ;
554
+ } else if (found_requester_pays_param->second == " false" ) {
555
+ params.requester_pays = false ;
556
+ } else {
557
+ throw IOException (" Incorrect setting found for s3_requester_pays, allowed values are: 'true' or 'false'" );
558
+ }
559
+ query_params.erase (found_requester_pays_param);
560
+ }
534
561
if (!query_params.empty ()) {
535
562
throw IOException (" Invalid query parameters found. Supported parameters are:\n 's3_region', 's3_access_key_id', "
536
- " 's3_secret_access_key', 's3_session_token',\n 's3_endpoint', 's3_url_style', 's3_use_ssl'" );
563
+ " 's3_secret_access_key', 's3_session_token',\n 's3_endpoint', 's3_url_style', 's3_use_ssl', "
564
+ " 's3_requester_pays'" );
537
565
}
538
566
}
539
567
0 commit comments