PluginProbe ʕ •ᴥ•ʔ
NitroPack – Performance, Page Speed & Cache Plugin for Core Web Vitals, CDN & Image Optimization / 1.5.19
NitroPack – Performance, Page Speed & Cache Plugin for Core Web Vitals, CDN & Image Optimization v1.5.19
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 / classes / Integration / Server / LiteSpeed.php
nitropack / classes / Integration / Server Last commit date
Cloudflare.php 3 years ago Fastly.php 4 years ago LiteSpeed.php 3 years ago Sucuri.php 4 years ago
LiteSpeed.php
181 lines
1 <?php
2
3 namespace NitroPack\Integration\Server;
4 use NitroPack\WordPress\NitroPack;
5 use NitroPack\Url\Url;
6 use NitroPack\SDK\Device;
7 use NitroPack\Integration\Hosting\WPX;
8
9 class LiteSpeed {
10 const STAGE = "very_early";
11
12 public static function detect() {
13 return !empty($_SERVER["X-LSCACHE"]) || ( !empty($_SERVER["SERVER_SOFTWARE"]) && strtolower($_SERVER["SERVER_SOFTWARE"]) == "litespeed" );
14 }
15
16 public static function isCacheEnabled() {
17 return
18 !empty($_SERVER["X-LSCACHE"]) &&
19 in_array("on", array_map("trim", explode(",", $_SERVER["X-LSCACHE"]))) &&
20 !empty($_SERVER['LSCACHE_VARY_VALUE']) &&
21 in_array($_SERVER['LSCACHE_VARY_VALUE'], array("nitrodesktop", "nitrotablet", "nitromobile"));
22 }
23
24 public static function sendCacheHeader($maxAge = NULL) {
25 if (!$maxAge) {
26 nitropack_header("X-LiteSpeed-Cache-Control: public");
27 } else if (is_numeric($maxAge)) {
28 nitropack_header("X-LiteSpeed-Cache-Control: public,max-age=" . (int)$maxAge);
29 }
30 }
31
32 public static function purge($url = NULL, $tag = NULL) {
33 if ($url || $tag) {
34 $headerValues = [];
35
36 if ($url) {
37 $urlObj = new Url((new Url($url))->getNormalized());
38 if (!$urlObj->getQuery()) {
39 $headerValues[] = "uri=" . md5($urlObj->getPath());
40 } else {
41 $headerValues[] = "uri=" . md5($urlObj->getPath() . "?" . $urlObj->getQuery());
42 }
43 }
44
45 if ($tag) {
46 $headerValues[] = $tag;
47 }
48
49 nitropack_header("X-LiteSpeed-Purge: " . implode(", ", $headerValues), false);
50 } else {
51 nitropack_header("X-LiteSpeed-Purge: *", false);
52 }
53 }
54
55 public function init($stage) {
56 if (self::detect()) {
57 add_filter('nitropack_should_modify_htaccess', function() { return true; });
58 add_filter('nitropack_htaccess_rules', [$this, 'getHtaccessRules'], 10);
59
60 if (self::isCacheEnabled()) {
61 add_action('nitropack_integration_purge_url', [$this, 'purgeUrl']);
62 add_action('nitropack_integration_purge_all', [$this, 'purgeAll']);
63 add_action('nitropack_early_cache_headers', [$this, 'setupVary']);
64 add_action('nitropack_early_cache_headers', [$this, 'preventProxyCache']);
65 add_action('nitropack_cacheable_cache_headers', [$this, 'allowProxyCache']);
66 add_filter('nocache_headers', function($headers) {
67 $headers["X-LiteSpeed-Cache-Control"] = "no-cache";
68 return $headers;
69 });
70 } else {
71 add_filter('nitropack_needs_htaccess_changes', function() { return true; });
72 }
73 }
74 }
75
76 public function purgeUrl($url) {
77 self::purge($url);
78 }
79
80 public function purgeAll() {
81 self::purge();
82 }
83
84 public function setupVary() {
85 $cookies = []; // Configure vary based on NitroPack's variation cookies.
86
87 $nitro = get_nitropack()->getSdk();
88 if ($nitro && !empty($nitro->getConfig()->PageCache->SupportedCookies)) {
89 $cookies = $nitro->getConfig()->PageCache->SupportedCookies;
90 }
91
92 $device = new Device($_SERVER["HTTP_USER_AGENT"]);
93 $deviceStr = "nitrodesktop";
94
95 if ($device->isMobile()) {
96 $deviceStr = "nitromobile";
97 } else if ($device->isTablet()) {
98 $deviceStr = "nitrotablet";
99 }
100
101 $varyStr = "";
102
103 if ($cookies) {
104 $varyStr = implode(",", array_map(function($name) { return "cookie=$name"; }, $cookies)); // Vary on multiple cookies should look like this: cookie=name1,cookie=name2
105 }
106
107 $varyStr .= ($varyStr ? ", " : "") . "value=$deviceStr";
108
109 nitropack_header("X-LiteSpeed-Vary: $varyStr");
110 }
111
112 public function preventProxyCache() {
113 nitropack_header("X-LiteSpeed-Cache-Control: no-cache");
114 }
115
116 public function allowProxyCache() {
117 self::sendCacheHeader(3600);
118 $urlObj = new Url(NitroPack::getInstance()->getSdk()->getUrl());
119 if (!$urlObj->getQuery()) {
120 $uri = md5($urlObj->getPath());
121 } else {
122 $uri = md5($urlObj->getPath() . "?" . $urlObj->getQuery());
123 }
124
125 nitropack_header("X-LiteSpeed-Tag: uri=$uri");
126
127 // TODO: Add LSC-Cookie headers for variation cookies - https://docs.litespeedtech.com/lscache/devguide/controls/#lsc-cookie
128 }
129
130 public function getHtaccessRules($ruleLines) {
131 $rules = "
132 <IfModule LiteSpeed>
133 RewriteEngine on
134 CacheLookup on
135
136 RewriteRule .* - [E=NitroPackHtaccessVersion:NITROPACK_VERSION]
137 RewriteRule .* - [E=Cache-Control:vary=nitrodesktop]
138
139 RewriteCond %{HTTP_USER_AGENT} Android|iPad|RIM\ Tablet|hp-tablet|Kindle\ Fire [NC]
140 RewriteRule .* - [E=Cache-Control:vary=nitrotablet]
141
142 RewriteCond %{HTTP_USER_AGENT} iPod|iPhone|MobileSafari|webOS|BlackBerry|windows\ phone|symbian|vodafone|opera\ mini|windows\ ce|smartphone|palm|midp [NC,OR]
143 RewriteCond %{HTTP_USER_AGENT} Android.*Mobile [NC,OR]
144 RewriteCond %{HTTP_USER_AGENT} Mobile.*Android [NC]
145 RewriteRule .* - [E=Cache-Control:vary=nitromobile]
146
147 RewriteCond %{HTTP_COOKIE} COOKIEBYPASS
148 RewriteRule .* - [E=Cache-Control:no-cache]
149
150 # QSDROP
151
152 </IfModule>
153 ";
154
155 $rules = str_replace("NITROPACK_VERSION", NITROPACK_VERSION, $rules);
156
157 $nitro = get_nitropack()->getSdk();
158
159 $bypassCookies = ["wordpress_logged_in", "comment_author", "wp-postpass_", "woocommerce_items_in_cart="];
160 if (defined('NITROPACK_LOGGED_IN_COOKIE') || defined('LOGGED_IN_COOKIE')) {
161 $bypassCookies[] = (defined('NITROPACK_LOGGED_IN_COOKIE') ? NITROPACK_LOGGED_IN_COOKIE : (defined('LOGGED_IN_COOKIE') ? LOGGED_IN_COOKIE : '')) . "="; // Add "=" for exact match
162 }
163 if ($nitro && !!$nitro->getConfig()->ExcludedCookies->Status && !empty($nitro->getConfig()->ExcludedCookies->Cookies)) {
164 foreach ($nitro->getConfig()->ExcludedCookies->Cookies as $excludedCookie) {
165 if ($excludedCookie->values) {
166 $bypassCookies[] = $excludedCookie->name . "=(" . implode("|", $excludedCookie->values) . ')\s*(;|$)';
167 } else {
168 $bypassCookies[] = $excludedCookie->name . "=";
169 }
170 }
171 }
172 $rules = str_replace("COOKIEBYPASS", "(" . implode("|", array_map(function($cookie){ return "(^|\;\s*)$cookie"; }, $bypassCookies)) . ")", $rules);
173
174 if ($nitro && !empty($nitro->getConfig()->IgnoredParams)) {
175 $rules = str_replace("# QSDROP", implode("\n", array_map(function($param) { return "CacheKeyModify -qs:$param"; }, array_filter($nitro->getConfig()->IgnoredParams, function($param) { return $param != "ignorenitro"; }))), $rules);
176 }
177
178 return array_merge($ruleLines, explode("\n", $rules));
179 }
180 }
181