'gzencode' ]; /** * Create a middleware wrapper function. * * @return callable */ public static function wrap(array $config) { return function (callable $handler) use ($config) { return new self($handler, $config); }; } public function __construct(callable $nextHandler, $config) { $this->minimumCompressionSize = $this->determineMinimumCompressionSize($config); $this->api = $config['api']; $this->nextHandler = $nextHandler; } public function __invoke(CommandInterface $command, RequestInterface $request) { if (isset($command['@request_min_compression_size_bytes']) && is_int($command['@request_min_compression_size_bytes']) && $this->isValidCompressionSize($command['@request_min_compression_size_bytes']) ) { $this->minimumCompressionSize = $command['@request_min_compression_size_bytes']; } $nextHandler = $this->nextHandler; $operation = $this->api->getOperation($command->getName()); $compressionInfo = isset($operation['requestcompression']) ? $operation['requestcompression'] : null; if (!$this->shouldCompressRequestBody( $compressionInfo, $command, $operation, $request )) { return $nextHandler($command, $request); } $this->encodings = $compressionInfo['encodings']; $request = $this->compressRequestBody($request); return $nextHandler($command, $request); } private function compressRequestBody( RequestInterface $request ) { $fn = $this->determineEncoding(); if (is_null($fn)) { return $request; } $body = $request->getBody()->getContents(); $compressedBody = $fn($body); return $request->withBody(Psr7\Utils::streamFor($compressedBody)) ->withHeader('content-encoding', $this->encoding); } private function determineEncoding() { foreach ($this->encodings as $encoding) { if (isset($this->encodingMap[$encoding])) { $this->encoding = $encoding; return $this->encodingMap[$encoding]; } } return null; } private function shouldCompressRequestBody( $compressionInfo, $command, $operation, $request ){ if ($compressionInfo) { if (isset($command['@disable_request_compression']) && $command['@disable_request_compression'] === true ) { return false; } elseif ($this->hasStreamingTraitWithoutRequiresLength($command, $operation) ) { return true; } $requestBodySize = $request->hasHeader('content-length') ? (int) $request->getHeaderLine('content-length') : $request->getBody()->getSize(); if ($requestBodySize >= $this->minimumCompressionSize) { return true; } } return false; } private function hasStreamingTraitWithoutRequiresLength($command, $operation) { foreach ($operation->getInput()->getMembers() as $name => $member) { if (isset($command[$name]) && !empty($member['streaming']) && empty($member['requiresLength']) ){ return true; } } return false; } private function determineMinimumCompressionSize($config) { if (is_callable($config['request_min_compression_size_bytes'])) { $minCompressionSz = $config['request_min_compression_size_bytes'](); } else { $minCompressionSz = $config['request_min_compression_size_bytes']; } if ($this->isValidCompressionSize($minCompressionSz)) { return $minCompressionSz; } } private function isValidCompressionSize($compressionSize) { if (is_numeric($compressionSize) && ($compressionSize >= 0 && $compressionSize <= 10485760) ) { return true; } throw new \InvalidArgumentException( 'The minimum request compression size must be a ' . 'non-negative integer value between 0 and 10485760 bytes, inclusive.' ); } }