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
 
3
namespace Kevinrob\GuzzleCache\Strategy;
4
 
5
use Kevinrob\GuzzleCache\CacheEntry;
6
use Kevinrob\GuzzleCache\KeyValueHttpHeader;
7
use Kevinrob\GuzzleCache\Storage\CacheStorageInterface;
8
use Psr\Http\Message\RequestInterface;
9
use Psr\Http\Message\ResponseInterface;
10
 
11
/**
12
 * This strategy represents a "greedy" HTTP client.
13
 *
14
 * It can be used to cache responses in spite of any cache related response headers,
15
 * but it SHOULDN'T be used unless absolutely necessary, e.g. when accessing
16
 * badly designed APIs without Cache control.
17
 *
18
 * Obviously, this follows no RFC :(.
19
 */
20
class GreedyCacheStrategy extends PrivateCacheStrategy
21
{
22
    const HEADER_TTL = 'X-Kevinrob-GuzzleCache-TTL';
23
 
24
    /**
25
     * @var int
26
     */
27
    protected $defaultTtl;
28
 
29
    /**
30
     * @var KeyValueHttpHeader
31
     */
32
    private $varyHeaders;
33
 
1441 ariadna 34
    public function __construct(
35
        ?CacheStorageInterface $cache = null,
36
        $defaultTtl = 60,
37
        ?KeyValueHttpHeader $varyHeaders = null,
38
    ) {
1 efrain 39
        $this->defaultTtl = $defaultTtl;
40
        $this->varyHeaders = $varyHeaders;
41
        parent::__construct($cache);
42
    }
43
 
1441 ariadna 44
    protected function getCacheKey(RequestInterface $request, ?KeyValueHttpHeader $varyHeaders = null)
1 efrain 45
    {
46
        if (null === $varyHeaders || $varyHeaders->isEmpty()) {
47
            return hash(
48
                'sha256',
49
                'greedy'.$request->getMethod().$request->getUri()
50
            );
51
        }
52
 
53
        $cacheHeaders = [];
54
        foreach ($varyHeaders as $key => $value) {
55
            if ($request->hasHeader($key)) {
56
                $cacheHeaders[$key] = $request->getHeader($key);
57
            }
58
        }
59
 
60
        return hash(
61
            'sha256',
62
            'greedy'.$request->getMethod().$request->getUri().json_encode($cacheHeaders)
63
        );
64
    }
65
 
66
    public function cache(RequestInterface $request, ResponseInterface $response)
67
    {
68
        $warningMessage = sprintf('%d - "%s" "%s"',
69
            299,
70
            'Cached although the response headers indicate not to do it!',
71
            (new \DateTime())->format(\DateTime::RFC1123)
72
        );
73
 
74
        $response = $response->withAddedHeader('Warning', $warningMessage);
75
 
76
        if ($cacheObject = $this->getCacheObject($request, $response)) {
77
            return $this->storage->save(
78
                $this->getCacheKey($request, $this->varyHeaders),
79
                $cacheObject
80
            );
81
        }
82
 
83
        return false;
84
    }
85
 
86
    protected function getCacheObject(RequestInterface $request, ResponseInterface $response)
87
    {
88
        if (!array_key_exists($response->getStatusCode(), $this->statusAccepted)) {
89
            // Don't cache it
90
            return null;
91
        }
92
 
93
        if (null !== $this->varyHeaders && $this->varyHeaders->has('*')) {
94
            // This will never match with a request
95
            return;
96
        }
97
 
98
        $response = $response->withoutHeader('Etag')->withoutHeader('Last-Modified');
99
 
100
        $ttl = $this->defaultTtl;
1441 ariadna 101
        if ($request->hasHeader(static::HEADER_TTL)) {
102
            $ttlHeaderValues = $request->getHeader(static::HEADER_TTL);
1 efrain 103
            $ttl = (int)reset($ttlHeaderValues);
104
        }
105
 
1441 ariadna 106
        return new CacheEntry($request->withoutHeader(static::HEADER_TTL), $response, new \DateTime(sprintf('%+d seconds', $ttl)));
1 efrain 107
    }
108
 
109
    public function fetch(RequestInterface $request)
110
    {
111
        $cache = $this->storage->fetch($this->getCacheKey($request, $this->varyHeaders));
112
        return $cache;
113
    }
114
 
115
    /**
116
     * {@inheritdoc}
117
     */
118
    public function delete(RequestInterface $request)
119
    {
120
        return $this->storage->delete($this->getCacheKey($request));
121
    }
122
}