Skip to content

Add possibility generate varnish 4 config file, issue #864 #895

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 48 additions & 3 deletions app/code/Magento/PageCache/Model/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ class Config
const XML_VARNISH_PAGECACHE_BACKEND_PORT = 'system/full_page_cache/varnish/backend_port';

const XML_VARNISH_PAGECACHE_BACKEND_HOST = 'system/full_page_cache/varnish/backend_host';

const XML_VARNISH_PAGECACHE_VERSION = 'system/full_page_cache/varnish/varnish_version';

const XML_VARNISH_PAGECACHE_DESIGN_THEME_REGEX = 'design/theme/ua_regexp';

Expand All @@ -49,10 +51,15 @@ class Config
protected $_scopeConfig;

/**
* XML path to value for saving temporary .vcl configuration
* XML base path for varnish configurations
*/
const VARNISH_CONFIGURATION_PATH = 'system/full_page_cache/varnish/path';
const VARNISH_CONFIGURATION_BASE_PATH = 'system/full_page_cache/varnish/path';

/**
* XML path template for version specific .vcl configurations
*/
const VARNISH_CONFIGURATION_PATH = '{{ varnish_configuration_base_path }}/{{ varnish_version }}/vcl';

/**
* @var \Magento\Framework\App\Cache\StateInterface $_cacheState
*/
Expand Down Expand Up @@ -97,6 +104,30 @@ public function getTtl()
{
return $this->_scopeConfig->getValue(self::XML_PAGECACHE_TTL);
}

/**
* Retrieve varnish version
*
* @return string
*/
public function getVarnishVersion()
{
return $this->_scopeConfig->getValue(self::XML_VARNISH_PAGECACHE_VERSION);
}

/**
* Retrieve vcl file path
*
* @return string
*/
public function getVclFilePath()
{
$vclPath = strtr(
self::VARNISH_CONFIGURATION_PATH,
$this->_getVclFilePathReplacements()
);
return $this->_scopeConfig->getValue($vclPath);
}

/**
* Return generated varnish.vcl configuration file
Expand All @@ -105,10 +136,24 @@ public function getTtl()
*/
public function getVclFile()
{
$data = $this->_modulesDirectory->readFile($this->_scopeConfig->getValue(self::VARNISH_CONFIGURATION_PATH));
$vclPath = $this->getVclFilePath();
$data = $this->_modulesDirectory->readFile($vclPath);
return strtr($data, $this->_getReplacements());
}

/**
* retrieve replacements for self::XML_VARNISH_CONFIGURATION_FULL_PATH
*
* @return array
*/
protected function _getVclFilePathReplacements()
{
return [
'{{ varnish_configuration_base_path }}' => self::VARNISH_CONFIGURATION_BASE_PATH,
'{{ varnish_version }}' => $this->getVarnishVersion()
];
}

/**
* Prepare data for VCL config
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php
/**
* @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com)
*/

namespace Magento\PageCache\Model\System\Config\Source;

use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Option\ArrayInterface;
use Magento\PageCache\Model\Config;

/**
* Varnish versions source class
*
*/
class VarnishVersion implements ArrayInterface
{
/**
*
* @var ScopeConfigInterface
*/
protected $scopeConfig;

/**
*
* @param ScopeConfigInterface $scopeConfig
*/
public function __construct(ScopeConfigInterface $scopeConfig)
{
$this->scopeConfig = $scopeConfig;
}

/**
* retrieve varnish versions as option array
*
* @return array
*/
public function toOptionArray()
{
$options = [];
$varnishVersions = $this->scopeConfig->getValue(
Config::VARNISH_CONFIGURATION_BASE_PATH
);
foreach ($varnishVersions as $versionId => $varnishVersion) {
if (!isset($varnishVersion['label'], $varnishVersion['vcl'])) {
continue;
}
$options[$versionId] = $varnishVersion['label'];
}
return $options;
}
}
7 changes: 7 additions & 0 deletions app/code/Magento/PageCache/etc/adminhtml/system.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@
<field id="caching_application">1</field>
</depends>
</field>
<field id="varnish_version" translate="label" type="select" sortOrder="30" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Varnish version</label>
<source_model>Magento\PageCache\Model\System\Config\Source\VarnishVersion</source_model>
<depends>
<field id="caching_application">1</field>
</depends>
</field>
<field id="export_button" type="button" sortOrder="35" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Export Varnish Configuration</label>
<frontend_model>Magento\PageCache\Block\System\Config\Form\Field\Export</frontend_model>
Expand Down
12 changes: 11 additions & 1 deletion app/code/Magento/PageCache/etc/config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,16 @@
<system>
<full_page_cache>
<varnish>
<path>Magento/PageCache/etc/varnish.vcl</path>
<path>
<v3>
<label>3.0</label>
<vcl>Magento/PageCache/etc/varnish-3.vcl</vcl>
</v3>
<v4>
<label>4.0</label>
<vcl>Magento/PageCache/etc/varnish-4.vcl</vcl>
</v4>
</path>
</varnish>
<ttl>120</ttl>
<caching_application>1</caching_application>
Expand All @@ -19,6 +28,7 @@
<backend_host>localhost</backend_host>
<backend_port>8080</backend_port>
<ttl>120</ttl>
<varnish_version>v3</varnish_version>
</default>
</full_page_cache>
</system>
Expand Down
109 changes: 109 additions & 0 deletions app/code/Magento/PageCache/etc/varnish-4.vcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
vcl 4.0;

