@@ -1108,91 +1108,103 @@ class EndpointProviderCache {
1108
1108
1109
1109
class ClientBuilder {
1110
1110
public:
1111
- explicit ClientBuilder (S3Options options) : options_(std::move(options)) {}
1111
+ explicit ClientBuilder (S3Options options) : options_(std::move(options)) {
1112
+ // The ClientConfiguration constructor always does a current region lookup
1113
+ // via EC2 metadata, unless IMDS is disabled (GH-46214).
1114
+ client_config_.emplace (/* useSmartDefaults=*/ true , options_.smart_defaults ,
1115
+ /* shouldDisableIMDS=*/ true );
1116
+ }
1112
1117
1113
- const Aws::Client::ClientConfiguration& config () const { return client_config_; }
1118
+ const Aws::Client::ClientConfiguration& config () const {
1119
+ DCHECK (client_config_.has_value ());
1120
+ return *client_config_;
1121
+ }
1114
1122
1115
- Aws::Client::ClientConfiguration* mutable_config () { return &client_config_; }
1123
+ Aws::Client::ClientConfiguration* mutable_config () {
1124
+ DCHECK (client_config_.has_value ());
1125
+ return &*client_config_;
1126
+ }
1116
1127
1117
1128
Result<std::shared_ptr<S3ClientHolder>> BuildClient (
1118
1129
std::optional<io::IOContext> io_context = std::nullopt) {
1119
1130
credentials_provider_ = options_.credentials_provider ;
1120
1131
if (!options_.region .empty ()) {
1121
- client_config_. region = ToAwsString (options_.region );
1132
+ client_config_-> region = ToAwsString (options_.region );
1122
1133
}
1123
1134
if (options_.request_timeout > 0 ) {
1124
1135
// Use ceil() to avoid setting it to 0 as that probably means no timeout.
1125
- client_config_. requestTimeoutMs =
1136
+ client_config_-> requestTimeoutMs =
1126
1137
static_cast <long >(ceil (options_.request_timeout * 1000 )); // NOLINT runtime/int
1127
1138
}
1128
1139
if (options_.connect_timeout > 0 ) {
1129
- client_config_. connectTimeoutMs =
1140
+ client_config_-> connectTimeoutMs =
1130
1141
static_cast <long >(ceil (options_.connect_timeout * 1000 )); // NOLINT runtime/int
1131
1142
}
1132
1143
1133
- client_config_. endpointOverride = ToAwsString (options_.endpoint_override );
1144
+ client_config_-> endpointOverride = ToAwsString (options_.endpoint_override );
1134
1145
if (options_.scheme == " http" ) {
1135
- client_config_. scheme = Aws::Http::Scheme::HTTP;
1146
+ client_config_-> scheme = Aws::Http::Scheme::HTTP;
1136
1147
} else if (options_.scheme == " https" ) {
1137
- client_config_. scheme = Aws::Http::Scheme::HTTPS;
1148
+ client_config_-> scheme = Aws::Http::Scheme::HTTPS;
1138
1149
} else {
1139
1150
return Status::Invalid (" Invalid S3 connection scheme '" , options_.scheme , " '" );
1140
1151
}
1141
1152
if (options_.retry_strategy ) {
1142
- client_config_. retryStrategy =
1153
+ client_config_-> retryStrategy =
1143
1154
std::make_shared<WrappedRetryStrategy>(options_.retry_strategy );
1144
1155
} else {
1145
- client_config_. retryStrategy = std::make_shared<ConnectRetryStrategy>();
1156
+ client_config_-> retryStrategy = std::make_shared<ConnectRetryStrategy>();
1146
1157
}
1147
1158
if (!options_.tls_ca_file_path .empty ()) {
1148
- client_config_. caFile = ToAwsString (options_.tls_ca_file_path );
1159
+ client_config_-> caFile = ToAwsString (options_.tls_ca_file_path );
1149
1160
} else if (!internal::global_options.tls_ca_file_path .empty ()) {
1150
- client_config_. caFile = ToAwsString (internal::global_options.tls_ca_file_path );
1161
+ client_config_-> caFile = ToAwsString (internal::global_options.tls_ca_file_path );
1151
1162
}
1152
1163
if (!options_.tls_ca_dir_path .empty ()) {
1153
- client_config_. caPath = ToAwsString (options_.tls_ca_dir_path );
1164
+ client_config_-> caPath = ToAwsString (options_.tls_ca_dir_path );
1154
1165
} else if (!internal::global_options.tls_ca_dir_path .empty ()) {
1155
- client_config_. caPath = ToAwsString (internal::global_options.tls_ca_dir_path );
1166
+ client_config_-> caPath = ToAwsString (internal::global_options.tls_ca_dir_path );
1156
1167
}
1157
- client_config_. verifySSL = options_.tls_verify_certificates ;
1168
+ client_config_-> verifySSL = options_.tls_verify_certificates ;
1158
1169
1159
1170
// Set proxy options if provided
1160
1171
if (!options_.proxy_options .scheme .empty ()) {
1161
1172
if (options_.proxy_options .scheme == " http" ) {
1162
- client_config_. proxyScheme = Aws::Http::Scheme::HTTP;
1173
+ client_config_-> proxyScheme = Aws::Http::Scheme::HTTP;
1163
1174
} else if (options_.proxy_options .scheme == " https" ) {
1164
- client_config_. proxyScheme = Aws::Http::Scheme::HTTPS;
1175
+ client_config_-> proxyScheme = Aws::Http::Scheme::HTTPS;
1165
1176
} else {
1166
1177
return Status::Invalid (" Invalid proxy connection scheme '" ,
1167
1178
options_.proxy_options .scheme , " '" );
1168
1179
}
1169
1180
}
1170
1181
if (!options_.proxy_options .host .empty ()) {
1171
- client_config_. proxyHost = ToAwsString (options_.proxy_options .host );
1182
+ client_config_-> proxyHost = ToAwsString (options_.proxy_options .host );
1172
1183
}
1173
1184
if (options_.proxy_options .port != -1 ) {
1174
- client_config_. proxyPort = options_.proxy_options .port ;
1185
+ client_config_-> proxyPort = options_.proxy_options .port ;
1175
1186
}
1176
1187
if (!options_.proxy_options .username .empty ()) {
1177
- client_config_. proxyUserName = ToAwsString (options_.proxy_options .username );
1188
+ client_config_-> proxyUserName = ToAwsString (options_.proxy_options .username );
1178
1189
}
1179
1190
if (!options_.proxy_options .password .empty ()) {
1180
- client_config_. proxyPassword = ToAwsString (options_.proxy_options .password );
1191
+ client_config_-> proxyPassword = ToAwsString (options_.proxy_options .password );
1181
1192
}
1182
1193
1183
1194
if (io_context) {
1184
1195
// TODO: Once ARROW-15035 is done we can get rid of the "at least 25" fallback
1185
- client_config_.maxConnections = std::max (io_context->executor ()->GetCapacity (), 25 );
1196
+ client_config_->maxConnections =
1197
+ std::max (io_context->executor ()->GetCapacity (), 25 );
1186
1198
}
1187
1199
1188
1200
const bool use_virtual_addressing =
1189
1201
options_.endpoint_override .empty () || options_.force_virtual_addressing ;
1190
1202
1191
1203
#ifdef ARROW_S3_HAS_S3CLIENT_CONFIGURATION
1192
- client_config_. useVirtualAddressing = use_virtual_addressing;
1193
- auto endpoint_provider = EndpointProviderCache::Instance ()->Lookup (client_config_);
1204
+ client_config_-> useVirtualAddressing = use_virtual_addressing;
1205
+ auto endpoint_provider = EndpointProviderCache::Instance ()->Lookup (* client_config_);
1194
1206
auto client = std::make_shared<S3Client>(credentials_provider_, endpoint_provider,
1195
- client_config_);
1207
+ * client_config_);
1196
1208
#else
1197
1209
auto client = std::make_shared<S3Client>(
1198
1210
credentials_provider_, client_config_,
@@ -1207,10 +1219,12 @@ class ClientBuilder {
1207
1219
1208
1220
protected:
1209
1221
S3Options options_;
1222
+ // GH-46214: the ClientConfiguration default constructor may issue arbitrary metadata
1223
+ // calls, defer construction until necessary.
1210
1224
#ifdef ARROW_S3_HAS_S3CLIENT_CONFIGURATION
1211
- Aws::S3::S3ClientConfiguration client_config_;
1225
+ std::optional< Aws::S3::S3ClientConfiguration> client_config_;
1212
1226
#else
1213
- Aws::Client::ClientConfiguration client_config_;
1227
+ std::optional< Aws::Client::ClientConfiguration> client_config_;
1214
1228
#endif
1215
1229
std::shared_ptr<Aws::Auth::AWSCredentialsProvider> credentials_provider_;
1216
1230
};
0 commit comments