Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
namespace Aws;
3
 
4
use GuzzleHttp\Psr7;
5
use Psr\Http\Message\RequestInterface;
6
 
7
/**
8
 * Used to compress request payloads if the service/operation support it.
9
 *
10
 * IMPORTANT: this middleware must be added after the "build" step.
11
 *
12
 * @internal
13
 */
14
class RequestCompressionMiddleware
15
{
16
    private $api;
17
    private $minimumCompressionSize;
18
    private $nextHandler;
19
    private $encodings;
20
    private $encoding;
21
    private $encodingMap = [
22
        'gzip' => 'gzencode'
23
    ];
24
 
25
    /**
26
     * Create a middleware wrapper function.
27
     *
28
     * @return callable
29
     */
30
    public static function wrap(array $config)
31
    {
32
        return function (callable $handler) use ($config) {
33
            return new self($handler, $config);
34
        };
35
    }
36
 
37
    public function __construct(callable $nextHandler, $config)
38
    {
39
        $this->minimumCompressionSize = $this->determineMinimumCompressionSize($config);
40
        $this->api = $config['api'];
41
        $this->nextHandler = $nextHandler;
42
    }
43
 
44
    public function __invoke(CommandInterface $command, RequestInterface $request)
45
    {
46
        if (isset($command['@request_min_compression_size_bytes'])
47
            && is_int($command['@request_min_compression_size_bytes'])
48
            && $this->isValidCompressionSize($command['@request_min_compression_size_bytes'])
49
        ) {
50
            $this->minimumCompressionSize = $command['@request_min_compression_size_bytes'];
51
        }
52
        $nextHandler = $this->nextHandler;
53
        $operation = $this->api->getOperation($command->getName());
54
        $compressionInfo = isset($operation['requestcompression'])
55
            ? $operation['requestcompression']
56
            : null;
57
 
58
        if (!$this->shouldCompressRequestBody(
59
            $compressionInfo,
60
            $command,
61
            $operation,
1441 ariadna 62
            $request
1 efrain 63
        )) {
64
            return $nextHandler($command, $request);
65
        }
66
 
67
        $this->encodings = $compressionInfo['encodings'];
68
        $request = $this->compressRequestBody($request);
69
 
1441 ariadna 70
        // Capture request compression metric
71
        $command->getMetricsBuilder()->identifyMetricByValueAndAppend(
72
            'request_compression',
73
            $request->getHeaderLine('content-encoding')
74
        );
75
 
1 efrain 76
        return $nextHandler($command, $request);
77
    }
78
 
79
    private function compressRequestBody(
80
        RequestInterface $request
81
    ) {
82
        $fn = $this->determineEncoding();
83
        if (is_null($fn)) {
84
            return $request;
85
        }
86
 
87
        $body = $request->getBody()->getContents();
88
        $compressedBody = $fn($body);
89
 
90
        return $request->withBody(Psr7\Utils::streamFor($compressedBody))
91
            ->withHeader('content-encoding', $this->encoding);
92
    }
93
 
94
    private function determineEncoding()
95
    {
96
        foreach ($this->encodings as $encoding) {
97
            if (isset($this->encodingMap[$encoding])) {
98
                $this->encoding = $encoding;
99
                return $this->encodingMap[$encoding];
100
            }
101
        }
102
        return null;
103
    }
104
 
105
    private function shouldCompressRequestBody(
106
        $compressionInfo,
107
        $command,
108
        $operation,
1441 ariadna 109
        $request
1 efrain 110
    ){
111
        if ($compressionInfo) {
112
            if (isset($command['@disable_request_compression'])
113
                && $command['@disable_request_compression'] === true
114
            ) {
115
                return false;
116
            } elseif ($this->hasStreamingTraitWithoutRequiresLength($command, $operation)
117
            ) {
118
                return true;
119
            }
1441 ariadna 120
 
121
            $requestBodySize = $request->hasHeader('content-length')
122
                ? (int) $request->getHeaderLine('content-length')
123
                : $request->getBody()->getSize();
124
 
125
            if ($requestBodySize >= $this->minimumCompressionSize) {
126
                return true;
127
            }
1 efrain 128
        }
129
        return false;
130
    }
131
 
132
    private function hasStreamingTraitWithoutRequiresLength($command, $operation)
133
    {
134
        foreach ($operation->getInput()->getMembers() as $name => $member) {
135
            if (isset($command[$name])
136
                && !empty($member['streaming'])
137
                && empty($member['requiresLength'])
138
            ){
139
                return true;
140
            }
141
        }
142
        return false;
143
    }
144
 
145
    private function determineMinimumCompressionSize($config) {
146
        if (is_callable($config['request_min_compression_size_bytes'])) {
147
            $minCompressionSz = $config['request_min_compression_size_bytes']();
148
        } else {
149
            $minCompressionSz = $config['request_min_compression_size_bytes'];
150
        }
151
 
152
        if ($this->isValidCompressionSize($minCompressionSz)) {
153
            return $minCompressionSz;
154
        }
155
    }
156
 
157
    private function isValidCompressionSize($compressionSize)
158
    {
159
        if (is_numeric($compressionSize)
160
            && ($compressionSize >= 0 && $compressionSize <= 10485760)
161
        ) {
162
            return true;
163
        }
164
 
165
        throw new \InvalidArgumentException(
166
            'The minimum request compression size must be a '
167
            . 'non-negative integer value between 0 and 10485760 bytes, inclusive.'
168
        );
169
    }
1441 ariadna 170
}