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