Completed
Push — master ( c28032...f16ad4 )
by David
25s queued 12s
created

Fastly   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 140
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 6
Bugs 0 Features 1
Metric Value
eloc 55
c 6
b 0
f 1
dl 0
loc 140
ccs 46
cts 46
cp 1
rs 10
wmc 9

6 Methods

Rating   Name   Duplication   Size   Complexity  
A clear() 0 10 1
A configureOptions() 0 15 1
A queueRequest() 0 8 1
A purge() 0 14 2
A refresh() 0 19 1
A invalidateTags() 0 20 3
1
<?php
2
3
/*
4
 * This file is part of the FOSHttpCache package.
5
 *
6
 * (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace FOS\HttpCache\ProxyClient;
13
14
use FOS\HttpCache\ProxyClient\Invalidation\ClearCapable;
15
use FOS\HttpCache\ProxyClient\Invalidation\PurgeCapable;
16
use FOS\HttpCache\ProxyClient\Invalidation\RefreshCapable;
17
use FOS\HttpCache\ProxyClient\Invalidation\TagCapable;
18
19
/**
20
 * Fastly HTTP cache invalidator.
21
 *
22
 * Additional constructor options:
23
 * - service_identifier    Identifier for your Fastly service account.
24
 * - authentication_token  Token for authentication against Fastly APIs.
25
 *                         For full capabilities (incl ClearCapable) you'll need one with Fastly Engineer permissions.
26
 * - soft_purge            Boolean for doing soft purges or not on tag invalidation and url purging, default true.
27
 *                         Soft purges expires cache instead of hard purge, and allow grace/stale handling.
28
 *
29
 * @see https://docs.fastly.com/api/purge Fastly Purge API documentation.
30
 *
31
 * @author Simone Fumagalli <[email protected]>
32
 */
33
class Fastly extends HttpProxyClient implements ClearCapable, PurgeCapable, RefreshCapable, TagCapable
34
{
35
    private const HTTP_METHOD_PURGE = 'PURGE';
36
37
    /**
38
     * @see https://docs.fastly.com/api/purge#purge_db35b293f8a724717fcf25628d713583 Fastly's limit on batch tag purges.
39
     */
40
    private const TAG_BATCH_PURGE_LIMIT = 256;
41
42
    /**
43
     * @see https://docs.fastly.com/api/purge Base url endpoint used on anything but url PURGE/GET/HEAD.
44
     */
45
    private const API_ENDPOINT = 'https://api.fastly.com';
46
47
    /**
48
     * {@inheritdoc}
49
     *
50
     * @see https://docs.fastly.com/api/purge#purge_db35b293f8a724717fcf25628d713583
51
     */
52 3
    public function invalidateTags(array $tags)
53
    {
54 3
        $url = sprintf(self::API_ENDPOINT.'/service/%s/purge', $this->options['service_identifier']);
55 3
        $headers = ['Accept' => 'application/json'];
56 3
        if (true === $this->options['soft_purge']) {
57 2
            $headers['Fastly-Soft-Purge'] = 1;
58
        }
59
60
        // Split tag invalidations across several requests within Fastly's tag batch invalidations limits.
61 3
        foreach (\array_chunk($tags, self::TAG_BATCH_PURGE_LIMIT) as $tagChunk) {
62 3
            $this->queueRequest(
63 3
                'POST',
64
                $url,
65
                $headers,
66 3
                false,
67 3
                json_encode(['surrogate_keys' => $tagChunk])
68
            );
69
        }
70
71 3
        return $this;
72
    }
73
74
    /**
75
     * {@inheritdoc}
76
     *
77
     * @see https://docs.fastly.com/api/purge#soft_purge_0c4f56f3d68e9bed44fb8b638b78ea36
78
     * @see https://docs.fastly.com/guides/purging/authenticating-api-purge-requests#purging-urls-with-an-api-token
79
     */
80 1
    public function purge($url, array $headers = [])
81
    {
82 1
        if (true === $this->options['soft_purge']) {
83 1
            $headers['Fastly-Soft-Purge'] = 1;
84
        }
85
86 1
        $this->queueRequest(
87 1
            self::HTTP_METHOD_PURGE,
88
            $url,
89
            $headers,
90 1
            false
91
        );
92
93 1
        return $this;
94
    }
95
96
    /**
97
     * {@inheritdoc}
98
     */
99 1
    public function refresh($url, array $headers = [])
100
    {
101
        // First soft purge url
102 1
        $this->queueRequest(
103 1
            self::HTTP_METHOD_PURGE,
104
            $url,
105 1
            ['Fastly-Soft-Purge' => 1] + $headers,
106 1
            false
107
        );
108
109
        // Secondly make sure refresh is triggered with a HEAD request
110 1
        $this->queueRequest(
111 1
            'HEAD',
112
            $url,
113
            $headers,
114 1
            false
115
        );
116
117 1
        return $this;
118
    }
119
120
    /**
121
     * {@inheritdoc}
122
     *
123
     * @see https://docs.fastly.com/api/purge#purge_bee5ed1a0cfd541e8b9f970a44718546
124
     *
125
     * Warning:
126
     * - Does not support soft purge, for that use an "all" key.
127
     * - Requires a API token of a user with at least Engineer permissions.
128
     */
129 1
    public function clear()
130
    {
131 1
        $this->queueRequest(
132 1
            'POST',
133 1
            sprintf(self::API_ENDPOINT.'/service/%s/purge_all', $this->options['service_identifier']),
134 1
            ['Accept' => 'application/json'],
135 1
            false
136
        );
137
138 1
        return $this;
139
    }
140
141
    /**
142
     * {@inheritdoc} Always provides default authentication token on "Fastly-Key" header.
143
     */
144 6
    protected function queueRequest($method, $url, array $headers, $validateHost = true, $body = null)
145
    {
146 6
        parent::queueRequest(
147 6
            $method,
148
            $url,
149 6
            $headers + ['Fastly-Key' => $this->options['authentication_token']],
150
            $validateHost,
151
            $body
152
        );
153 6
    }
154
155
    /**
156
     * {@inheritdoc}
157
     */
158 6
    protected function configureOptions()
159
    {
160 6
        $resolver = parent::configureOptions();
161
162 6
        $resolver->setRequired([
163 6
            'authentication_token',
164
            'service_identifier',
165
            'soft_purge',
166
        ]);
167
168 6
        $resolver->setDefaults([
169 6
            'soft_purge' => true,
170
        ]);
171
172 6
        return $resolver;
173
    }
174
}
175