Completed
Push — master ( 478cf7...3c1cb3 )
by David
22s queued 17s
created

Fastly   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 149
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 9
lcom 1
cbo 2
dl 0
loc 149
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A invalidateTags() 0 21 3
A purge() 0 15 2
A refresh() 0 20 1
A clear() 0 11 1
A queueRequest() 0 10 1
A configureOptions() 0 16 1
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
 */
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
     *
44
     * @see https://docs.fastly.com/api/purge#purge_db35b293f8a724717fcf25628d713583 Fastly's limit on batch tag purges.
45
     */
46
    const TAG_BATCH_PURGE_LIMIT = 256;
47
48
    /**
49
     * @internal
50
     *
51
     * @see https://docs.fastly.com/api/purge Base url endpoint used on anything but url PURGE/GET/HEAD.
52
     */
53
    const API_ENDPOINT = 'https://api.fastly.com';
54
55
    /**
56
     * {@inheritdoc}
57
     *
58
     * @see https://docs.fastly.com/api/purge#purge_db35b293f8a724717fcf25628d713583
59
     */
60
    public function invalidateTags(array $tags)
61
    {
62
        $url = sprintf(self::API_ENDPOINT.'/service/%s/purge', $this->options['service_identifier']);
63
        $headers = ['Accept' => 'application/json'];
64
        if (true === $this->options['soft_purge']) {
65
            $headers['Fastly-Soft-Purge'] = 1;
66
        }
67
68
        // Split tag invalidations across several requests within Fastly's tag batch invalidations limits.
69
        foreach (\array_chunk($tags, self::TAG_BATCH_PURGE_LIMIT) as $tagChunk) {
70
            $this->queueRequest(
71
                Request::METHOD_POST,
72
                $url,
73
                $headers,
74
                false,
75
                json_encode(['surrogate_keys' => $tagChunk])
76
            );
77
        }
78
79
        return $this;
80
    }
81
82
    /**
83
     * {@inheritdoc}
84
     *
85
     * @see https://docs.fastly.com/api/purge#soft_purge_0c4f56f3d68e9bed44fb8b638b78ea36
86
     * @see https://docs.fastly.com/guides/purging/authenticating-api-purge-requests#purging-urls-with-an-api-token
87
     */
88
    public function purge($url, array $headers = [])
89
    {
90
        if (true === $this->options['soft_purge']) {
91
            $headers['Fastly-Soft-Purge'] = 1;
92
        }
93
94
        $this->queueRequest(
95
            self::HTTP_METHOD_PURGE,
96
            $url,
97
            $headers,
98
            false
99
        );
100
101
        return $this;
102
    }
103
104
    /**
105
     * {@inheritdoc}
106
     */
107
    public function refresh($url, array $headers = [])
108
    {
109
        // First soft purge url
110
        $this->queueRequest(
111
            self::HTTP_METHOD_PURGE,
112
            $url,
113
            ['Fastly-Soft-Purge' => 1] + $headers,
114
            false
115
        );
116
117
        // Secondly make sure refresh is triggered with a HEAD request
118
        $this->queueRequest(
119
            Request::METHOD_HEAD,
120
            $url,
121
            $headers,
122
            false
123
        );
124
125
        return $this;
126
    }
127
128
    /**
129
     * {@inheritdoc}
130
     *
131
     * @see https://docs.fastly.com/api/purge#purge_bee5ed1a0cfd541e8b9f970a44718546
132
     *
133
     * Warning:
134
     * - Does not support soft purge, for that use an "all" key.
135
     * - Requires a API token of a user with at least Engineer permissions.
136
     */
137
    public function clear()
138
    {
139
        $this->queueRequest(
140
            Request::METHOD_POST,
141
            sprintf(self::API_ENDPOINT.'/service/%s/purge_all', $this->options['service_identifier']),
142
            ['Accept' => 'application/json'],
143
            false
144
        );
145
146
        return $this;
147
    }
148
149
    /**
150
     * {@inheritdoc} Always provides default authentication token on "Fastly-Key" header.
151
     */
152
    protected function queueRequest($method, $url, array $headers, $validateHost = true, $body = null)
153
    {
154
        parent::queueRequest(
155
            $method,
156
            $url,
157
            $headers + ['Fastly-Key' => $this->options['authentication_token']],
158
            $validateHost,
159
            $body
160
        );
161
    }
162
163
    /**
164
     * {@inheritdoc}
165
     */
166
    protected function configureOptions()
167
    {
168
        $resolver = parent::configureOptions();
169
170
        $resolver->setRequired([
171
            'authentication_token',
172
            'service_identifier',
173
            'soft_purge',
174
        ]);
175
176
        $resolver->setDefaults([
177
            'soft_purge' => true,
178
        ]);
179
180
        return $resolver;
181
    }
182
}
183