Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
namespace Aws\S3;
3
 
4
use Aws\CommandInterface;
5
use Psr\Http\Message\RequestInterface;
6
 
7
/**
8
 * Used to update the host used for S3 requests in the case of using a
9
 * "bucket endpoint" or CNAME bucket.
10
 *
11
 * IMPORTANT: this middleware must be added after the "build" step.
12
 *
13
 * @internal
14
 */
15
class BucketEndpointMiddleware
16
{
17
    private static $exclusions = ['GetBucketLocation' => true];
18
    private $nextHandler;
19
 
20
    /**
21
     * Create a middleware wrapper function.
22
     *
23
     * @return callable
24
     */
25
    public static function wrap()
26
    {
27
        return function (callable $handler) {
28
            return new self($handler);
29
        };
30
    }
31
 
32
    public function __construct(callable $nextHandler)
33
    {
34
        $this->nextHandler = $nextHandler;
35
    }
36
 
37
    public function __invoke(CommandInterface $command, RequestInterface $request)
38
    {
39
        $nextHandler = $this->nextHandler;
40
        $bucket = $command['Bucket'];
41
 
42
        if ($bucket && !isset(self::$exclusions[$command->getName()])) {
43
            $request = $this->modifyRequest($request, $command);
44
        }
45
 
46
        return $nextHandler($command, $request);
47
    }
48
 
49
    /**
50
     * Performs a one-time removal of Bucket from path, then if
51
     * the bucket name is duplicated in the path, performs additional
52
     * removal which is dependent on the number of occurrences of the bucket
53
     * name in a path-like format in the key name.
54
     *
55
     * @return string
56
     */
57
    private function removeBucketFromPath($path, $bucket, $key)
58
    {
59
        $occurrencesInKey = $this->getBucketNameOccurrencesInKey($key, $bucket);
60
        do {
61
            $len = strlen($bucket) + 1;
62
            if (substr($path, 0, $len) === "/{$bucket}") {
63
                $path = substr($path, $len);
64
            }
65
        } while (substr_count($path, "/{$bucket}") > $occurrencesInKey + 1);
66
 
67
        return $path ?: '/';
68
    }
69
 
70
    private function removeDuplicateBucketFromHost($host, $bucket)
71
    {
72
        if (substr_count($host, $bucket) > 1) {
73
            while (strpos($host, "{$bucket}.{$bucket}") === 0) {
74
                $hostArr = explode('.', $host);
75
                array_shift($hostArr);
76
                $host = implode('.', $hostArr);
77
            }
78
        }
79
        return $host;
80
    }
81
 
82
    private function getBucketNameOccurrencesInKey($key, $bucket)
83
    {
84
        $occurrences = 0;
85
        if (empty($key)) {
86
            return $occurrences;
87
        }
88
 
89
        $segments = explode('/', $key);
90
        foreach($segments as $segment) {
91
            if (strpos($segment, $bucket) === 0) {
92
                $occurrences++;
93
            }
94
        }
95
        return $occurrences;
96
    }
97
 
98
    private function modifyRequest(
99
        RequestInterface $request,
100
        CommandInterface $command
101
    ) {
102
        $key = isset($command['Key']) ? $command['Key'] : null;
103
        $uri = $request->getUri();
104
        $path = $uri->getPath();
105
        $host = $uri->getHost();
106
        $bucket = $command['Bucket'];
107
        $path = $this->removeBucketFromPath($path, $bucket, $key);
108
        $host = $this->removeDuplicateBucketFromHost($host, $bucket);
109
 
110
        // Modify the Key to make sure the key is encoded, but slashes are not.
111
        if ($key) {
112
            $path = S3Client::encodeKey(rawurldecode($path));
113
        }
114
 
115
        return $request->withUri(
116
            $uri->withHost($host)
117
                ->withPath($path)
118
        );
119
    }
120
}