Completed
Pull Request — master (#451)
by André
02:26
created

Fastly::clear()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 16
rs 9.7333
c 0
b 0
f 0
cc 1
nc 1
nop 0
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
use Symfony\Component\HttpFoundation\Request;
19
20
/**
21
 * Fastly HTTP cache invalidator.
22
 *
23
 * Additional constructor options:
24
 * - service_identifier    Identifier for your Fastly service account.
25
 * - authentication_token  Token for authentication against Fastly APIs.
26
 *                         For full capabilities (incl ClearCapable) you'll need one with Fastly Engineer permissions.
27
 * - soft_purge            Boolean for doing soft purges or not on tag invalidation and url purging, default true.
28
 *                         Soft purges expires cache instead of hard purge, and allow grace/stale handling.
29
 *
30
 * @link https://docs.fastly.com/api/purge Fastly Purge API documentation.
31
 * @author Simone Fumagalli <[email protected]>
32
 * @author André Rømcke <[email protected]>
33
 */
34
class Fastly extends HttpProxyClient implements ClearCapable, PurgeCapable, RefreshCapable, TagCapable
35
{
36
    /**
37
     * @internal
38
     */
39
    const HTTP_METHOD_PURGE = 'PURGE';
40
41
    /**
42
     * @internal
43
     * @see https://docs.fastly.com/api/purge#purge_db35b293f8a724717fcf25628d713583 Fastly's limit on batch tag purges.
44
     */
45
    const TAG_BATCH_PURGE_LIMIT = 256;
46
47
    /**
48
     * @internal
49
     * @see https://docs.fastly.com/api/purge Base url endpoint used on anything but url PURGE/GET/HEAD.
50
     */
51
    const API_ENDPOINT = 'https://api.fastly.com';
52
53
    /**
54
     * {@inheritdoc}
55
     *
56
     * @see https://docs.fastly.com/api/purge#purge_db35b293f8a724717fcf25628d713583
57
     */
58
    public function invalidateTags(array $tags)
59
    {
60
        $headers = [
61
            'Fastly-Key' => $this->options['authentication_token'],
62
            'Accept' => 'application/json',
63
        ];
64
65
        if (true === $this->options['soft_purge']) {
66
            $headers['Fastly-Soft-Purge'] = 1;
67
        }
68
69
        // Split tag invalidations across several requests within Fastly's tag batch invalidations limits.
70
        foreach (\array_chunk($tags, self::TAG_BATCH_PURGE_LIMIT) as $tagChunk) {
71
            $this->queueRequest(
72
                Request::METHOD_POST,
73
                sprintf(self::API_ENDPOINT . '/service/%s/purge', $this->options['service_identifier']),
74
                $headers + [
75
                    // Note: Can be changed to rather use json payload if queueRequest is changed to allow passing body
76
                    'Surrogate-Key' => implode(' ', $tagChunk),
77
                ],
78
                false
79
            );
80
        }
81
82
        return $this;
83
    }
84
85
    /**
86
     * {@inheritdoc}
87
     *
88
     * @see https://docs.fastly.com/api/purge#soft_purge_0c4f56f3d68e9bed44fb8b638b78ea36
89
     * @see https://docs.fastly.com/guides/purging/authenticating-api-purge-requests#purging-urls-with-an-api-token
90
     */
91
    public function purge($url, array $headers = [])
92
    {
93
        $headers['Fastly-Key'] = $this->options['authentication_token'];
94
95
        if (true === $this->options['soft_purge']) {
96
            $headers['Fastly-Soft-Purge'] = 1;
97
        }
98
99
        $this->queueRequest(
100
            self::HTTP_METHOD_PURGE,
101
            $url,
102
            $headers,
103
            false
104
        );
105
106
        return $this;
107
    }
108
109
    /**
110
     * {@inheritdoc}
111
     */
112
    public function refresh($url, array $headers = [])
113
    {
114
        $headers['Fastly-Key'] = $this->options['authentication_token'];
115
116
        // First soft purge url
117
        $this->queueRequest(
118
            self::HTTP_METHOD_PURGE,
119
            $url,
120
            array_merge($headers, ['Fastly-Soft-Purge' => 1]),
121
            false
122
        );
123
124
        // Secondly make sure refresh is triggered
125
        $this->queueRequest(
126
            Request::METHOD_HEAD,
127
            $url,
128
            $headers,
129
            false
130
        );
131
132
        return $this;
133
    }
134
135
    /**
136
     * {@inheritdoc}
137
     *
138
     * @see https://docs.fastly.com/api/purge#purge_bee5ed1a0cfd541e8b9f970a44718546
139
     *
140
     * Warning:
141
     * - Does not support soft purge, for that use an "all" key.
142
     * - Requires a API token of a user with at least Engineer permissions.
143
     */
144
    public function clear()
145
    {
146
        $headers = [
147
            'Fastly-Key' => $this->options['authentication_token'],
148
            'Accept' => 'application/json',
149
        ];
150
151
        $this->queueRequest(
152
            Request::METHOD_POST,
153
            sprintf(self::API_ENDPOINT . '/service/%s/purge_all', $this->options['service_identifier']),
154
            $headers,
155
            false
156
        );
157
158
        return $this;
159
    }
160
161
    /**
162
     * {@inheritdoc}
163
     */
164
    protected function configureOptions()
165
    {
166
        $resolver = parent::configureOptions();
167
168
        $resolver->setRequired([
169
            'authentication_token',
170
            'service_identifier',
171
            'soft_purge',
172
        ]);
173
174
        $resolver->setDefaults([
175
            'soft_purge' => true,
176
        ]);
177
178
        return $resolver;
179
    }
180
}
181