Skip to content

Commit

Permalink
feature: add support for per-service endpoint url configuration (#2737)
Browse files Browse the repository at this point in the history
  • Loading branch information
stobrien89 authored Sep 1, 2023
1 parent d68b83b commit 1cf7f36
Show file tree
Hide file tree
Showing 9 changed files with 501 additions and 12 deletions.
7 changes: 7 additions & 0 deletions .changes/nextrelease/endpoint-url.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"type": "feature",
"category": "",
"description": "Adds support for service-specific endpoint url configuration."
}
]
62 changes: 62 additions & 0 deletions src/ClientResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,19 @@ class ClientResolver
'doc' => 'Set to true to disable host prefix injection logic for services that use it. This disables the entire prefix injection, including the portions supplied by user-defined parameters. Setting this flag will have no effect on services that do not use host prefix injection.',
'default' => false,
],
'ignore_configured_endpoint_urls' => [
'type' => 'value',
'valid' => ['bool'],
'doc' => 'Set to true to disable endpoint urls configured using `AWS_ENDPOINT_URL` and `endpoint_url` shared config option.',
'fn' => [__CLASS__, '_apply_ignore_configured_endpoint_urls'],
'default' => [__CLASS__, '_default_ignore_configured_endpoint_urls'],
],
'endpoint' => [
'type' => 'value',
'valid' => ['string'],
'doc' => 'The full URI of the webservice. This is only required when connecting to a custom endpoint (e.g., a local version of S3).',
'fn' => [__CLASS__, '_apply_endpoint'],
'default' => [__CLASS__, '_default_endpoint']
],
'region' => [
'type' => 'value',
Expand Down Expand Up @@ -993,6 +1001,11 @@ public static function _apply_user_agent($inputUserAgent, array &$args, HandlerL

public static function _apply_endpoint($value, array &$args, HandlerList $list)
{
if (empty($value)) {
unset($args['endpoint']);
return;
}

$args['endpoint'] = $value;
}

Expand Down Expand Up @@ -1116,6 +1129,55 @@ public static function _default_signing_region(array &$args)
: $args['region'];
}

public static function _apply_ignore_configured_endpoint_urls($value, array &$args)
{
$args['config']['ignore_configured_endpoint_urls'] = $value;
}

public static function _default_ignore_configured_endpoint_urls(array &$args)
{
return ConfigurationResolver::resolve(
'ignore_configured_endpoint_urls',
false,
'bool',
$args
);
}

public static function _default_endpoint(array &$args)
{
if ($args['config']['ignore_configured_endpoint_urls']
|| !self::isValidService($args['service'])
) {
return '';
}

$serviceIdentifier = \Aws\manifest($args['service'])['serviceIdentifier'];
$value = ConfigurationResolver::resolve(
'endpoint_url_' . $serviceIdentifier,
'',
'string',
$args + [
'ini_resolver_options' => [
'section' => 'services',
'subsection' => $serviceIdentifier,
'key' => 'endpoint_url'
]
]
);

if (empty($value)) {
$value = ConfigurationResolver::resolve(
'endpoint_url',
'',
'string',
$args
);
}

return $value;
}

public static function _apply_region($value, array &$args)
{
if (empty($value)) {
Expand Down
2 changes: 2 additions & 0 deletions src/CloudSearchDomain/CloudSearchDomainClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use Aws\AwsClient;
use Aws\CommandInterface;
use Aws\HandlerList;
use GuzzleHttp\Psr7\Uri;
use Psr\Http\Message\RequestInterface;
use GuzzleHttp\Psr7;
Expand Down Expand Up @@ -35,6 +36,7 @@ public static function getArguments()
// (e.g. http://search-blah.{region}.cloudsearch.amazonaws.com)
return explode('.', new Uri($args['endpoint']))[1];
};
unset($args['endpoint']['default']);

return $args;
}
Expand Down
82 changes: 76 additions & 6 deletions src/Configuration/ConfigurationResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ class ConfigurationResolver
* to retrieve value from the environment or ini file.
* @param mixed $defaultValue
* @param string $expectedType The expected type of the retrieved value.
* @param array $config
* @param array $additionalArgs
* @param array $config additional configuration options.
*
* @return mixed
*/
Expand All @@ -33,6 +32,10 @@ public static function resolve(
$config = []
)
{
$iniOptions = isset($config['ini_resolver_options'])
? $config['ini_resolver_options']
: [];

$envValue = self::env($key, $expectedType);
if (!is_null($envValue)) {
return $envValue;
Expand All @@ -41,7 +44,13 @@ public static function resolve(
if (!isset($config['use_aws_shared_config_files'])
|| $config['use_aws_shared_config_files'] != false
) {
$iniValue = self::ini($key, $expectedType);
$iniValue = self::ini(
$key,
$expectedType,
null,
null,
$iniOptions
);
if(!is_null($iniValue)) {
return $iniValue;
}
Expand Down Expand Up @@ -89,8 +98,13 @@ public static function env($key, $expectedType)
*
* @return null | mixed
*/
public static function ini($key, $expectedType, $profile = null, $filename = null)
{
public static function ini(
$key,
$expectedType,
$profile = null,
$filename = null,
$options = []
){
$filename = $filename ?: (self::getDefaultConfigFilename());
$profile = $profile ?: (getenv(self::ENV_PROFILE) ?: 'default');

Expand All @@ -100,6 +114,20 @@ public static function ini($key, $expectedType, $profile = null, $filename = nul
// Use INI_SCANNER_NORMAL instead of INI_SCANNER_TYPED for PHP 5.5 compatibility
//TODO change after deprecation
$data = @\Aws\parse_ini_file($filename, true, INI_SCANNER_NORMAL);

if (isset($options['section'])
&& isset($options['subsection'])
&& isset($options['key']))
{
return self::retrieveValueFromIniSubsection(
$data,
$profile,
$filename,
$expectedType,
$options
);
}

if ($data === false
|| !isset($data[$profile])
|| !isset($data[$profile][$key])
Expand Down Expand Up @@ -177,4 +205,46 @@ private static function convertType($value, $type)
}
return $value;
}
}

/**
* Normalizes string values pulled out of ini files and
* environment variables.
*
* @param array $data The data retrieved the ini file
* @param string $profile The specified ini profile
* @param string $filename The full path to the ini file
* @param array $options Additional arguments passed to the configuration resolver
*
* @return mixed
*/
private static function retrieveValueFromIniSubsection(
$data,
$profile,
$filename,
$expectedType,
$options
){
$section = $options['section'];
if ($data === false
|| !isset($data[$profile][$section])
|| !isset($data["{$section} {$data[$profile][$section]}"])
) {
return null;
}

$services_section = \Aws\parse_ini_section_with_subsections(
$filename,
"services {$data[$profile]['services']}"
);

if (!isset($services_section[$options['subsection']][$options['key']])
) {
return null;
}

return self::convertType(
$services_section[$options['subsection']][$options['key']],
$expectedType
);
}
}
61 changes: 61 additions & 0 deletions src/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,67 @@ function boolean_value($input)
return null;
}

/**
* Parses ini sections with subsections (i.e. the service section)
*
* @param $filename
* @param $filename
* @return array
*/
function parse_ini_section_with_subsections($filename, $section_name) {
$config = [];
$stream = fopen($filename, 'r');

if (!$stream) {
return $config;
}

$current_subsection = '';

while (!feof($stream)) {
$line = trim(fgets($stream));

if (empty($line) || in_array($line[0], [';', '#'])) {
continue;
}

if (preg_match('/^\[.*\]$/', $line)
&& trim($line, '[]') === $section_name)
{
while (!feof($stream)) {
$line = trim(fgets($stream));

if (empty($line) || in_array($line[0], [';', '#'])) {
continue;
}

if (preg_match('/^\[.*\]$/', $line)
&& trim($line, '[]') === $section_name)
{
continue;
} elseif (strpos($line, '[') === 0) {
break;
}

if (strpos($line, ' = ') !== false) {
list($key, $value) = explode(' = ', $line, 2);
if (empty($current_subsection)) {
$config[$key] = $value;
} else {
$config[$current_subsection][$key] = $value;
}
} else {
$current_subsection = trim(str_replace('=', '', $line));
$config[$current_subsection] = [];
}
}
}
}

fclose($stream);
return $config;
}

/**
* Checks if an input is a valid epoch time
*
Expand Down
3 changes: 2 additions & 1 deletion tests/AwsClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,8 @@ public function testVerifyGetConfig()
'use_fips_endpoint' => new FipsConfiguration(false),
'use_dual_stack_endpoint' => new DualStackConfiguration(false, "foo"),
'disable_request_compression' => false,
'request_min_compression_size_bytes' => 10240
'request_min_compression_size_bytes' => 10240,
'ignore_configured_endpoint_urls' => false
],
$client->getConfig()
);
Expand Down
Loading

0 comments on commit 1cf7f36

Please sign in to comment.