1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* Nexcess.net Turpentine Extension for Magento |
5
|
|
|
* Copyright (C) 2012 Nexcess.net L.L.C. |
6
|
|
|
* |
7
|
|
|
* This program is free software; you can redistribute it and/or modify |
8
|
|
|
* it under the terms of the GNU General Public License as published by |
9
|
|
|
* the Free Software Foundation; either version 2 of the License, or |
10
|
|
|
* (at your option) any later version. |
11
|
|
|
* |
12
|
|
|
* This program is distributed in the hope that it will be useful, |
13
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
14
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15
|
|
|
* GNU General Public License for more details. |
16
|
|
|
* |
17
|
|
|
* You should have received a copy of the GNU General Public License along |
18
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc., |
19
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
20
|
|
|
*/ |
21
|
|
|
|
22
|
|
|
abstract class Nexcessnet_Turpentine_Model_Varnish_Configurator_Abstract { |
23
|
|
|
|
24
|
|
|
const VCL_CUSTOM_C_CODE_FILE = 'uuid.c'; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* Get the correct version of a configurator from a socket |
28
|
|
|
* |
29
|
|
|
* @param Nexcessnet_Turpentine_Model_Varnish_Admin_Socket $socket |
30
|
|
|
* @return Nexcessnet_Turpentine_Model_Varnish_Configurator_Abstract |
31
|
|
|
*/ |
32
|
|
|
static public function getFromSocket($socket) { |
33
|
|
|
try { |
34
|
|
|
$version = $socket->getVersion(); |
35
|
|
|
} catch (Mage_Core_Exception $e) { |
36
|
|
|
Mage::getSingleton('core/session') |
37
|
|
|
->addError('Error determining Varnish version: '. |
38
|
|
|
$e->getMessage()); |
39
|
|
|
return null; |
40
|
|
|
} |
41
|
|
|
switch ($version) { |
42
|
|
|
case '4.0': |
43
|
|
|
case '4.1': |
44
|
|
|
return Mage::getModel( |
45
|
|
|
'turpentine/varnish_configurator_version4', |
46
|
|
|
array('socket' => $socket) ); |
47
|
|
|
|
48
|
|
|
case '3.0': |
49
|
|
|
return Mage::getModel( |
50
|
|
|
'turpentine/varnish_configurator_version3', |
51
|
|
|
array('socket' => $socket) ); |
52
|
|
|
case '2.1': |
53
|
|
|
return Mage::getModel( |
54
|
|
|
'turpentine/varnish_configurator_version2', |
55
|
|
|
array('socket' => $socket) ); |
56
|
|
|
default: |
57
|
|
|
Mage::throwException('Unsupported Varnish version'); |
58
|
|
|
} |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* The socket this configurator is based on |
63
|
|
|
* |
64
|
|
|
* @var Nexcessnet_Turpentine_Model_Varnish_Admin_Socket |
65
|
|
|
*/ |
66
|
|
|
protected $_socket = null; |
67
|
|
|
/** |
68
|
|
|
* options array |
69
|
|
|
* |
70
|
|
|
* @var array |
71
|
|
|
*/ |
72
|
|
|
protected $_options = array( |
73
|
|
|
'vcl_template' => null, |
74
|
|
|
); |
75
|
|
|
|
76
|
|
|
public function __construct($options = array()) { |
77
|
|
|
$this->_options = array_merge($this->_options, $options); |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
abstract public function generate($doClean = true); |
81
|
|
|
// abstract protected function _getTemplateVars(); |
82
|
|
|
|
83
|
|
|
/** |
84
|
|
|
* Save the generated config to the file specified in Magento config |
85
|
|
|
* |
86
|
|
|
* @param string $generatedConfig config generated by @generate |
87
|
|
|
* @return null |
88
|
|
|
*/ |
89
|
|
|
public function save($generatedConfig) { |
90
|
|
|
$filename = $this->_getVclFilename(); |
91
|
|
|
$dir = dirname($filename); |
92
|
|
|
if ( ! is_dir($dir)) { |
93
|
|
|
// this umask is probably redundant, but just in case... |
94
|
|
|
if ( ! mkdir($dir, 0777 & ~umask(), true)) { |
95
|
|
|
$err = error_get_last(); |
96
|
|
|
return array(false, $err); |
97
|
|
|
} |
98
|
|
|
} |
99
|
|
|
if (strlen($generatedConfig) !== |
100
|
|
|
file_put_contents($filename, $generatedConfig)) { |
101
|
|
|
$err = error_get_last(); |
102
|
|
|
return array(false, $err); |
103
|
|
|
} |
104
|
|
|
return array(true, null); |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* Get the full path for a given template filename |
109
|
|
|
* |
110
|
|
|
* @param string $baseFilename |
111
|
|
|
* @return string |
112
|
|
|
*/ |
113
|
|
|
protected function _getVclTemplateFilename($baseFilename) { |
114
|
|
|
$extensionDir = Mage::getModuleDir('', 'Nexcessnet_Turpentine'); |
115
|
|
|
return sprintf('%s/misc/%s', $extensionDir, $baseFilename); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* Get the name of the file to save the VCL to |
120
|
|
|
* |
121
|
|
|
* @return string |
122
|
|
|
*/ |
123
|
|
|
protected function _getVclFilename() { |
124
|
|
|
return $this->_formatTemplate( |
125
|
|
|
Mage::getStoreConfig('turpentine_varnish/servers/config_file'), |
126
|
|
|
array('root_dir' => Mage::getBaseDir()) ); |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
/** |
130
|
|
|
* Get the name of the custom include VCL file |
131
|
|
|
* |
132
|
|
|
* @return string |
133
|
|
|
*/ |
134
|
|
|
protected function _getCustomIncludeFilename($position = '') { |
135
|
|
|
$key = 'custom_include_file'; |
136
|
|
|
$key .= ($position) ? '_'.$position : ''; |
137
|
|
|
return $this->_formatTemplate( |
138
|
|
|
Mage::getStoreConfig('turpentine_varnish/servers/'.$key), |
139
|
|
|
array('root_dir' => Mage::getBaseDir()) ); |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
|
143
|
|
|
/** |
144
|
|
|
* Get the custom VCL template, if it exists |
145
|
|
|
* Returns 'null' if the file doesn't exist |
146
|
|
|
* |
147
|
|
|
* @return string |
148
|
|
|
*/ |
149
|
|
|
protected function _getCustomTemplateFilename() { |
150
|
|
|
$filePath = $this->_formatTemplate( |
151
|
|
|
Mage::getStoreConfig('turpentine_varnish/servers/custom_vcl_template'), |
152
|
|
|
array('root_dir' => Mage::getBaseDir()) |
153
|
|
|
); |
154
|
|
|
if (is_file($filePath)) { return $filePath; } else { return null; } |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
|
158
|
|
|
/** |
159
|
|
|
* Format a template string, replacing {{keys}} with the appropriate values |
160
|
|
|
* and remove unspecified keys |
161
|
|
|
* |
162
|
|
|
* @param string $template template string to operate on |
163
|
|
|
* @param array $vars array of key => value replacements |
164
|
|
|
* @return string |
165
|
|
|
*/ |
166
|
|
|
protected function _formatTemplate($template, array $vars) { |
167
|
|
|
$needles = array_map(create_function('$k', 'return "{{".$k."}}";'), |
168
|
|
|
array_keys($vars)); |
169
|
|
|
$replacements = array_values($vars); |
170
|
|
|
// do replacements, then delete unused template vars |
171
|
|
|
return preg_replace('~{{[^}]+}}~', '', |
172
|
|
|
str_replace($needles, $replacements, $template)); |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* Format a VCL subroutine call |
177
|
|
|
* |
178
|
|
|
* @param string $subroutine subroutine name |
179
|
|
|
* @return string |
180
|
|
|
*/ |
181
|
|
|
protected function _vcl_call($subroutine) { |
182
|
|
|
return sprintf('call %s;', $subroutine); |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
/** |
186
|
|
|
* Get the Magento admin frontname |
187
|
|
|
* |
188
|
|
|
* This is just the plain string, not in URL format. ex: |
189
|
|
|
* http://example.com/magento/admin -> admin |
190
|
|
|
* |
191
|
|
|
* @return string |
192
|
|
|
*/ |
193
|
|
|
protected function _getAdminFrontname() { |
194
|
|
|
if (Mage::getStoreConfig('admin/url/use_custom_path')) { |
195
|
|
|
if (Mage::getStoreConfig('web/url/use_store')) { |
196
|
|
|
return Mage::getModel('core/store')->load(0)->getCode()."/".Mage::getStoreConfig('admin/url/custom_path'); |
197
|
|
|
} else { |
198
|
|
|
return Mage::getStoreConfig('admin/url/custom_path'); |
199
|
|
|
} |
200
|
|
|
} else { |
201
|
|
|
return (string) Mage::getConfig()->getNode( |
202
|
|
|
'admin/routers/adminhtml/args/frontName' ); |
203
|
|
|
} |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
/** |
207
|
|
|
* Get the hostname for host normalization from Magento's base URL |
208
|
|
|
* |
209
|
|
|
* @return string |
210
|
|
|
*/ |
211
|
|
|
protected function _getNormalizeHostTarget() { |
212
|
|
|
$configHost = trim(Mage::getStoreConfig( |
213
|
|
|
'turpentine_vcl/normalization/host_target' )); |
214
|
|
|
if ($configHost) { |
215
|
|
|
return $configHost; |
216
|
|
|
} else { |
217
|
|
|
$baseUrl = parse_url(Mage::getBaseUrl()); |
218
|
|
|
if (isset($baseUrl['port'])) { |
219
|
|
|
return sprintf('%s:%d', $baseUrl['host'], $baseUrl['port']); |
220
|
|
|
} else { |
221
|
|
|
return $baseUrl['host']; |
222
|
|
|
} |
223
|
|
|
} |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
/** |
227
|
|
|
* Get hosts as regex |
228
|
|
|
* |
229
|
|
|
* ex: base_url: example.com |
230
|
|
|
* path_regex: (example.com|example.net) |
231
|
|
|
* |
232
|
|
|
* @return string |
233
|
|
|
*/ |
234
|
|
|
public function getAllowedHostsRegex() { |
235
|
|
|
$hosts = array(); |
236
|
|
|
foreach (Mage::app()->getStores() as $store) { |
237
|
|
|
$hosts[] = parse_url($store->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB, false), PHP_URL_HOST); |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
$hosts = array_values(array_unique($hosts)); |
241
|
|
|
|
242
|
|
|
$pattern = '('.implode('|', array_map("preg_quote", $hosts)).')'; |
243
|
|
|
return $pattern; |
244
|
|
|
} |
245
|
|
|
|
246
|
|
|
/** |
247
|
|
|
* Get the Host normalization sub routine |
248
|
|
|
* |
249
|
|
|
* @return string |
250
|
|
|
*/ |
251
|
|
|
protected function _vcl_sub_allowed_hosts_regex() { |
252
|
|
|
$tpl = <<<EOS |
253
|
|
|
# if host is not allowed in magento pass to backend |
254
|
|
|
if (req.http.host !~ "{{allowed_hosts_regex}}") { |
255
|
|
|
return (pass); |
256
|
|
|
} |
257
|
|
|
EOS; |
258
|
|
|
return $this->_formatTemplate($tpl, array( |
259
|
|
|
'allowed_hosts_regex' => $this->getAllowedHostsRegex() )); |
260
|
|
|
} |
261
|
|
|
|
262
|
|
|
/** |
263
|
|
|
* Get the base url path regex |
264
|
|
|
* |
265
|
|
|
* ex: base_url: http://example.com/magento/ |
266
|
|
|
* path_regex: /magento/(?:(?:index|litespeed)\.php/)? |
267
|
|
|
* |
268
|
|
|
* @return string |
269
|
|
|
*/ |
270
|
|
|
public function getBaseUrlPathRegex() { |
271
|
|
|
$pattern = '^(%s)(?:(?:index|litespeed)\\.php/)?'; |
272
|
|
|
return sprintf($pattern, implode('|', |
273
|
|
|
array_map(create_function('$x', 'return preg_quote($x,"|");'), |
274
|
|
|
$this->_getBaseUrlPaths()))); |
275
|
|
|
} |
276
|
|
|
|
277
|
|
|
/** |
278
|
|
|
* Get the path part of each store's base URL and static file URLs |
279
|
|
|
* |
280
|
|
|
* @return array |
281
|
|
|
*/ |
282
|
|
|
protected function _getBaseUrlPaths() { |
283
|
|
|
$paths = array(); |
284
|
|
|
$linkTypes = array(Mage_Core_Model_Store::URL_TYPE_LINK, |
285
|
|
|
Mage_Core_Model_Store::URL_TYPE_JS, |
286
|
|
|
Mage_Core_Model_Store::URL_TYPE_SKIN, |
287
|
|
|
Mage_Core_Model_Store::URL_TYPE_MEDIA); |
288
|
|
|
foreach (Mage::app()->getStores() as $store) { |
289
|
|
|
foreach ($linkTypes as $linkType) { |
290
|
|
|
$paths[] = parse_url($store->getBaseUrl($linkType, false), |
291
|
|
|
PHP_URL_PATH); |
292
|
|
|
$paths[] = parse_url($store->getBaseUrl($linkType, true), |
293
|
|
|
PHP_URL_PATH); |
294
|
|
|
} |
295
|
|
|
} |
296
|
|
|
$paths = array_unique($paths); |
297
|
|
|
usort($paths, create_function('$a, $b', |
298
|
|
|
'return strlen( $b ) - strlen( $a );')); |
299
|
|
|
return array_values($paths); |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
/** |
303
|
|
|
* Format the URL exclusions for insertion in a regex. Admin frontname and |
304
|
|
|
* API are automatically added. |
305
|
|
|
* |
306
|
|
|
* @return string |
307
|
|
|
*/ |
308
|
|
|
protected function _getUrlExcludes() { |
309
|
|
|
$urls = Mage::getStoreConfig('turpentine_vcl/urls/url_blacklist'); |
310
|
|
|
return implode('|', array_merge(array($this->_getAdminFrontname(), 'api'), |
311
|
|
|
Mage::helper('turpentine/data')->cleanExplode(PHP_EOL, $urls))); |
312
|
|
|
} |
313
|
|
|
|
314
|
|
|
/** |
315
|
|
|
* Get the default cache TTL from Magento config |
316
|
|
|
* |
317
|
|
|
* @return string |
318
|
|
|
*/ |
319
|
|
|
protected function _getDefaultTtl() { |
320
|
|
|
return Mage::helper('turpentine/varnish')->getDefaultTtl(); |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
/** |
324
|
|
|
* Get the default backend configuration string |
325
|
|
|
* |
326
|
|
|
* @return string |
327
|
|
|
*/ |
328
|
|
View Code Duplication |
protected function _getDefaultBackend() { |
|
|
|
|
329
|
|
|
$timeout = Mage::getStoreConfig('turpentine_vcl/backend/frontend_timeout'); |
330
|
|
|
$default_options = array( |
331
|
|
|
'first_byte_timeout' => $timeout.'s', |
332
|
|
|
'between_bytes_timeout' => $timeout.'s', |
333
|
|
|
); |
334
|
|
|
if (Mage::getStoreConfig('turpentine_vcl/backend/load_balancing') != 'no') { |
335
|
|
|
return $this->_vcl_director('default', $default_options); |
336
|
|
|
} else { |
337
|
|
|
return $this->_vcl_backend('default', |
338
|
|
|
Mage::getStoreConfig('turpentine_vcl/backend/backend_host'), |
339
|
|
|
Mage::getStoreConfig('turpentine_vcl/backend/backend_port'), |
340
|
|
|
$default_options); |
341
|
|
|
} |
342
|
|
|
} |
343
|
|
|
|
344
|
|
|
/** |
345
|
|
|
* Get the admin backend configuration string |
346
|
|
|
* |
347
|
|
|
* @return string |
348
|
|
|
*/ |
349
|
|
View Code Duplication |
protected function _getAdminBackend() { |
|
|
|
|
350
|
|
|
$timeout = Mage::getStoreConfig('turpentine_vcl/backend/admin_timeout'); |
351
|
|
|
$admin_options = array( |
352
|
|
|
'first_byte_timeout' => $timeout.'s', |
353
|
|
|
'between_bytes_timeout' => $timeout.'s', |
354
|
|
|
); |
355
|
|
|
if (Mage::getStoreConfig('turpentine_vcl/backend/load_balancing') != 'no') { |
356
|
|
|
return $this->_vcl_director('admin', $admin_options); |
357
|
|
|
} else { |
358
|
|
|
return $this->_vcl_backend('admin', |
359
|
|
|
Mage::getStoreConfig('turpentine_vcl/backend/backend_host'), |
360
|
|
|
Mage::getStoreConfig('turpentine_vcl/backend/backend_port'), |
361
|
|
|
$admin_options); |
362
|
|
|
} |
363
|
|
|
} |
364
|
|
|
|
365
|
|
|
/** |
366
|
|
|
* Get the grace period for vcl_fetch |
367
|
|
|
* |
368
|
|
|
* This is curently hardcoded to 15 seconds, will be configurable at some |
369
|
|
|
* point |
370
|
|
|
* |
371
|
|
|
* @return string |
372
|
|
|
*/ |
373
|
|
|
protected function _getGracePeriod() { |
374
|
|
|
return Mage::getStoreConfig('turpentine_vcl/ttls/grace_period'); |
375
|
|
|
} |
376
|
|
|
|
377
|
|
|
/** |
378
|
|
|
* Get whether debug headers should be enabled or not |
379
|
|
|
* |
380
|
|
|
* @return string |
381
|
|
|
*/ |
382
|
|
|
protected function _getEnableDebugHeaders() { |
383
|
|
|
return Mage::getStoreConfig('turpentine_varnish/general/varnish_debug') |
384
|
|
|
? 'true' : 'false'; |
385
|
|
|
} |
386
|
|
|
|
387
|
|
|
/** |
388
|
|
|
* Format the GET variable excludes for insertion in a regex |
389
|
|
|
* |
390
|
|
|
* @return string |
391
|
|
|
*/ |
392
|
|
|
protected function _getGetParamExcludes() { |
393
|
|
|
return implode('|', Mage::helper('turpentine/data')->cleanExplode(',', |
394
|
|
|
Mage::getStoreConfig('turpentine_vcl/params/get_params'))); |
395
|
|
|
} |
396
|
|
|
|
397
|
|
|
protected function _getIgnoreGetParameters() |
398
|
|
|
{ |
399
|
|
|
/** @var Nexcessnet_Turpentine_Helper_Data $helper */ |
400
|
|
|
$helper = Mage::helper('turpentine'); |
401
|
|
|
$ignoredParameters = $helper->cleanExplode(',', Mage::getStoreConfig('turpentine_vcl/params/ignore_get_params')); |
402
|
|
|
return implode('|', $ignoredParameters); |
403
|
|
|
} |
404
|
|
|
|
405
|
|
|
/** |
406
|
|
|
* @return boolean |
407
|
|
|
*/ |
408
|
|
|
protected function _sendUnModifiedUrlToBackend() |
409
|
|
|
{ |
410
|
|
|
return Mage::getStoreConfigFlag('turpentine_vcl/params/transfer_unmodified_url'); |
411
|
|
|
} |
412
|
|
|
|
413
|
|
|
/** |
414
|
|
|
* Get the Generate Session |
415
|
|
|
* |
416
|
|
|
* @return string |
417
|
|
|
*/ |
418
|
|
|
protected function _getGenerateSessionStart() { |
419
|
|
|
return Mage::getStoreConfig('turpentine_varnish/general/vcl_fix') |
420
|
|
|
? '/* -- REMOVED' : ''; |
421
|
|
|
} |
422
|
|
|
|
423
|
|
|
/** |
424
|
|
|
* Get the Generate Session |
425
|
|
|
* |
426
|
|
|
* @return string |
427
|
|
|
*/ |
428
|
|
|
protected function _getGenerateSessionEnd() { |
429
|
|
|
return Mage::getStoreConfig('turpentine_varnish/general/vcl_fix') |
430
|
|
|
? '-- */' : ''; |
431
|
|
|
} |
432
|
|
|
|
433
|
|
|
|
434
|
|
|
/** |
435
|
|
|
* Get the Generate Session |
436
|
|
|
* |
437
|
|
|
* @return string |
438
|
|
|
*/ |
439
|
|
|
protected function _getGenerateSession() { |
440
|
|
|
return Mage::getStoreConfigFlag('turpentine_varnish/general/vcl_fix') |
441
|
|
|
? 'return (pipe);' : 'call generate_session;'; |
442
|
|
|
} |
443
|
|
|
|
444
|
|
|
|
445
|
|
|
/** |
446
|
|
|
* Get the Generate Session Expires |
447
|
|
|
* |
448
|
|
|
* @return string |
449
|
|
|
*/ |
450
|
|
|
protected function _getGenerateSessionExpires() { |
451
|
|
|
return Mage::getStoreConfig('turpentine_varnish/general/vcl_fix') |
452
|
|
|
? '# call generate_session_expires' : 'call generate_session_expires;'; |
453
|
|
|
} |
454
|
|
|
|
455
|
|
|
/** |
456
|
|
|
* Get the Force Static Caching option |
457
|
|
|
* |
458
|
|
|
* @return string |
459
|
|
|
*/ |
460
|
|
|
protected function _getForceCacheStatic() { |
461
|
|
|
return Mage::getStoreConfig('turpentine_vcl/static/force_static') |
462
|
|
|
? 'true' : 'false'; |
463
|
|
|
} |
464
|
|
|
|
465
|
|
|
/** |
466
|
|
|
* Get the Force Static Caching option |
467
|
|
|
* |
468
|
|
|
* @return string |
469
|
|
|
*/ |
470
|
|
|
protected function _getSimpleHashStatic() { |
471
|
|
|
return Mage::getStoreConfig('turpentine_vcl/static/simple_hash') |
472
|
|
|
? 'true' : 'false'; |
473
|
|
|
} |
474
|
|
|
|
475
|
|
|
/** |
476
|
|
|
* Format the list of static cache extensions |
477
|
|
|
* |
478
|
|
|
* @return string |
479
|
|
|
*/ |
480
|
|
|
protected function _getStaticExtensions() { |
481
|
|
|
return implode('|', Mage::helper('turpentine/data')->cleanExplode(',', |
482
|
|
|
Mage::getStoreConfig('turpentine_vcl/static/exts'))); |
483
|
|
|
} |
484
|
|
|
|
485
|
|
|
/** |
486
|
|
|
* Get the static caching TTL |
487
|
|
|
* |
488
|
|
|
* @return string |
489
|
|
|
*/ |
490
|
|
|
protected function _getStaticTtl() { |
491
|
|
|
return Mage::getStoreConfig('turpentine_vcl/ttls/static_ttl'); |
492
|
|
|
} |
493
|
|
|
|
494
|
|
|
/** |
495
|
|
|
* Format the by-url TTL value list |
496
|
|
|
* |
497
|
|
|
* @return string |
498
|
|
|
*/ |
499
|
|
|
protected function _getUrlTtls() { |
500
|
|
|
$str = array(); |
501
|
|
|
$configTtls = Mage::helper('turpentine/data')->cleanExplode(PHP_EOL, |
502
|
|
|
Mage::getStoreConfig('turpentine_vcl/ttls/url_ttls')); |
503
|
|
|
$ttls = array(); |
504
|
|
|
foreach ($configTtls as $line) { |
505
|
|
|
$ttls[] = explode(',', trim($line)); |
506
|
|
|
} |
507
|
|
|
foreach ($ttls as $ttl) { |
508
|
|
|
$str[] = sprintf('if (bereq.url ~ "%s%s") { set beresp.ttl = %ds; }', |
509
|
|
|
$this->getBaseUrlPathRegex(), $ttl[0], $ttl[1]); |
510
|
|
|
} |
511
|
|
|
$str = implode(' else ', $str); |
512
|
|
|
if ($str) { |
513
|
|
|
$str .= sprintf(' else { set beresp.ttl = %ds; }', |
514
|
|
|
$this->_getDefaultTtl()); |
515
|
|
|
} else { |
516
|
|
|
$str = sprintf('set beresp.ttl = %ds;', $this->_getDefaultTtl()); |
517
|
|
|
} |
518
|
|
|
return $str; |
519
|
|
|
} |
520
|
|
|
|
521
|
|
|
/** |
522
|
|
|
* Get the Enable Caching value |
523
|
|
|
* |
524
|
|
|
* @return string |
525
|
|
|
*/ |
526
|
|
|
protected function _getEnableCaching() { |
527
|
|
|
return Mage::helper('turpentine/varnish')->getVarnishEnabled() ? |
528
|
|
|
'true' : 'false'; |
529
|
|
|
} |
530
|
|
|
|
531
|
|
|
/** |
532
|
|
|
* Get the list of allowed debug IPs |
533
|
|
|
* |
534
|
|
|
* @return array |
535
|
|
|
*/ |
536
|
|
|
protected function _getDebugIps() { |
537
|
|
|
return Mage::helper('turpentine/data')->cleanExplode(',', |
538
|
|
|
Mage::getStoreConfig('dev/restrict/allow_ips')); |
539
|
|
|
} |
540
|
|
|
|
541
|
|
|
/** |
542
|
|
|
* Get the list of crawler IPs |
543
|
|
|
* |
544
|
|
|
* @return array |
545
|
|
|
*/ |
546
|
|
|
protected function _getCrawlerIps() { |
547
|
|
|
return Mage::helper('turpentine/data')->cleanExplode(',', |
548
|
|
|
Mage::getStoreConfig('turpentine_vcl/backend/crawlers')); |
549
|
|
|
} |
550
|
|
|
|
551
|
|
|
/** |
552
|
|
|
* Get the regex formatted list of crawler user agents |
553
|
|
|
* |
554
|
|
|
* @return string |
555
|
|
|
*/ |
556
|
|
|
protected function _getCrawlerUserAgents() { |
557
|
|
|
return implode('|', Mage::helper('turpentine/data') |
558
|
|
|
->cleanExplode(',', |
559
|
|
|
Mage::getStoreConfig( |
560
|
|
|
'turpentine_vcl/backend/crawler_user_agents' ))); |
561
|
|
|
} |
562
|
|
|
|
563
|
|
|
/** |
564
|
|
|
* Get the time to increase a cached objects TTL on cache hit (in seconds). |
565
|
|
|
* |
566
|
|
|
* This should be set very low since it gets added to every hit. |
567
|
|
|
* |
568
|
|
|
* @return string |
569
|
|
|
*/ |
570
|
|
|
protected function _getLruFactor() { |
571
|
|
|
return Mage::getStoreConfig('turpentine_vcl/ttls/lru_factor'); |
572
|
|
|
} |
573
|
|
|
|
574
|
|
|
/** |
575
|
|
|
* Get the advanced session validation restrictions |
576
|
|
|
* |
577
|
|
|
* Note that if User-Agent Normalization is on then the normalized user-agent |
578
|
|
|
* is used for user-agent validation instead of the full user-agent |
579
|
|
|
* |
580
|
|
|
* @return string |
581
|
|
|
*/ |
582
|
|
|
protected function _getAdvancedSessionValidationTargets() { |
583
|
|
|
$validation = array(); |
584
|
|
|
if (Mage::getStoreConfig('web/session/use_remote_addr')) { |
585
|
|
|
$validation[] = 'client.ip'; |
586
|
|
|
} |
587
|
|
|
if (Mage::getStoreConfig('web/session/use_http_via')) { |
588
|
|
|
$validation[] = 'req.http.Via'; |
589
|
|
|
} |
590
|
|
|
if (Mage::getStoreConfig('web/session/use_http_x_forwarded_for')) { |
591
|
|
|
$validation[] = 'req.http.X-Forwarded-For'; |
592
|
|
|
} |
593
|
|
|
if (Mage::getStoreConfig( |
594
|
|
|
'web/session/use_http_user_agent' ) && |
595
|
|
|
! Mage::getStoreConfig( |
596
|
|
|
'turpentine_vcl/normalization/user_agent' )) { |
597
|
|
|
$validation[] = 'req.http.User-Agent'; |
598
|
|
|
} |
599
|
|
|
return $validation; |
600
|
|
|
} |
601
|
|
|
|
602
|
|
|
/** |
603
|
|
|
* Remove empty and commented out lines from the generated VCL |
604
|
|
|
* |
605
|
|
|
* @param string $dirtyVcl generated vcl |
606
|
|
|
* @return string |
607
|
|
|
*/ |
608
|
|
|
protected function _cleanVcl($dirtyVcl) { |
609
|
|
|
return implode(PHP_EOL, |
610
|
|
|
array_filter( |
611
|
|
|
Mage::helper('turpentine/data') |
612
|
|
|
->cleanExplode(PHP_EOL, $dirtyVcl), |
613
|
|
|
array($this, '_cleanVclHelper') |
614
|
|
|
) |
615
|
|
|
); |
616
|
|
|
} |
617
|
|
|
|
618
|
|
|
/** |
619
|
|
|
* Helper to filter out blank/commented lines for VCL cleaning |
620
|
|
|
* |
621
|
|
|
* @param string $line |
622
|
|
|
* @return bool |
623
|
|
|
*/ |
624
|
|
|
protected function _cleanVclHelper($line) { |
625
|
|
|
return $line && |
626
|
|
|
((substr($line, 0, 1) != '#' && |
627
|
|
|
substr($line, 0, 2) != '//') || |
628
|
|
|
substr($line, 0, 8) == '#include'); |
629
|
|
|
} |
630
|
|
|
|
631
|
|
|
/** |
632
|
|
|
* Format a VCL backend declaration |
633
|
|
|
* |
634
|
|
|
* @param string $name name of the backend |
635
|
|
|
* @param string $host backend host |
636
|
|
|
* @param string $port backend port |
637
|
|
|
* @param array $options options |
638
|
|
|
* @return string |
639
|
|
|
*/ |
640
|
|
|
protected function _vcl_backend($name, $host, $port, $options = array()) { |
641
|
|
|
$tpl = <<<EOS |
642
|
|
|
backend {{name}} { |
643
|
|
|
.host = "{{host}}"; |
644
|
|
|
.port = "{{port}}"; |
645
|
|
|
|
646
|
|
|
EOS; |
647
|
|
|
$vars = array( |
648
|
|
|
'host' => $host, |
649
|
|
|
'port' => $port, |
650
|
|
|
'name' => $name, |
651
|
|
|
); |
652
|
|
|
$str = $this->_formatTemplate($tpl, $vars); |
653
|
|
|
foreach ($options as $key => $value) { |
654
|
|
|
$str .= sprintf(' .%s = %s;', $key, $value).PHP_EOL; |
655
|
|
|
} |
656
|
|
|
$str .= '}'.PHP_EOL; |
657
|
|
|
return $str; |
658
|
|
|
} |
659
|
|
|
|
660
|
|
|
/** |
661
|
|
|
* Format a VCL director declaration, for load balancing |
662
|
|
|
* |
663
|
|
|
* @param string $name name of the director, also used to select config settings |
664
|
|
|
* @param array $backendOptions options for each backend |
665
|
|
|
* @return string |
666
|
|
|
*/ |
667
|
|
View Code Duplication |
protected function _vcl_director($name, $backendOptions) { |
|
|
|
|
668
|
|
|
$tpl = <<<EOS |
669
|
|
|
director {{name}} round-robin { |
670
|
|
|
{{backends}} |
671
|
|
|
} |
672
|
|
|
EOS; |
673
|
|
|
if ('admin' == $name && 'yes_admin' == Mage::getStoreConfig('turpentine_vcl/backend/load_balancing')) { |
674
|
|
|
$backendNodes = Mage::helper('turpentine/data')->cleanExplode(PHP_EOL, |
675
|
|
|
Mage::getStoreConfig('turpentine_vcl/backend/backend_nodes_admin')); |
676
|
|
|
$probeUrl = Mage::getStoreConfig('turpentine_vcl/backend/backend_probe_url_admin'); |
677
|
|
|
$prefix = 'admin'; |
678
|
|
|
} else { |
679
|
|
|
$backendNodes = Mage::helper('turpentine/data')->cleanExplode(PHP_EOL, |
680
|
|
|
Mage::getStoreConfig('turpentine_vcl/backend/backend_nodes')); |
681
|
|
|
$probeUrl = Mage::getStoreConfig('turpentine_vcl/backend/backend_probe_url'); |
682
|
|
|
if ('admin' == $name) { |
683
|
|
|
$prefix = 'admin'; |
684
|
|
|
} else { |
685
|
|
|
$prefix = ''; |
686
|
|
|
} |
687
|
|
|
} |
688
|
|
|
$backends = ''; |
689
|
|
|
$number = 0; |
690
|
|
|
foreach ($backendNodes as $backendNode) { |
691
|
|
|
$parts = explode(':', $backendNode, 2); |
692
|
|
|
$host = (empty($parts[0])) ? '127.0.0.1' : $parts[0]; |
693
|
|
|
$port = (empty($parts[1])) ? '80' : $parts[1]; |
694
|
|
|
$backends .= $this->_vcl_director_backend($host, $port, $prefix.$number, $probeUrl, $backendOptions); |
695
|
|
|
$number++; |
696
|
|
|
} |
697
|
|
|
$vars = array( |
698
|
|
|
'name' => $name, |
699
|
|
|
'backends' => $backends |
700
|
|
|
); |
701
|
|
|
return $this->_formatTemplate($tpl, $vars); |
702
|
|
|
} |
703
|
|
|
|
704
|
|
|
/** |
705
|
|
|
* Format a VCL backend declaration to put inside director |
706
|
|
|
* |
707
|
|
|
* @param string $host backend host |
708
|
|
|
* @param string $port backend port |
709
|
|
|
* @param string $descriptor backend descriptor |
710
|
|
|
* @param string $probeUrl URL to check if backend is up |
711
|
|
|
* @param array $options extra options for backend |
712
|
|
|
* @return string |
713
|
|
|
*/ |
714
|
|
View Code Duplication |
protected function _vcl_director_backend($host, $port, $descriptor = '', $probeUrl = '', $options = array()) { |
|
|
|
|
715
|
|
|
$tpl = <<<EOS |
716
|
|
|
{ |
717
|
|
|
.backend {$descriptor} = { |
718
|
|
|
.host = "{{host}}"; |
719
|
|
|
.port = "{{port}}"; |
720
|
|
|
{{probe}} |
721
|
|
|
|
722
|
|
|
EOS; |
723
|
|
|
$vars = array( |
724
|
|
|
'host' => $host, |
725
|
|
|
'port' => $port, |
726
|
|
|
'probe' => '' |
727
|
|
|
); |
728
|
|
|
if ( ! empty($probeUrl)) { |
729
|
|
|
$vars['probe'] = $this->_vcl_get_probe($probeUrl); |
730
|
|
|
} |
731
|
|
|
$str = $this->_formatTemplate($tpl, $vars); |
732
|
|
|
foreach ($options as $key => $value) { |
733
|
|
|
$str .= sprintf(' .%s = %s;', $key, $value).PHP_EOL; |
734
|
|
|
} |
735
|
|
|
$str .= <<<EOS |
736
|
|
|
} |
737
|
|
|
} |
738
|
|
|
EOS; |
739
|
|
|
return $str; |
740
|
|
|
} |
741
|
|
|
|
742
|
|
|
/** |
743
|
|
|
* Format a VCL probe declaration to put in backend which is in director |
744
|
|
|
* |
745
|
|
|
* @param string $probeUrl URL to check if backend is up |
746
|
|
|
* |
747
|
|
|
* @return string |
748
|
|
|
*/ |
749
|
|
|
protected function _vcl_get_probe($probeUrl) { |
750
|
|
|
$urlParts = parse_url($probeUrl); |
751
|
|
|
if (empty($urlParts)) { |
752
|
|
|
// Malformed URL |
753
|
|
|
return ''; |
754
|
|
|
} else { |
755
|
|
|
$tpl = <<<EOS |
756
|
|
|
.probe = { |
757
|
|
|
.timeout = {{timeout}}; |
758
|
|
|
.interval = {{interval}}; |
759
|
|
|
.window = {{window}}; |
760
|
|
|
.threshold = {{threshold}}; |
761
|
|
|
.request = |
762
|
|
|
"GET {{probe_path}} HTTP/1.1" |
763
|
|
|
"Host: {{probe_host}}" |
764
|
|
|
"Connection: close"; |
765
|
|
|
} |
766
|
|
|
EOS; |
767
|
|
|
|
768
|
|
|
$timeout = Mage::getStoreConfig('turpentine_vcl/backend/backend_probe_timeout'); |
769
|
|
|
$interval = Mage::getStoreConfig('turpentine_vcl/backend/backend_probe_interval'); |
770
|
|
|
$window = Mage::getStoreConfig('turpentine_vcl/backend/backend_probe_window'); |
771
|
|
|
$threshold = Mage::getStoreConfig('turpentine_vcl/backend/backend_probe_threshold'); |
772
|
|
|
|
773
|
|
|
return $this->_formatTemplate($tpl, array( |
774
|
|
|
'probe_host' => $urlParts['host'], |
775
|
|
|
'probe_path' => $urlParts['path'], |
776
|
|
|
'timeout' => $timeout, |
777
|
|
|
'interval' => $interval, |
778
|
|
|
'window' => $window, |
779
|
|
|
'threshold' => $threshold, |
780
|
|
|
)); |
781
|
|
|
} |
782
|
|
|
} |
783
|
|
|
|
784
|
|
|
/** |
785
|
|
|
* Format a VCL ACL declaration |
786
|
|
|
* |
787
|
|
|
* @param string $name ACL name |
788
|
|
|
* @param array $hosts list of hosts to add to the ACL |
789
|
|
|
* @return string |
790
|
|
|
*/ |
791
|
|
|
protected function _vcl_acl($name, array $hosts) { |
792
|
|
|
$tpl = <<<EOS |
793
|
|
|
acl {{name}} { |
794
|
|
|
{{hosts}} |
795
|
|
|
} |
796
|
|
|
EOS; |
797
|
|
|
$fmtHost = create_function('$h', 'return sprintf(\'"%s";\',$h);'); |
798
|
|
|
$vars = array( |
799
|
|
|
'name' => $name, |
800
|
|
|
'hosts' => implode("\n ", array_map($fmtHost, $hosts)), |
801
|
|
|
); |
802
|
|
|
return $this->_formatTemplate($tpl, $vars); |
803
|
|
|
} |
804
|
|
|
|
805
|
|
|
/** |
806
|
|
|
* Get the User-Agent normalization sub routine |
807
|
|
|
* |
808
|
|
|
* @return string |
809
|
|
|
*/ |
810
|
|
|
protected function _vcl_sub_normalize_user_agent() { |
811
|
|
|
/** |
812
|
|
|
* Mobile regex from |
813
|
|
|
* @link http://magebase.com/magento-tutorials/magento-design-exceptions-explained/ |
814
|
|
|
*/ |
815
|
|
|
$tpl = <<<EOS |
816
|
|
|
if (req.http.User-Agent ~ "iP(?:hone|ad|od)|BlackBerry|Palm|Googlebot-Mobile|Mobile|mobile|mobi|Windows Mobile|Safari Mobile|Android|Opera (?:Mini|Mobi)") { |
817
|
|
|
set req.http.X-Normalized-User-Agent = "mobile"; |
818
|
|
|
} else { |
819
|
|
|
set req.http.X-Normalized-User-Agent = "other"; |
820
|
|
|
} |
821
|
|
|
|
822
|
|
|
EOS; |
823
|
|
|
return $tpl; |
824
|
|
|
} |
825
|
|
|
|
826
|
|
|
/** |
827
|
|
|
* Get the Accept-Encoding normalization sub routine |
828
|
|
|
* |
829
|
|
|
* @return string |
830
|
|
|
*/ |
831
|
|
|
protected function _vcl_sub_normalize_encoding() { |
832
|
|
|
$tpl = <<<EOS |
833
|
|
|
if (req.http.Accept-Encoding) { |
834
|
|
|
if (req.http.Accept-Encoding ~ "\*|gzip") { |
835
|
|
|
set req.http.Accept-Encoding = "gzip"; |
836
|
|
|
} else if (req.http.Accept-Encoding ~ "deflate") { |
837
|
|
|
set req.http.Accept-Encoding = "deflate"; |
838
|
|
|
} else { |
839
|
|
|
# unknown algorithm |
840
|
|
|
unset req.http.Accept-Encoding; |
841
|
|
|
} |
842
|
|
|
} |
843
|
|
|
|
844
|
|
|
EOS; |
845
|
|
|
return $tpl; |
846
|
|
|
} |
847
|
|
|
|
848
|
|
|
/** |
849
|
|
|
* Get the Host normalization sub routine |
850
|
|
|
* |
851
|
|
|
* @return string |
852
|
|
|
*/ |
853
|
|
|
protected function _vcl_sub_normalize_host() { |
854
|
|
|
$tpl = <<<EOS |
855
|
|
|
set req.http.Host = "{{normalize_host_target}}"; |
856
|
|
|
|
857
|
|
|
EOS; |
858
|
|
|
return $this->_formatTemplate($tpl, array( |
859
|
|
|
'normalize_host_target' => $this->_getNormalizeHostTarget() )); |
860
|
|
|
} |
861
|
|
|
|
862
|
|
|
/** |
863
|
|
|
* Get the hostname for cookie normalization |
864
|
|
|
* |
865
|
|
|
* @return string |
866
|
|
|
*/ |
867
|
|
|
protected function _getNormalizeCookieTarget() { |
868
|
|
|
return trim(Mage::getStoreConfig( |
869
|
|
|
'turpentine_vcl/normalization/cookie_target' )); |
870
|
|
|
} |
871
|
|
|
|
872
|
|
|
/** |
873
|
|
|
* Get the regex for cookie normalization |
874
|
|
|
* |
875
|
|
|
* @return string |
876
|
|
|
*/ |
877
|
|
|
protected function _getNormalizeCookieRegex() { |
878
|
|
|
return trim(Mage::getStoreConfig( |
879
|
|
|
'turpentine_vcl/normalization/cookie_regex' )); |
880
|
|
|
} |
881
|
|
|
|
882
|
|
|
/** |
883
|
|
|
* Get the allowed IPs when in maintenance mode |
884
|
|
|
* |
885
|
|
|
* @return string |
886
|
|
|
*/ |
887
|
|
View Code Duplication |
protected function _vcl_sub_maintenance_allowed_ips() { |
|
|
|
|
888
|
|
|
if (( ! $this->_getDebugIps()) || ! Mage::getStoreConfig('turpentine_vcl/maintenance/custom_vcl_synth')) { |
889
|
|
|
return false; |
890
|
|
|
} |
891
|
|
|
|
892
|
|
|
switch (Mage::getStoreConfig('turpentine_varnish/servers/version')) { |
893
|
|
|
case 4.0: |
894
|
|
|
case 4.1: |
895
|
|
|
$tpl = <<<EOS |
896
|
|
|
if (req.http.X-Forwarded-For) { |
897
|
|
|
if (req.http.X-Forwarded-For !~ "{{debug_ips}}") { |
898
|
|
|
return (synth(999, "Maintenance mode")); |
899
|
|
|
} |
900
|
|
|
} |
901
|
|
|
else { |
902
|
|
|
if (client.ip !~ debug_acl) { |
903
|
|
|
return (synth(999, "Maintenance mode")); |
904
|
|
|
} |
905
|
|
|
} |
906
|
|
|
|
907
|
|
|
EOS; |
908
|
|
|
break; |
909
|
|
|
default: |
910
|
|
|
$tpl = <<<EOS |
911
|
|
|
if (req.http.X-Forwarded-For) { |
912
|
|
|
if(req.http.X-Forwarded-For !~ "{{debug_ips}}") { |
913
|
|
|
error 503; |
914
|
|
|
} |
915
|
|
|
} else { |
916
|
|
|
if (client.ip !~ debug_acl) { |
917
|
|
|
error 503; |
918
|
|
|
} |
919
|
|
|
} |
920
|
|
|
EOS; |
921
|
|
|
} |
922
|
|
|
|
923
|
|
|
return $this->_formatTemplate($tpl, array( |
924
|
|
|
'debug_ips' => Mage::getStoreConfig('dev/restrict/allow_ips') )); |
925
|
|
|
} |
926
|
|
|
|
927
|
|
|
/** |
928
|
|
|
* When using Varnish on port 80 and Hitch listen on port 443 for HTTPS, the fix will set X-Forwarded-Proto to HTTPS to prevent redirect loop. |
929
|
|
|
* |
930
|
|
|
* @return string |
931
|
|
|
*/ |
932
|
|
|
protected function _vcl_sub_https_proto_fix() { |
933
|
|
|
$tpl = <<<EOS |
934
|
|
|
if (std.port(server.ip) == 443) { |
935
|
|
|
set req.http.X-Forwarded-Proto = "https"; |
936
|
|
|
} |
937
|
|
|
EOS; |
938
|
|
|
return $tpl; |
939
|
|
|
} |
940
|
|
|
|
941
|
|
|
/** |
942
|
|
|
* When using Varnish as front door listen on port 80 and Nginx/Apache listen on port 443 for HTTPS, the fix will keep the url parameters when redirect from HTTP to HTTPS. |
943
|
|
|
* |
944
|
|
|
* @return string |
945
|
|
|
*/ |
946
|
|
|
protected function _vcl_sub_https_redirect_fix() { |
947
|
|
|
|
948
|
|
|
$hostRegex = array(); |
949
|
|
|
foreach ($this->_getHostNames() as $host) { |
950
|
|
|
$hostRegex[] = 'req.http.host ~ "^(?i)'.$host.'"'; |
951
|
|
|
} |
952
|
|
|
$hostRegex = implode(' || ', $hostRegex); |
953
|
|
|
|
954
|
|
|
switch (Mage::getStoreConfig('turpentine_varnish/servers/version')) { |
955
|
|
|
case 4.0: |
956
|
|
|
case 4.1: |
957
|
|
|
$tpl = <<<EOS |
958
|
|
|
if ( ($hostRegex) && req.http.X-Forwarded-Proto !~ "(?i)https") { |
959
|
|
|
return (synth(750, "")); |
960
|
|
|
} |
961
|
|
|
EOS; |
962
|
|
|
break; |
963
|
|
|
default: |
964
|
|
|
$tpl = <<<EOS |
965
|
|
|
if ( ($hostRegex) && req.http.X-Forwarded-Proto !~ "(?i)https") { |
966
|
|
|
error 750 "https://" + req.http.host + req.url; |
967
|
|
|
} |
968
|
|
|
EOS; |
969
|
|
|
} |
970
|
|
|
|
971
|
|
|
return $tpl; |
972
|
|
|
} |
973
|
|
|
|
974
|
|
|
|
975
|
|
|
protected function _getHostNames() { |
976
|
|
|
|
977
|
|
|
$baseUrl = $this->_stripHost(Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB)); |
978
|
|
|
$hosts = array( |
979
|
|
|
$baseUrl => $baseUrl |
980
|
|
|
); |
981
|
|
|
|
982
|
|
|
foreach (Mage::app()->getWebsites() as $website) { |
983
|
|
|
foreach ($website->getGroups() as $group) { |
984
|
|
|
$stores = $group->getStores(); |
985
|
|
|
foreach ($stores as $store) { |
986
|
|
|
$baseUrl = $this->_stripHost(Mage::getStoreConfig('web/unsecure/base_url', $store->getId())); |
987
|
|
|
$secureBaseUrl = $this->_stripHost(Mage::getStoreConfig('web/secure/base_url', $store->getId())); |
988
|
|
|
|
989
|
|
|
$hosts[$baseUrl] = $baseUrl; |
990
|
|
|
$hosts[$secureBaseUrl] = $secureBaseUrl; |
991
|
|
|
} |
992
|
|
|
} |
993
|
|
|
} |
994
|
|
|
|
995
|
|
|
return $hosts; |
996
|
|
|
} |
997
|
|
|
|
998
|
|
|
protected function _stripHost ($baseUrl){ |
999
|
|
|
return rtrim(str_replace(array('http://', 'https://'), '', $baseUrl), '/'); |
1000
|
|
|
} |
1001
|
|
|
|
1002
|
|
|
/** |
1003
|
|
|
* Get the allowed IPs when in maintenance mode |
1004
|
|
|
* |
1005
|
|
|
* @return string |
1006
|
|
|
*/ |
1007
|
|
View Code Duplication |
protected function _vcl_sub_synth() |
|
|
|
|
1008
|
|
|
{ |
1009
|
|
|
if (( ! $this->_getDebugIps()) || ! Mage::getStoreConfig('turpentine_vcl/maintenance/custom_vcl_synth')) { |
1010
|
|
|
return false; |
1011
|
|
|
} |
1012
|
|
|
|
1013
|
|
|
switch (Mage::getStoreConfig('turpentine_varnish/servers/version')) { |
1014
|
|
|
case 4.0: |
1015
|
|
|
case 4.1: |
1016
|
|
|
$tpl = <<<EOS |
1017
|
|
|
sub vcl_synth { |
1018
|
|
|
if (resp.status == 999) { |
1019
|
|
|
set resp.status = 503; |
1020
|
|
|
set resp.http.Content-Type = "text/html; charset=utf-8"; |
1021
|
|
|
synthetic({"{{vcl_synth_content}}"}); |
1022
|
|
|
return (deliver); |
1023
|
|
|
} |
1024
|
|
|
return (deliver); |
1025
|
|
|
} |
1026
|
|
|
|
1027
|
|
|
EOS; |
1028
|
|
|
break; |
1029
|
|
|
default: |
1030
|
|
|
$tpl = <<<EOS |
1031
|
|
|
sub vcl_error { |
1032
|
|
|
set obj.http.Content-Type = "text/html; charset=utf-8"; |
1033
|
|
|
synthetic {"{{vcl_synth_content}}"}; |
1034
|
|
|
return (deliver); |
1035
|
|
|
} |
1036
|
|
|
EOS; |
1037
|
|
|
} |
1038
|
|
|
|
1039
|
|
|
return $this->_formatTemplate($tpl, array( |
1040
|
|
|
'vcl_synth_content' => Mage::getStoreConfig('turpentine_vcl/maintenance/custom_vcl_synth'))); |
1041
|
|
|
} |
1042
|
|
|
|
1043
|
|
|
/** |
1044
|
|
|
* vcl_synth for fixing https |
1045
|
|
|
* |
1046
|
|
|
* @return string |
1047
|
|
|
*/ |
1048
|
|
|
protected function _vcl_sub_synth_https_fix() |
1049
|
|
|
{ |
1050
|
|
|
$tpl = $this->_vcl_sub_synth(); |
1051
|
|
|
|
1052
|
|
|
if ( ! $tpl) { |
|
|
|
|
1053
|
|
|
$tpl = <<<EOS |
1054
|
|
|
sub vcl_synth { |
1055
|
|
|
if (resp.status == 750) { |
1056
|
|
|
set resp.status = 301; |
1057
|
|
|
set resp.http.Location = "https://" + req.http.host + req.url; |
1058
|
|
|
return(deliver); |
1059
|
|
|
} |
1060
|
|
|
} |
1061
|
|
|
EOS; |
1062
|
|
|
} else{ |
1063
|
|
|
$tpl_750 = ' |
1064
|
|
|
sub vcl_synth { |
1065
|
|
|
if (resp.status == 750) { |
1066
|
|
|
set resp.status = 301; |
1067
|
|
|
set resp.http.Location = "https://" + req.http.host + req.url; |
1068
|
|
|
return(deliver); |
1069
|
|
|
}'; |
1070
|
|
|
|
1071
|
|
|
$tpl = str_ireplace('sub vcl_synth {', $tpl_750, $tpl); |
1072
|
|
|
} |
1073
|
|
|
|
1074
|
|
|
return $tpl; |
1075
|
|
|
} |
1076
|
|
|
|
1077
|
|
|
|
1078
|
|
|
|
1079
|
|
|
/** |
1080
|
|
|
* Build the list of template variables to apply to the VCL template |
1081
|
|
|
* |
1082
|
|
|
* @return array |
1083
|
|
|
*/ |
1084
|
|
|
protected function _getTemplateVars() { |
1085
|
|
|
$vars = array( |
1086
|
|
|
'default_backend' => $this->_getDefaultBackend(), |
1087
|
|
|
'admin_backend' => $this->_getAdminBackend(), |
1088
|
|
|
'admin_frontname' => $this->_getAdminFrontname(), |
1089
|
|
|
'normalize_host_target' => $this->_getNormalizeHostTarget(), |
1090
|
|
|
'url_base_regex' => $this->getBaseUrlPathRegex(), |
1091
|
|
|
'allowed_hosts_regex' => $this->getAllowedHostsRegex(), |
1092
|
|
|
'url_excludes' => $this->_getUrlExcludes(), |
1093
|
|
|
'get_param_excludes' => $this->_getGetParamExcludes(), |
1094
|
|
|
'get_param_ignored' => $this->_getIgnoreGetParameters(), |
1095
|
|
|
'default_ttl' => $this->_getDefaultTtl(), |
1096
|
|
|
'enable_get_excludes' => ($this->_getGetParamExcludes() ? 'true' : 'false'), |
1097
|
|
|
'enable_get_ignored' => ($this->_getIgnoreGetParameters() ? 'true' : 'false'), |
1098
|
|
|
'send_unmodified_url' => ($this->_sendUnModifiedUrlToBackend() ? 'true' : 'false'), |
1099
|
|
|
'debug_headers' => $this->_getEnableDebugHeaders(), |
1100
|
|
|
'grace_period' => $this->_getGracePeriod(), |
1101
|
|
|
'force_cache_static' => $this->_getForceCacheStatic(), |
1102
|
|
|
'simple_hash_static' => $this->_getSimpleHashStatic(), |
1103
|
|
|
'generate_session_expires' => $this->_getGenerateSessionExpires(), |
1104
|
|
|
'generate_session' => $this->_getGenerateSession(), |
1105
|
|
|
'generate_session_start' => $this->_getGenerateSessionStart(), |
1106
|
|
|
'generate_session_end' => $this->_getGenerateSessionEnd(), |
1107
|
|
|
'static_extensions' => $this->_getStaticExtensions(), |
1108
|
|
|
'static_ttl' => $this->_getStaticTtl(), |
1109
|
|
|
'url_ttls' => $this->_getUrlTtls(), |
1110
|
|
|
'enable_caching' => $this->_getEnableCaching(), |
1111
|
|
|
'crawler_acl' => $this->_vcl_acl('crawler_acl', |
1112
|
|
|
$this->_getCrawlerIps()), |
1113
|
|
|
'esi_cache_type_param' => |
1114
|
|
|
Mage::helper('turpentine/esi')->getEsiCacheTypeParam(), |
1115
|
|
|
'esi_method_param' => |
1116
|
|
|
Mage::helper('turpentine/esi')->getEsiMethodParam(), |
1117
|
|
|
'esi_ttl_param' => Mage::helper('turpentine/esi')->getEsiTtlParam(), |
1118
|
|
|
'secret_handshake' => Mage::helper('turpentine/varnish') |
1119
|
|
|
->getSecretHandshake(), |
1120
|
|
|
'crawler_user_agent_regex' => $this->_getCrawlerUserAgents(), |
1121
|
|
|
// 'lru_factor' => $this->_getLruFactor(), |
1122
|
|
|
'debug_acl' => $this->_vcl_acl('debug_acl', |
1123
|
|
|
$this->_getDebugIps()), |
1124
|
|
|
'custom_c_code' => file_get_contents( |
1125
|
|
|
$this->_getVclTemplateFilename(self::VCL_CUSTOM_C_CODE_FILE) ), |
1126
|
|
|
'esi_private_ttl' => Mage::helper('turpentine/esi') |
1127
|
|
|
->getDefaultEsiTtl(), |
1128
|
|
|
); |
1129
|
|
|
|
1130
|
|
|
if ((bool) Mage::getStoreConfig('turpentine_vcl/urls/bypass_cache_store_url')) { |
1131
|
|
|
$vars['allowed_hosts'] = $this->_vcl_sub_allowed_hosts_regex(); |
1132
|
|
|
} |
1133
|
|
|
|
1134
|
|
|
if (Mage::getStoreConfig('turpentine_vcl/normalization/encoding')) { |
1135
|
|
|
$vars['normalize_encoding'] = $this->_vcl_sub_normalize_encoding(); |
1136
|
|
|
} |
1137
|
|
|
if (Mage::getStoreConfig('turpentine_vcl/normalization/user_agent')) { |
1138
|
|
|
$vars['normalize_user_agent'] = $this->_vcl_sub_normalize_user_agent(); |
1139
|
|
|
} |
1140
|
|
|
if (Mage::getStoreConfig('turpentine_vcl/normalization/host')) { |
1141
|
|
|
$vars['normalize_host'] = $this->_vcl_sub_normalize_host(); |
1142
|
|
|
} |
1143
|
|
|
if (Mage::getStoreConfig('turpentine_vcl/normalization/cookie_regex')) { |
1144
|
|
|
$vars['normalize_cookie_regex'] = $this->_getNormalizeCookieRegex(); |
1145
|
|
|
} |
1146
|
|
|
if (Mage::getStoreConfig('turpentine_vcl/normalization/cookie_target')) { |
1147
|
|
|
$vars['normalize_cookie_target'] = $this->_getNormalizeCookieTarget(); |
1148
|
|
|
} |
1149
|
|
|
|
1150
|
|
|
if (Mage::getStoreConfig('turpentine_vcl/maintenance/enable')) { |
1151
|
|
|
// in vcl_recv set the allowed IPs otherwise load the vcl_error (v3)/vcl_synth (v4) |
1152
|
|
|
$vars['maintenance_allowed_ips'] = $this->_vcl_sub_maintenance_allowed_ips(); |
1153
|
|
|
// set the vcl_error from Magento database |
1154
|
|
|
$vars['vcl_synth'] = $this->_vcl_sub_synth(); |
1155
|
|
|
} |
1156
|
|
|
|
1157
|
|
|
if (Mage::getStoreConfig('turpentine_varnish/general/https_proto_fix')) { |
1158
|
|
|
$vars['https_proto_fix'] = $this->_vcl_sub_https_proto_fix(); |
1159
|
|
|
} |
1160
|
|
|
|
1161
|
|
|
if (Mage::getStoreConfig('turpentine_varnish/general/https_redirect_fix')) { |
1162
|
|
|
$vars['https_redirect'] = $this->_vcl_sub_https_redirect_fix(); |
1163
|
|
|
if (Mage::getStoreConfig('turpentine_varnish/servers/version') == '4.0' || Mage::getStoreConfig('turpentine_varnish/servers/version') == '4.1') { |
1164
|
|
|
$vars['vcl_synth'] = $this->_vcl_sub_synth_https_fix(); |
1165
|
|
|
} |
1166
|
|
|
} |
1167
|
|
|
|
1168
|
|
|
foreach (array('', 'top') as $position) { |
1169
|
|
|
$customIncludeFile = $this->_getCustomIncludeFilename($position); |
1170
|
|
|
if (is_readable($customIncludeFile)) { |
1171
|
|
|
$key = 'custom_vcl_include'; |
1172
|
|
|
$key .= ($position) ? '_'.$position : ''; |
1173
|
|
|
$vars[$key] = file_get_contents($customIncludeFile); |
1174
|
|
|
} |
1175
|
|
|
} |
1176
|
|
|
|
1177
|
|
|
return $vars; |
1178
|
|
|
} |
1179
|
|
|
} |
1180
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.