import std;
# The minimal Varnish version is 4.0

backend default {
.host = "{{ host }}";
.port = "{{ port }}";
}

acl purge {
{{ ips }}
}

sub vcl_recv {
if (req.method == "PURGE") {
if (client.ip !~ purge) {
return (synth(405, "Method not allowed"));
}
if (!req.http.X-Magento-Tags-Pattern) {
return (synth(400, "X-Magento-Tags-Pattern header required"));
}
ban("obj.http.X-Magento-Tags ~ " + req.http.X-Magento-Tags-Pattern);
return (synth(200, "Purged"));
}

if (req.method != "GET" &&
req.method != "HEAD" &&
req.method != "PUT" &&
req.method != "POST" &&
req.method != "TRACE" &&
req.method != "OPTIONS" &&
req.method != "DELETE") {
/* Non-RFC2616 or CONNECT which is weird. */
return (pipe);
}

# We only deal with GET and HEAD by default
if (req.method != "GET" && req.method != "HEAD") {
return (pass);
}

return (hash);
}

sub vcl_hash {
if (req.http.cookie ~ "X-Magento-Vary=") {
hash_data(regsub(req.http.cookie, "^.*?X-Magento-Vary=([^;]+);*.*$", "\1"));
}
{{ design_exceptions_code }}
}

sub vcl_backend_response {
if (beresp.http.content-type ~ "text") {
set beresp.do_esi = true;
}

if (bereq.url ~ "\.js$" || beresp.http.content-type ~ "text") {
set beresp.do_gzip = true;
}

# cache only successfully responses
if (beresp.status != 200) {
set beresp.ttl = 0s;
set beresp.uncacheable = true;
return (deliver);
} elsif (beresp.http.Cache-Control ~ "private") {
set beresp.uncacheable = true;
set beresp.ttl = 120s;
return (deliver);
}

if (beresp.http.X-Magento-Debug) {
set beresp.http.X-Magento-Cache-Control = beresp.http.Cache-Control;
}

# validate if we need to cache it and prevent from setting cookie
# images, css and js are cacheable by default so we have to remove cookie also
if (beresp.ttl > 0s && (bereq.method == "GET" || bereq.method == "HEAD")) {
unset beresp.http.set-cookie;
if (bereq.url !~ "\.(css|js|jpg|png|gif|tiff|bmp|gz|tgz|bz2|tbz|mp3|ogg|svg|swf|woff)(\?|$)") {
set beresp.http.Pragma = "no-cache";
set beresp.http.Expires = "-1";
set beresp.http.Cache-Control = "no-store, no-cache, must-revalidate, max-age=0";
set beresp.grace = 1m;
}
}
return (deliver);
}

sub vcl_deliver {
if (resp.http.X-Magento-Debug) {
if (obj.hits > 0) {
set resp.http.X-Magento-Cache-Debug = "HIT";
} else {
set resp.http.X-Magento-Cache-Debug = "MISS";
}
} else {
unset resp.http.Age;
}

unset resp.http.X-Magento-Debug;
unset resp.http.X-Magento-Tags;
unset resp.http.X-Powered-By;
unset resp.http.Server;
unset resp.http.X-Varnish;
unset resp.http.Via;
unset resp.http.Link;
}
22 changes: 21 additions & 1 deletion dev/tests/unit/testsuite/Magento/PageCache/Model/ConfigTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,18 @@ public function setUp()
null,
serialize([['regexp' => '(?i)pattern', 'value' => 'value_for_pattern']])
],
[
\Magento\PageCache\Model\Config::XML_VARNISH_PAGECACHE_VERSION,
\Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT,
null,
'v3'
],
[
\Magento\PageCache\Model\Config::VARNISH_CONFIGURATION_BASE_PATH . '/v3/vcl',
\Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT,
null,
'Magento/PageCache/etc/varnish-3.vcl'
]
]
)
);
Expand All @@ -107,7 +119,15 @@ public function testGetVcl()
$test = $this->_model->getVclFile();
$this->assertEquals(file_get_contents(__DIR__ . '/_files/result.vcl'), $test);
}


public function testGetVclFilePath()
{
$this->assertEquals(
'Magento/PageCache/etc/varnish-3.vcl',
$this->_model->getVclFilePath()
);
}

public function testGetTll()
{
$this->_coreConfigMock->expects($this->once())->method('getValue')->with(Config::XML_PAGECACHE_TTL);
Expand Down