PluginProbe ʕ •ᴥ•ʔ
NitroPack – Performance, Page Speed & Cache Plugin for Core Web Vitals, CDN & Image Optimization / 1.5.4
NitroPack – Performance, Page Speed & Cache Plugin for Core Web Vitals, CDN & Image Optimization v1.5.4
1.19.8 1.19.7 1.19.6 1.19.5 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.11.0 1.12.0 1.13.0 1.14.0 1.15.0 1.15.1 1.15.2 1.15.3 1.16.0 1.16.1 1.16.2 1.16.3 1.16.4 1.16.5 1.16.6 1.16.7 1.16.8 1.17.0 1.17.6 1.17.7 1.17.8 1.17.9 1.18.0 1.18.1 1.18.2 1.18.3 1.18.4 1.18.5 1.18.6 1.18.7 1.18.8 1.18.9 1.19.0 1.19.1 1.19.2 1.19.3 1.19.4 1.3.19 1.3.20 1.4.0 1.4.1 1.5.0 1.5.1 1.5.10 1.5.11 1.5.12 1.5.13 1.5.14 1.5.15 1.5.16 1.5.17 1.5.18 1.5.19 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.7.0 1.7.1 1.8.0 1.8.1 1.8.3 1.9.0 1.9.1 1.9.2
nitropack / nitropack-sdk / bootstrap.php
nitropack / nitropack-sdk Last commit date
NitroPack 5 years ago vendor 5 years ago autoload.php 6 years ago bootstrap.php 6 years ago nitro.start.php 6 years ago
bootstrap.php
377 lines
1 <?php
2
3 require_once dirname(__FILE__) . "/autoload.php";
4
5 $np_originalRequestCookies = $_COOKIE;
6 /* You must define these constants before requiring this file for easier installation of SDK updates
7 define("NITROPACK_HOME_URL", "Your home page URL");
8 define("NITROPACK_SITE_ID", "your site ID");
9 define("NITROPACK_SITE_SECRET", "your site secret");
10 */
11 if (!defined("NITROPACK_ENABLE_COMPRESSION")) define("NITROPACK_ENABLE_COMPRESSION", false); // Set this to true to enable compression. Only do this if your server does not already have compression enabled
12 if (!defined("NITROPACK_WEBHOOK_TOKEN")) define("NITROPACK_WEBHOOK_TOKEN", md5(__FILE__)); // Feel free to set this to a value of your liking
13 if (!defined("NITROPACK_USE_REDIS")) define("NITROPACK_USE_REDIS", false); // Set this to true to enable storing cache in Redis
14 if (!defined("NITROPACK_REDIS_HOST")) define("NITROPACK_REDIS_HOST", "127.0.0.1"); // Set this to the IP of your Redis server
15 if (!defined("NITROPACK_REDIS_PORT")) define("NITROPACK_REDIS_PORT", 6379); // Set this to the port of your Redis server
16 if (!defined("NITROPACK_REDIS_PASS")) define("NITROPACK_REDIS_PASS", NULL); // Set this to the password of your redis server if authentication is needed
17 if (!defined("NITROPACK_REDIS_DB")) define("NITROPACK_REDIS_DB", NULL); // Set this to the number of the Redis DB if you'd like to not use the default one
18
19 if (NITROPACK_USE_REDIS) {
20 NitroPack\SDK\Filesystem::setStorageDriver(new NitroPack\SDK\StorageDriver\Redis(
21 NITROPACK_REDIS_HOST,
22 NITROPACK_REDIS_PORT,
23 NITROPACK_REDIS_PASS,
24 NITROPACK_REDIS_DB
25 ));
26 }
27
28 function nitropack_filter_non_original_cookies(&$cookies) {
29 global $np_originalRequestCookies;
30 $ogNames = is_array($np_originalRequestCookies) ? array_keys($np_originalRequestCookies) : array();
31 foreach ($cookies as $name=>$val) {
32 if (!in_array($name, $ogNames)) {
33 unset($cookies[$name]);
34 }
35 }
36 }
37
38 function nitropack_get_instance($siteId = NULL, $siteSecret = NULL, $url = NULL) {
39 static $instances = [];
40 $key = $url ? $url : "auto";
41 if (empty($instances[$key])) {
42 try {
43 NitroPack\SDK\NitroPack::addCookieFilter("nitropack_filter_non_original_cookies");
44 $siteId = $siteId !== NULL ? $siteId : NITROPACK_SITE_ID;
45 $siteSecret = $siteSecret !== NULL ? $siteSecret : NITROPACK_SITE_SECRET;
46 $instances[$key] = new NitroPack\SDK\NitroPack($siteId, $siteSecret, NULL, $url);
47 } catch(\Exception $e) {
48 $instances[$key] = NULL;
49 }
50 }
51
52 return $instances[$key];
53 }
54
55 function nitropack_handle_request() {
56 header('Cache-Control: no-cache');
57 header('X-Nitro-Cache: MISS');
58 if ( !empty($_SERVER["HTTP_HOST"]) && !empty($_SERVER["REQUEST_URI"]) ) {
59 try {
60 if (is_valid_nitropack_webhook()) {
61 nitropack_handle_webhook();
62 } else {
63 if (is_valid_nitropack_beacon()) {
64 nitropack_handle_beacon();
65 } else {
66 if ( null !== $nitro = nitropack_get_instance() ) {
67 if ($nitro->isCacheAllowed()) {
68 if (NITROPACK_ENABLE_COMPRESSION) {
69 $nitro->enableCompression();
70 }
71
72 if ($nitro->hasLocalCache()) {
73 header('X-Nitro-Cache: HIT');
74 setcookie("nitroCache", "HIT", time() + 10);
75 $nitro->pageCache->readfile();
76 exit;
77 } else {
78 // We need the following if..else block to handle bot requests which will not be firing our beacon
79 if (nitropack_is_warmup_request()) {
80 $nitro->hasRemoteCache("default"); // Only ping the API letting our service know that this page must be cached.
81 exit; // No need to continue handling this request. The response is not important.
82 } else if (nitropack_is_lighthouse_request() || nitropack_is_gtmetrix_request() || nitropack_is_pingdom_request()) {
83 $nitro->hasRemoteCache("default"); // Ping the API letting our service know that this page must be cached.
84 }
85
86 $nitro->pageCache->useInvalidated(true);
87 if ($nitro->hasLocalCache()) {
88 header('X-Nitro-Cache: STALE');
89 $nitro->pageCache->readfile();
90 exit;
91 } else {
92 $nitro->pageCache->useInvalidated(false);
93 }
94 }
95 }
96 }
97 }
98 }
99 } catch (\Exception $e) {
100 // Fail silently
101 }
102 }
103 }
104
105 function nitropack_validate_webhook_token($token) {
106 return preg_match("/^([abcdef0-9]{32})$/", strtolower($token)) && $token == NITROPACK_WEBHOOK_TOKEN;
107 }
108
109 function is_valid_nitropack_webhook() {
110 return !empty($_GET["nitroWebhook"]) && !empty($_GET["token"]) && nitropack_validate_webhook_token($_GET["token"]);
111 }
112
113 function is_valid_nitropack_beacon() {
114 if (!isset($_POST["nitroBeaconUrl"]) || !isset($_POST["nitroBeaconHash"])) return false;
115
116 if (function_exists("hash_hmac") && function_exists("hash_equals")) {
117 $url = base64_decode($_POST["nitroBeaconUrl"]);
118 $cookiesJson = !empty($_POST["nitroBeaconCookies"]) ? base64_decode($_POST["nitroBeaconCookies"]) : ""; // We need to fall back to empty string to remain backwards compatible. Otherwise cache files invalidated before an upgrade will never get updated :(
119 $localHash = hash_hmac("sha512", $url.$cookiesJson, NITROPACK_SITE_SECRET);
120 return hash_equals($_POST["nitroBeaconHash"], $localHash);
121 } else {
122 return !empty($_POST["nitroBeaconUrl"]);
123 }
124 }
125
126 function nitropack_handle_beacon() {
127 global $np_originalRequestCookies;
128 if (!empty($_POST["nitroBeaconUrl"])) {
129 $url = base64_decode($_POST["nitroBeaconUrl"]);
130
131 if (!empty($_POST["nitroBeaconCookies"])) {
132 $np_originalRequestCookies = json_decode(base64_decode($_POST["nitroBeaconCookies"]), true);
133 }
134
135 if (null !== $nitro = nitropack_get_instance(NITROPACK_SITE_ID, NITROPACK_SITE_SECRET, $url) ) {
136 try {
137 if (!$nitro->hasLocalCache(false)) {
138 header("X-Nitro-Beacon: FORWARD");
139 $hasCache = $nitro->hasRemoteCache("default", false); // Download the new cache file
140 $nitro->purgeProxyCache($url);
141 printf("Cache %s", $hasCache ? "fetched" : "requested");
142 } else {
143 header("X-Nitro-Beacon: SKIP");
144 printf("Cache exists already");
145 }
146 } catch (Exception $e) {
147 // not a critical error, do nothing
148 }
149 }
150 }
151 exit;
152 }
153
154 function nitropack_handle_webhook() {
155 if (NITROPACK_WEBHOOK_TOKEN == $_GET["token"]) {
156 switch($_GET["nitroWebhook"]) {
157 case "config":
158 if (null !== $nitro = nitropack_get_instance() ) {
159 try {
160 $nitro->fetchConfig();
161 } catch (\Exception $e) {}
162 }
163 break;
164 case "cache_ready":
165 if (!empty($_POST["url"])) {
166 $readyUrl = nitropack_sanitize_url_input($_POST["url"]);
167
168 if ($readyUrl && null !== $nitro = nitropack_get_instance(NITROPACK_SITE_ID, NITROPACK_SITE_SECRET, $readyUrl) ) {
169 $hasCache = $nitro->hasRemoteCache("default", false); // Download the new cache file
170 $nitro->purgeProxyCache($readyUrl);
171 }
172 }
173 break;
174 case "cache_clear":
175 if (!empty($_POST["url"])) {
176 $urls = is_array($_POST["url"]) ? $_POST["url"] : array($_POST["url"]);
177 foreach ($urls as $url) {
178 $sanitizedUrl = nitropack_sanitize_url_input($url);
179 nitropack_sdk_purge_local($sanitizedUrl);
180 }
181 } else {
182 nitropack_sdk_purge_local();
183 }
184 break;
185 }
186 }
187 exit;
188 }
189
190 function nitropack_sanitize_url_input($url) {
191 $result = NULL;
192 $sanitizedUrl = filter_var($url, FILTER_SANITIZE_URL);
193 if ($sanitizedUrl !== false && filter_var($sanitizedUrl, FILTER_VALIDATE_URL) !== false) {
194 $result = $sanitizedUrl;
195 }
196
197 return $result;
198 }
199
200 function nitropack_sdk_invalidate($url = NULL, $tag = NULL, $reason = NULL) {
201 if (null !== $nitro = nitropack_get_instance()) {
202 try {
203 if ($tag) {
204 if (is_array($tag)) {
205 $tag = array_map('nitropack_filter_tag', $tag);
206 } else {
207 $tag = nitropack_filter_tag($tag);
208 }
209 }
210
211 if ($tag != "pageType:home") {
212 $nitro->invalidateCache(NITROPACK_HOME_URL, "pageType:home", $reason);
213 }
214
215 $nitro->invalidateCache($url, $tag, $reason);
216 } catch (\Exception $e) {
217 return false;
218 }
219
220 return true;
221 }
222
223 return false;
224 }
225
226 function nitropack_sdk_purge($url = NULL, $tag = NULL, $reason = NULL, $type = \NitroPack\SDK\PurgeType::COMPLETE) {
227 if (null !== $nitro = nitropack_get_instance()) {
228 try {
229 if ($tag) {
230 if (is_array($tag)) {
231 $tag = array_map('nitropack_filter_tag', $tag);
232 } else {
233 $tag = nitropack_filter_tag($tag);
234 }
235 }
236
237 if ($tag != "pageType:home") {
238 $nitro->invalidateCache(NITROPACK_HOME_URL, "pageType:home", $reason);
239 }
240
241 $nitro->purgeCache($url, $tag, $type, $reason);
242 } catch (\Exception $e) {
243 return false;
244 }
245
246 return true;
247 }
248
249 return false;
250 }
251
252 function nitropack_sdk_purge_local($url = NULL) {
253 if (null !== $nitro = nitropack_get_instance()) {
254 try {
255 if ($url) {
256 $nitro->purgeLocalUrlCache($url);
257 } else {
258 $nitro->purgeLocalCache();
259 }
260 } catch (\Exception $e) {
261 return false;
262 }
263
264 return true;
265 }
266
267 return false;
268 }
269
270 function nitropack_filter_tag($tag) {
271 return preg_replace("/[^a-zA-Z0-9:]/", ":", $tag);
272 }
273
274 function nitropack_is_warmup_request() {
275 return !empty($_SERVER["HTTP_X_NITRO_WARMUP"]);
276 }
277
278 function nitropack_is_lighthouse_request() {
279 return !empty($_SERVER["HTTP_USER_AGENT"]) && stripos($_SERVER["HTTP_USER_AGENT"], "lighthouse") !== false;
280 }
281
282 function nitropack_is_gtmetrix_request() {
283 return !empty($_SERVER["HTTP_USER_AGENT"]) && stripos($_SERVER["HTTP_USER_AGENT"], "gtmetrix") !== false;
284 }
285
286 function nitropack_is_pingdom_request() {
287 return !empty($_SERVER["HTTP_USER_AGENT"]) && stripos($_SERVER["HTTP_USER_AGENT"], "pingdom") !== false;
288 }
289
290 function nitropack_is_optimizer_request() {
291 return isset($_SERVER["HTTP_X_NITROPACK_REQUEST"]);
292 }
293
294 function nitropack_add_tag($tag = NULL, $flush = false) {
295 static $addedTags = [];
296
297 if ($tag) {
298 $addedTags[] = $tag;
299 }
300
301 if ($flush) {
302 if (null !== $nitro = nitropack_get_instance()) {
303 try {
304 // Check whether this is the home page and tag this URL with pageType:home
305 $nitro->getApi()->tagUrl($nitro->getUrl(), array_map("nitropack_filter_tag", $addedTags));
306 } catch (\Exception $e) {}
307 }
308 }
309 }
310
311 function nitropack_get_beacon_script() {
312 if (null !== $nitro = nitropack_get_instance() ) {
313 $url = $nitro->getUrl();
314 $cookiesJson = json_encode($nitro->supportedCookiesFilter(NitroPack\SDK\NitroPack::getCookies()));
315
316 if (function_exists("hash_hmac") && function_exists("hash_equals")) {
317 $hash = hash_hmac("sha512", $url.$cookiesJson, NITROPACK_SITE_SECRET);
318 } else {
319 $hash = "";
320 }
321 $url = base64_encode($url); // We want only ASCII
322 $cookiesb64 = base64_encode($cookiesJson);
323
324 return "<script nitro-exclude>if (document.cookie.indexOf('nitroCache=HIT') == -1) {var nitroData = new FormData(); nitroData.append('nitroBeaconUrl', '$url'); nitroData.append('nitroBeaconCookies', '$cookiesb64'); nitroData.append('nitroBeaconHash', '$hash'); navigator.sendBeacon(location.href, nitroData);} document.cookie = 'nitroCache=HIT; expires=Thu, 01 Jan 1970 00:00:01 GMT;';</script>";
325 }
326 }
327
328 function nitropack_init_webhooks() {
329 $webhookFile = dirname(__FILE__) . "/nitropack_webhooks";
330
331 if (!NitroPack\SDK\Filesystem::fileExists($webhookFile)) {
332 NitroPack\SDK\Filesystem::filePutContents($webhookFile, time());
333 if (null !== $nitro = nitropack_get_instance() ) {
334 try {
335 $configUrl = new \NitroPack\Url(NITROPACK_HOME_URL . "?nitroWebhook=config&token=" . NITROPACK_WEBHOOK_TOKEN);
336 $cacheClearUrl = new \NitroPack\Url(NITROPACK_HOME_URL . "?nitroWebhook=cache_clear&token=" . NITROPACK_WEBHOOK_TOKEN);
337 $cacheReadyUrl = new \NitroPack\Url(NITROPACK_HOME_URL . "?nitroWebhook=cache_ready&token=" . NITROPACK_WEBHOOK_TOKEN);
338
339 $nitro->getApi()->setWebhook("config", $configUrl);
340 $nitro->getApi()->setWebhook("cache_clear", $cacheClearUrl);
341 $nitro->getApi()->setWebhook("cache_ready", $cacheReadyUrl);
342 } catch (\Exception $e) {}
343 }
344 }
345 }
346
347 nitropack_handle_request();
348 if ( null !== $nitro = nitropack_get_instance() ) {
349 if ($nitro->isAllowedUrl($nitro->getUrl()) && $nitro->isAllowedRequest(true)) {
350 nitropack_init_webhooks();
351 ob_start();
352 register_shutdown_function(function() {
353 $buffer = ob_get_clean();
354
355 if (nitropack_is_optimizer_request()) {
356 nitropack_add_tag(NULL, true); // Flush registered tags
357 }
358
359 // Remove BOM from output
360 $bom = pack('H*','EFBBBF');
361 $buffer = preg_replace("/^($bom)*/", '', $buffer);
362
363 if (stripos($buffer, "</body>") !== FALSE) {
364 // Append before </body>
365 $buffer = str_replace("</body>", nitropack_get_beacon_script() . "</body>", $buffer);
366 } else {
367 // Append at the end of the output
368 $buffer .= nitropack_get_beacon_script();
369 }
370
371 echo $buffer;
372 });
373 } else {
374 header("X-Nitro-Disabled: 1");
375 }
376 }
377