최초 커밋
This commit is contained in:
@@ -0,0 +1,338 @@
|
||||
<?php
|
||||
|
||||
namespace Aws;
|
||||
|
||||
use Aws\EndpointDiscovery\Configuration;
|
||||
use Closure;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Builds and injects the user agent header values.
|
||||
* This middleware must be appended into step where all the
|
||||
* metrics to be gathered are already resolved. As of now it should be
|
||||
* after the signing step.
|
||||
*/
|
||||
class UserAgentMiddleware
|
||||
{
|
||||
const AGENT_VERSION = 2.1;
|
||||
|
||||
static $userAgentFnList = [
|
||||
'getSdkVersion',
|
||||
'getUserAgentVersion',
|
||||
'getHhvmVersion',
|
||||
'getOsName',
|
||||
'getLangVersion',
|
||||
'getExecEnv',
|
||||
'getEndpointDiscovery',
|
||||
'getAppId',
|
||||
'getMetrics'
|
||||
];
|
||||
|
||||
static $metricsFnList = [
|
||||
'appendEndpointMetric',
|
||||
'appendAccountIdModeMetric',
|
||||
'appendRetryConfigMetric',
|
||||
];
|
||||
|
||||
/** @var callable */
|
||||
private $nextHandler;
|
||||
|
||||
/** @var array */
|
||||
private $args;
|
||||
|
||||
/** @var MetricsBuilder */
|
||||
private $metricsBuilder;
|
||||
|
||||
/**
|
||||
* Returns a middleware wrapper function.
|
||||
*
|
||||
* @param array $args
|
||||
*
|
||||
* @return Closure
|
||||
*/
|
||||
public static function wrap(
|
||||
array $args
|
||||
) : Closure
|
||||
{
|
||||
return function (callable $handler) use ($args) {
|
||||
return new self($handler, $args);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable $nextHandler
|
||||
* @param array $args
|
||||
*/
|
||||
public function __construct(callable $nextHandler, array $args=[])
|
||||
{
|
||||
$this->nextHandler = $nextHandler;
|
||||
$this->args = $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* When invoked, its injects the user agent header into the
|
||||
* request headers.
|
||||
*
|
||||
* @param CommandInterface $command
|
||||
* @param RequestInterface $request
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __invoke(CommandInterface $command, RequestInterface $request)
|
||||
{
|
||||
$handler = $this->nextHandler;
|
||||
$this->metricsBuilder = MetricsBuilder::fromCommand($command);
|
||||
$request = $this->requestWithUserAgentHeader($request);
|
||||
|
||||
return $handler($command, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the user agent header value, and injects it into the request
|
||||
* headers. Then, it returns the mutated request.
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
*
|
||||
* @return RequestInterface
|
||||
*/
|
||||
private function requestWithUserAgentHeader(RequestInterface $request): RequestInterface
|
||||
{
|
||||
$uaAppend = $this->args['ua_append'] ?? [];
|
||||
$userAgentValue = array_merge(
|
||||
$this->buildUserAgentValue(),
|
||||
$uaAppend
|
||||
);
|
||||
// It includes the user agent values just for the User-Agent header.
|
||||
// The reason is that the SEP does not mention appending the
|
||||
// metrics into the X-Amz-User-Agent header.
|
||||
return $request->withHeader(
|
||||
'User-Agent',
|
||||
implode(' ', array_merge(
|
||||
$userAgentValue,
|
||||
$request->getHeader('User-Agent')
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the different user agent values.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function buildUserAgentValue(): array
|
||||
{
|
||||
$userAgentValue = [];
|
||||
foreach (self::$userAgentFnList as $fn) {
|
||||
$val = $this->{$fn}();
|
||||
if (!empty($val)) {
|
||||
$userAgentValue[] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
return $userAgentValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user agent value for SDK version.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getSdkVersion(): string
|
||||
{
|
||||
return 'aws-sdk-php/' . Sdk::VERSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user agent value for the agent version.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getUserAgentVersion(): string
|
||||
{
|
||||
return 'ua/' . self::AGENT_VERSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user agent value for the hhvm version, but just
|
||||
* when it is defined.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getHhvmVersion(): string
|
||||
{
|
||||
if (defined('HHVM_VERSION')) {
|
||||
return 'HHVM/' . HHVM_VERSION;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user agent value for the os version.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getOsName(): string
|
||||
{
|
||||
$disabledFunctions = explode(',', ini_get('disable_functions'));
|
||||
if (function_exists('php_uname')
|
||||
&& !in_array('php_uname', $disabledFunctions, true)
|
||||
) {
|
||||
$osName = "OS/" . php_uname('s') . '#' . php_uname('r');
|
||||
if (!empty($osName)) {
|
||||
return $osName;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user agent value for the php language used.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getLangVersion(): string
|
||||
{
|
||||
return 'lang/php#' . phpversion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user agent value for the execution env.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getExecEnv(): string
|
||||
{
|
||||
if ($executionEnvironment = getenv('AWS_EXECUTION_ENV')) {
|
||||
return $executionEnvironment;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user agent value for endpoint discovery as cfg.
|
||||
* This feature is deprecated.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getEndpointDiscovery(): string
|
||||
{
|
||||
$args = $this->args;
|
||||
if (isset($args['endpoint_discovery'])) {
|
||||
if (($args['endpoint_discovery'] instanceof Configuration
|
||||
&& $args['endpoint_discovery']->isEnabled())
|
||||
) {
|
||||
return 'cfg/endpoint-discovery';
|
||||
} elseif (is_array($args['endpoint_discovery'])
|
||||
&& isset($args['endpoint_discovery']['enabled'])
|
||||
&& $args['endpoint_discovery']['enabled']
|
||||
) {
|
||||
return 'cfg/endpoint-discovery';
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user agent value for app id, but just when an
|
||||
* app id was provided as a client argument.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getAppId(): string
|
||||
{
|
||||
if (empty($this->args['app_id'])) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return 'app/' . $this->args['app_id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user agent value for metrics.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getMetrics(): string
|
||||
{
|
||||
foreach (self::$metricsFnList as $fn) {
|
||||
$this->{$fn}();
|
||||
}
|
||||
|
||||
$metricsEncoded = $this->metricsBuilder->build();
|
||||
if (empty($metricsEncoded)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return "m/" . $metricsEncoded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the endpoint metric into the metrics builder,
|
||||
* just if a custom endpoint was provided at client construction.
|
||||
*/
|
||||
private function appendEndpointMetric(): void
|
||||
{
|
||||
if (!empty($this->args['endpoint_override'])) {
|
||||
$this->metricsBuilder->append(MetricsBuilder::ENDPOINT_OVERRIDE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the account id endpoint mode metric into the metrics builder,
|
||||
* based on the account id endpoint mode provide as client argument.
|
||||
*/
|
||||
private function appendAccountIdModeMetric(): void
|
||||
{
|
||||
$accountIdMode = $this->args['account_id_endpoint_mode'] ?? null;
|
||||
if ($accountIdMode === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($accountIdMode === 'preferred') {
|
||||
$this->metricsBuilder->append(MetricsBuilder::ACCOUNT_ID_MODE_PREFERRED);
|
||||
} elseif ($accountIdMode === 'disabled') {
|
||||
$this->metricsBuilder->append(MetricsBuilder::ACCOUNT_ID_MODE_DISABLED);
|
||||
} elseif ($accountIdMode === 'required') {
|
||||
$this->metricsBuilder->append(MetricsBuilder::ACCOUNT_ID_MODE_REQUIRED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the retry mode metric into the metrics builder,
|
||||
* based on the resolved retry config mode.
|
||||
*/
|
||||
private function appendRetryConfigMetric(): void
|
||||
{
|
||||
$retries = $this->args['retries'] ?? null;
|
||||
if ($retries === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$retryMode = '';
|
||||
if ($retries instanceof \Aws\Retry\Configuration) {
|
||||
$retryMode = $retries->getMode();
|
||||
} elseif (is_array($retries)
|
||||
&& isset($retries["mode"])
|
||||
) {
|
||||
$retryMode = $retries["mode"];
|
||||
}
|
||||
|
||||
if ($retryMode === 'legacy') {
|
||||
$this->metricsBuilder->append(
|
||||
MetricsBuilder::RETRY_MODE_LEGACY
|
||||
);
|
||||
} elseif ($retryMode === 'standard') {
|
||||
$this->metricsBuilder->append(
|
||||
MetricsBuilder::RETRY_MODE_STANDARD
|
||||
);
|
||||
} elseif ($retryMode === 'adaptive') {
|
||||
$this->metricsBuilder->append(
|
||||
MetricsBuilder::RETRY_MODE_ADAPTIVE
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user