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

Fastly::refresh()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

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