Issues (1)

src/CDNMiddleware.php (1 issue)

Severity
1
<?php
2
3
namespace DorsetDigital\CDNRewrite;
4
5
use SilverStripe\Admin\AdminRootController;
6
use SilverStripe\Control\Director;
7
use SilverStripe\Control\HTTPRequest;
8
use SilverStripe\Control\Middleware\HTTPMiddleware;
9
use SilverStripe\Core\Config\Configurable;
10
use SilverStripe\Core\Injector\Injectable;
11
use SilverStripe\View\HTML;
12
13
class CDNMiddleware implements HTTPMiddleware
14
{
15
16
    use Injectable;
17
    use Configurable;
18
19
    /**
20
     * @config
21
     *
22
     * Enable rewriting
23
     * @var bool
24
     */
25
    private static $cdn_rewrite = false;
26
27
    /**
28
     * @config
29
     *
30
     * The cdn domain incl. protocol
31
     * @var string
32
     */
33
    private static $cdn_domain = '';
34
35
    /**
36
     * @config
37
     *
38
     * Enable rewrite in dev mode
39
     * @var bool
40
     */
41
    private static $enable_in_dev = false;
42
43
    /**
44
     * @config
45
     *
46
     * Add debug headers for each operation
47
     * @var bool
48
     */
49
    private static $add_debug_headers = false;
50
51
    /**
52
     * @config
53
     *
54
     * Subdirectory name for the site
55
     * @var string
56
     */
57
    private static $subdirectory = '';
58
59
    /**
60
     * @config
61
     *
62
     * Add dns-prefetch links to the html head
63
     * @var boolean
64
     */
65
    private static $add_prefetch = false;
66
67
    /**
68
     * @config
69
     *
70
     * Array of prefixes we wish to rewrite
71
     * @var array
72
     */
73
    private static $rewrites = [];
74
75
    /**
76
     * Process the request
77
     * @param HTTPRequest $request
78
     * @param $delegate
79
     * @return
80
     */
81
    public function process(HTTPRequest $request, callable $delegate)
82
    {
83
        $response = $delegate($request);
84
85
        if (($this->canRun() === true) && ($response !== null)) {
86
            $response->addHeader('X-CDN-Rewrites', 'Enabled');
87
88
            if ($this->getIsAdmin($request) === false) {
89
                $body = $response->getBody();
90
                $this->rewriteTags($body, $response);
91
                $this->addPrefetch($body, $response);
92
                $response->setBody($body);
93
            }
94
95
            if ($this->config()->get('add_debug_headers') == true) {
96
                $response->addHeader('X-CDN-Domain', $this->config()->get('cdn_domain'));
97
                $response->addHeader('X-CDN-Dir', $this->getSubdirectory());
98
            }
99
100
            if ($this->config()->get('cdn_rewrite') === true) {
101
                $response->addHeader('X-CDN-Module', 'Active');
102
            }
103
        }
104
105
        return $response;
106
    }
107
108
    /**
109
     * Check if we're OK to execute
110
     * @return bool
111
     */
112
    private function canRun()
113
    {
114
        $confEnabled = $this->config()->get('cdn_rewrite');
115
        $devEnabled = ((!Director::isDev()) || ($this->config()->get('enable_in_dev')));
116
        return ($confEnabled && $devEnabled);
117
    }
118
119
120
    /**
121
     * Rewrite all the tags we need
122
     * @param $body
123
     * @param $response
124
     */
125
    private function rewriteTags(&$body, &$response)
0 ignored issues
show
The parameter $response is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

125
    private function rewriteTags(&$body, /** @scrutinizer ignore-unused */ &$response)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
126
    {
127
        $cdn = $this->config()->get('cdn_domain');
128
        $subDir = $this->getSubdirectory();
129
        $prefixes = $this->config()->get('rewrites');
130
131
        foreach ($prefixes as $prefix) {
132
            $cleanPrefix = trim($prefix, '/');
133
134
            $search = [
135
                'src="' . $subDir . $cleanPrefix . '/',
136
                'src="/' . $subDir . $cleanPrefix . '/',
137
                'src=\"/' . $subDir . $cleanPrefix . '/',
138
                'href="/' . $subDir . $cleanPrefix . '/',
139
                Director::absoluteBaseURL() . $cleanPrefix . '/'
140
            ];
141
142
            $replace = [
143
                'src="' . $cdn . '/' . $subDir . $cleanPrefix . '/',
144
                'src="' . $cdn . '/' . $subDir . $cleanPrefix . '/',
145
                'src=\"' . $cdn . '/' . $subDir . $cleanPrefix . '/',
146
                'href="' . $cdn . '/' . $subDir . $cleanPrefix . '/',
147
                $cdn . '/' . $subDir . $cleanPrefix . '/'
148
            ];
149
150
            $body = str_replace($search, $replace, $body);
151
        }
152
    }
153
154
155
    private function addPrefetch(&$body, &$response)
156
    {
157
        if ($this->config()->get('add_prefetch') === true) {
158
            $prefetchTag = $this->getPrefetchTag();
159
            $body = str_replace('<head>', "<head>" . $prefetchTag, $body);
160
            if ($this->config()->get('add_debug_headers') == true) {
161
                $response->addHeader('X-CDN-Prefetch', 'Enabled');
162
            }
163
        }
164
    }
165
166
    private function getSubdirectory()
167
    {
168
        $subDir = trim($this->config()->get('subdirectory'), '/');
169
        if ($subDir != "") {
170
            $subDir = $subDir . '/';
171
        }
172
        return $subDir;
173
    }
174
175
    private function getPrefetchTag()
176
    {
177
        $atts = [
178
            'rel' => 'dns-prefetch',
179
            'href' => $this->config()->get('cdn_domain')
180
        ];
181
        $pfTag = "\n" . HTML::createTag('link', $atts);
182
183
        return $pfTag;
184
    }
185
186
    /**
187
     * Determine whether the website is being viewed from an admin protected area or not
188
     * (shamelessly based on https://github.com/silverstripe/silverstripe-subsites)
189
     *
190
     * @param HTTPRequest $request
191
     * @return bool
192
     */
193
    private function getIsAdmin(HTTPRequest $request)
194
    {
195
        $adminPath = AdminRootController::admin_url();
196
        $currentPath = rtrim($request->getURL(), '/') . '/';
197
        if (substr($currentPath, 0, strlen($adminPath)) === $adminPath) {
198
            return true;
199
        }
200
        return false;
201
    }
202
}
203