├── VERSION
├── Guides
├── images
│ ├── .DS_Store
│ └── guides
│ │ ├── force-tls
│ │ ├── force-tls.png
│ │ ├── secure-url.png
│ │ ├── force-tls-modal.png
│ │ └── force-tls-success.png
│ │ ├── installation
│ │ ├── golive.png
│ │ ├── wizard.png
│ │ ├── saveconfig.png
│ │ ├── successvcl.png
│ │ ├── vclupload.png
│ │ ├── choosefastly.png
│ │ ├── newfeatures.png
│ │ ├── account-api-key.png
│ │ ├── show-service-id.png
│ │ └── testcredentials.png
│ │ ├── backend-settings
│ │ ├── edit-backend.png
│ │ └── shielding-configuration.png
│ │ └── error-maintenance-page
│ │ ├── set-html.png
│ │ ├── new-error-page.png
│ │ ├── default-error-page.png
│ │ └── error-maintenance-page.png
├── ERROR-MAINTENANCE-PAGE.md
├── FORCE-TLS.md
├── ESI.md
├── BACKEND-SETTINGS.md
└── INSTALLATION.md
├── app
├── etc
│ ├── modules
│ │ ├── .DS_Store
│ │ └── Fastly_CDN.xml
│ └── fastlycdn.xml
├── locale
│ ├── de_DE
│ │ └── .DS_Store
│ └── en_US
│ │ └── .DS_Store
├── code
│ └── community
│ │ └── Fastly
│ │ └── CDN
│ │ ├── etc
│ │ ├── vcl_snippets
│ │ │ ├── miss.vcl
│ │ │ ├── pass.vcl
│ │ │ ├── error.vcl
│ │ │ ├── deliver.vcl
│ │ │ ├── fetch.vcl
│ │ │ └── recv.vcl
│ │ ├── vcl_snippets_image_optimizations
│ │ │ └── recv.vcl
│ │ ├── vcl_snippets_force_tls
│ │ │ └── recv.vcl
│ │ └── vcl_snippets_error_page
│ │ │ └── deliver.vcl
│ │ ├── .DS_Store
│ │ ├── Block
│ │ ├── Adminhtml
│ │ │ ├── System
│ │ │ │ └── Config
│ │ │ │ │ ├── Dialogs.php
│ │ │ │ │ └── Fieldset
│ │ │ │ │ ├── Backend.php
│ │ │ │ │ ├── IoConfigBtn.php
│ │ │ │ │ ├── ErrorPageBtn.php
│ │ │ │ │ ├── ToggleIoBtn.php
│ │ │ │ │ ├── ToggleTlsBtn.php
│ │ │ │ │ ├── UploadVclBtn.php
│ │ │ │ │ ├── TestConnection.php
│ │ │ │ │ ├── TestConnectionBtn.php
│ │ │ │ │ ├── EsiTTL.php
│ │ │ │ │ ├── RouteTTL.php
│ │ │ │ │ ├── Versioninfo.php
│ │ │ │ │ └── StoreMap.php
│ │ │ └── Cache
│ │ │ │ └── Additional.php
│ │ ├── Esi
│ │ │ ├── GeoIp
│ │ │ │ ├── Action.php
│ │ │ │ └── Getcountry.php
│ │ │ └── Catalog
│ │ │ │ └── Product.php
│ │ ├── Html
│ │ │ └── Header.php
│ │ └── Cookie
│ │ │ ├── Formkey.php
│ │ │ └── Environment.php
│ │ ├── Model
│ │ ├── Resource
│ │ │ └── Mysql4
│ │ │ │ ├── Statistic.php
│ │ │ │ ├── Statistic
│ │ │ │ └── Collection.php
│ │ │ │ ├── Cms
│ │ │ │ └── Page
│ │ │ │ │ ├── Store.php
│ │ │ │ │ └── Store
│ │ │ │ │ └── Collection.php
│ │ │ │ ├── Catalog
│ │ │ │ ├── Category
│ │ │ │ │ ├── Product.php
│ │ │ │ │ └── Product
│ │ │ │ │ │ └── Collection.php
│ │ │ │ └── Product
│ │ │ │ │ └── Relation
│ │ │ │ │ └── Collection.php
│ │ │ │ └── Core
│ │ │ │ └── Url
│ │ │ │ └── Rewrite
│ │ │ │ └── Collection.php
│ │ ├── Esi
│ │ │ ├── Processor
│ │ │ │ ├── Default.php
│ │ │ │ ├── Reports
│ │ │ │ │ └── Product
│ │ │ │ │ │ ├── Compared.php
│ │ │ │ │ │ └── Viewed.php
│ │ │ │ ├── Page
│ │ │ │ │ └── Template
│ │ │ │ │ │ └── Welcome.php
│ │ │ │ ├── Abstract.php
│ │ │ │ └── GeoIp
│ │ │ │ │ ├── Action.php
│ │ │ │ │ └── Getcountry.php
│ │ │ └── Tag
│ │ │ │ ├── Checkout
│ │ │ │ └── Sidebar
│ │ │ │ │ └── Cart.php
│ │ │ │ ├── Wishlist
│ │ │ │ └── Customer
│ │ │ │ │ └── Sidebar.php
│ │ │ │ ├── Catalog
│ │ │ │ └── Product
│ │ │ │ │ └── Compare
│ │ │ │ │ └── Sidebar.php
│ │ │ │ ├── GeoIp
│ │ │ │ ├── Action.php
│ │ │ │ └── Getcountry.php
│ │ │ │ ├── Page
│ │ │ │ ├── Template
│ │ │ │ │ ├── Links.php
│ │ │ │ │ └── Welcome.php
│ │ │ │ └── Html
│ │ │ │ │ └── Notices.php
│ │ │ │ ├── Reports
│ │ │ │ └── Product
│ │ │ │ │ ├── Viewed.php
│ │ │ │ │ └── Compared.php
│ │ │ │ └── Abstract.php
│ │ ├── Cms
│ │ │ └── Page
│ │ │ │ └── Store.php
│ │ ├── Catalog
│ │ │ ├── Product
│ │ │ │ └── Relation.php
│ │ │ └── Category
│ │ │ │ └── Product.php
│ │ ├── Processor.php
│ │ ├── Control
│ │ │ ├── Cms
│ │ │ │ └── Page.php
│ │ │ ├── Catalog
│ │ │ │ ├── Category.php
│ │ │ │ └── Product.php
│ │ │ └── Abstract.php
│ │ ├── Tag.php
│ │ ├── Hash
│ │ │ └── Parameters.php
│ │ └── Config.php
│ │ ├── Helper
│ │ ├── Template.php
│ │ ├── Control
│ │ │ ├── Cms
│ │ │ │ └── Page.php
│ │ │ └── Catalog
│ │ │ │ ├── Product.php
│ │ │ │ └── Category.php
│ │ ├── Tags.php
│ │ ├── Esi.php
│ │ ├── Webhooks.php
│ │ └── Environment.php
│ │ ├── sql
│ │ └── fastlycdn_setup
│ │ │ ├── install-1.0.1.php
│ │ │ ├── upgrade-1.0.0-1.0.1.php
│ │ │ └── install-0.1.0.php
│ │ ├── Controller
│ │ └── Router.php
│ │ └── controllers
│ │ └── EsiController.php
└── design
│ ├── frontend
│ └── base
│ │ └── default
│ │ ├── layout
│ │ ├── .DS_Store
│ │ └── fastlycdn.xml
│ │ └── template
│ │ ├── .DS_Store
│ │ └── fastlycdn
│ │ ├── geoip
│ │ ├── redirect.phtml
│ │ ├── cookie.phtml
│ │ └── dialog.phtml
│ │ ├── cookie
│ │ ├── environment.phtml
│ │ └── formkey.phtml
│ │ ├── catalog
│ │ └── product.phtml
│ │ └── page
│ │ └── notices_hook.phtml
│ └── adminhtml
│ └── default
│ └── default
│ ├── template
│ └── fastlycdn
│ │ ├── system
│ │ └── config
│ │ │ ├── upload_vcl_btn.phtml
│ │ │ ├── error_page_btn.phtml
│ │ │ ├── io_config_btn.phtml
│ │ │ ├── backends.phtml
│ │ │ ├── toggle_tls_btn.phtml
│ │ │ ├── test_connection_btn.phtml
│ │ │ └── toggle_io_btn.phtml
│ │ └── cache
│ │ └── additional.phtml
│ └── layout
│ └── fastlycdn.xml
├── composer.json
├── update_version.sh
├── modman
├── LICENSE.txt
├── Release-Notes.md
└── skin
└── adminhtml
└── default
└── default
└── css
└── fastlycdn
└── fastly.css
/VERSION:
--------------------------------------------------------------------------------
1 | 1.0.32
2 |
--------------------------------------------------------------------------------
/Guides/images/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/Guides/images/.DS_Store
--------------------------------------------------------------------------------
/app/etc/modules/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/app/etc/modules/.DS_Store
--------------------------------------------------------------------------------
/app/locale/de_DE/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/app/locale/de_DE/.DS_Store
--------------------------------------------------------------------------------
/app/locale/en_US/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/app/locale/en_US/.DS_Store
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/etc/vcl_snippets/miss.vcl:
--------------------------------------------------------------------------------
1 | # Deactivate gzip on origin
2 | unset bereq.http.Accept-Encoding;
3 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/etc/vcl_snippets/pass.vcl:
--------------------------------------------------------------------------------
1 | # Deactivate gzip on origin
2 | unset bereq.http.Accept-Encoding;
3 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/app/code/community/Fastly/CDN/.DS_Store
--------------------------------------------------------------------------------
/Guides/images/guides/force-tls/force-tls.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/Guides/images/guides/force-tls/force-tls.png
--------------------------------------------------------------------------------
/Guides/images/guides/force-tls/secure-url.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/Guides/images/guides/force-tls/secure-url.png
--------------------------------------------------------------------------------
/Guides/images/guides/installation/golive.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/Guides/images/guides/installation/golive.png
--------------------------------------------------------------------------------
/Guides/images/guides/installation/wizard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/Guides/images/guides/installation/wizard.png
--------------------------------------------------------------------------------
/Guides/images/guides/installation/saveconfig.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/Guides/images/guides/installation/saveconfig.png
--------------------------------------------------------------------------------
/Guides/images/guides/installation/successvcl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/Guides/images/guides/installation/successvcl.png
--------------------------------------------------------------------------------
/Guides/images/guides/installation/vclupload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/Guides/images/guides/installation/vclupload.png
--------------------------------------------------------------------------------
/Guides/images/guides/force-tls/force-tls-modal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/Guides/images/guides/force-tls/force-tls-modal.png
--------------------------------------------------------------------------------
/Guides/images/guides/installation/choosefastly.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/Guides/images/guides/installation/choosefastly.png
--------------------------------------------------------------------------------
/Guides/images/guides/installation/newfeatures.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/Guides/images/guides/installation/newfeatures.png
--------------------------------------------------------------------------------
/app/design/frontend/base/default/layout/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/app/design/frontend/base/default/layout/.DS_Store
--------------------------------------------------------------------------------
/Guides/images/guides/force-tls/force-tls-success.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/Guides/images/guides/force-tls/force-tls-success.png
--------------------------------------------------------------------------------
/Guides/images/guides/installation/account-api-key.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/Guides/images/guides/installation/account-api-key.png
--------------------------------------------------------------------------------
/Guides/images/guides/installation/show-service-id.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/Guides/images/guides/installation/show-service-id.png
--------------------------------------------------------------------------------
/Guides/images/guides/installation/testcredentials.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/Guides/images/guides/installation/testcredentials.png
--------------------------------------------------------------------------------
/app/design/frontend/base/default/template/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/app/design/frontend/base/default/template/.DS_Store
--------------------------------------------------------------------------------
/Guides/images/guides/backend-settings/edit-backend.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/Guides/images/guides/backend-settings/edit-backend.png
--------------------------------------------------------------------------------
/Guides/images/guides/error-maintenance-page/set-html.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/Guides/images/guides/error-maintenance-page/set-html.png
--------------------------------------------------------------------------------
/Guides/images/guides/error-maintenance-page/new-error-page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/Guides/images/guides/error-maintenance-page/new-error-page.png
--------------------------------------------------------------------------------
/Guides/images/guides/backend-settings/shielding-configuration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/Guides/images/guides/backend-settings/shielding-configuration.png
--------------------------------------------------------------------------------
/Guides/images/guides/error-maintenance-page/default-error-page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/Guides/images/guides/error-maintenance-page/default-error-page.png
--------------------------------------------------------------------------------
/Guides/images/guides/error-maintenance-page/error-maintenance-page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastly/fastly-magento/HEAD/Guides/images/guides/error-maintenance-page/error-maintenance-page.png
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/etc/vcl_snippets_image_optimizations/recv.vcl:
--------------------------------------------------------------------------------
1 | if ( req.url.ext ~ "(?i)^(gif|png|jpg|jpeg|webp)$" ) {
2 |
3 | set req.http.X-Fastly-Imageopto-Api = "fastly";
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/etc/vcl_snippets_force_tls/recv.vcl:
--------------------------------------------------------------------------------
1 | # Force SSL immediately to avoid magento module VCL stripping off
2 | # google campaign ids like gclid
3 | if (!req.http.Fastly-SSL) {
4 | error 801 "Force SSL";
5 | }
6 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/etc/vcl_snippets_error_page/deliver.vcl:
--------------------------------------------------------------------------------
1 | # If we are about to serve a 5xx we need to restart then in vcl_recv error out to
2 | # get the holding page
3 | if ( resp.status >= 500 && resp.status < 600 && !req.http.ResponseObject ) {
4 | set req.http.ResponseObject = "970";
5 | restart;
6 | }
7 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Block/Adminhtml/System/Config/Dialogs.php:
--------------------------------------------------------------------------------
1 | setTemplate('fastlycdn/system/config/dialogs.phtml');
12 | }
13 | }
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fastly/cdn",
3 | "type": "magento-module",
4 | "license": "BSD-3-Clause",
5 | "description":"Fastly CDN module for Magento 1.x",
6 | "version": "1.0.32",
7 | "authors":[
8 | {
9 | "name":"Fastly",
10 | "email":"support@fastly.com"
11 | }
12 | ],
13 | "require": {
14 | "magento-hackathon/magento-composer-installer": "*"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Resource/Mysql4/Statistic.php:
--------------------------------------------------------------------------------
1 | _init('fastlycdn/statistics', 'stat_id');
8 | }
9 |
10 | public function _beforeSave(Mage_Core_Model_Abstract $object)
11 | {
12 | $object->setCreatedAt(Varien_Date::now());
13 | return parent::_beforeSave($object); // TODO: Change the autogenerated stub
14 | }
15 | }
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Resource/Mysql4/Statistic/Collection.php:
--------------------------------------------------------------------------------
1 | _init('fastlycdn/statistic');
8 | }
9 |
10 | /**
11 | * @param $action
12 | * @return Varien_Object
13 | */
14 | public function getStatByAction($action)
15 | {
16 | return $this->addFieldToFilter('action', $action)->setOrder('created_at', 'DESC')->getFirstItem();
17 | }
18 | }
--------------------------------------------------------------------------------
/update_version.sh:
--------------------------------------------------------------------------------
1 | # Run this script before new release to embed version tag in the right places so
2 | # we can debug easier
3 | VERSION=`cat VERSION`
4 |
5 | sed -i "s/resp.http.Fastly-Magento-VCL-Uploaded = \".*\"/resp.http.Fastly-Magento-VCL-Uploaded = \"$VERSION\"/g" ./app/code/community/Fastly/CDN/etc/vcl_snippets/*.vcl
6 | sed -i "s/\"version\": \".*\"/\"version\": \"$VERSION\"/g" composer.json
7 | sed -i "s/\"Fastly-Module-Enabled\", \".*\"/\"Fastly-Module-Enabled\", \"$VERSION\"/g" app/code/community/Fastly/CDN/Helper/Cache.php
8 | sed -i "s|.* |$VERSION |g" app/code/community/Fastly/CDN/etc/config.xml
9 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/etc/vcl_snippets/error.vcl:
--------------------------------------------------------------------------------
1 | # geo ip request
2 | if (obj.status == 750) {
3 | set req.url = regsub(req.url, "(/fastlycdn/esi/getcountry/.*)", "/fastlycdn/esi/getcountryaction/?country_code=") obj.response;
4 | return (restart);
5 | }
6 |
7 | # geo ip country code
8 | if (obj.status == 755) {
9 | set obj.status = 200;
10 | synthetic obj.response;
11 | return(deliver);
12 | }
13 |
14 | # formkey request
15 | if (obj.status == 760) {
16 | set obj.status = 200;
17 | synthetic obj.response;
18 | return (deliver);
19 | }
20 |
--------------------------------------------------------------------------------
/app/design/adminhtml/default/default/template/fastlycdn/system/config/upload_vcl_btn.phtml:
--------------------------------------------------------------------------------
1 | getButtonHtml() ?>
2 |
3 |
12 |
13 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Block/Adminhtml/System/Config/Fieldset/Backend.php:
--------------------------------------------------------------------------------
1 | setTemplate('fastlycdn/system/config/backends.phtml');
12 | }
13 |
14 | /**
15 | * Return element html
16 | *
17 | * @param Varien_Data_Form_Element_Abstract $element
18 | * @return string
19 | */
20 | protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
21 | {
22 | return $this->_toHtml();
23 | }
24 | }
--------------------------------------------------------------------------------
/app/design/adminhtml/default/default/template/fastlycdn/system/config/error_page_btn.phtml:
--------------------------------------------------------------------------------
1 | isEnabled()): ?>
2 | getButtonHtml() ?>
3 |
4 | __('Please enable and configure the extension first. ') ?>
5 |
6 |
15 |
16 |
--------------------------------------------------------------------------------
/app/design/adminhtml/default/default/template/fastlycdn/system/config/io_config_btn.phtml:
--------------------------------------------------------------------------------
1 | isEnabled()): ?>
2 | getButtonHtml() ?>
3 |
4 | __('Please enable and configure the extension first. ') ?>
5 |
6 |
15 |
16 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Esi/Processor/Default.php:
--------------------------------------------------------------------------------
1 |
2 |
23 |
24 |
25 |
26 | true
27 | community
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Block/Esi/GeoIp/Action.php:
--------------------------------------------------------------------------------
1 | _init('fastlycdn/cms_page_store');
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Catalog/Product/Relation.php:
--------------------------------------------------------------------------------
1 | _init('catalog/product_relation');
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Catalog/Category/Product.php:
--------------------------------------------------------------------------------
1 | _init('fastlycdn/catalog_category_product');
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Esi/Tag/Checkout/Sidebar/Cart.php:
--------------------------------------------------------------------------------
1 |
2 |
23 |
24 |
25 |
26 |
27 | Fastly_CDN_Model_Processor
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Esi/Processor/Page/Template/Welcome.php:
--------------------------------------------------------------------------------
1 | getLayout()->getBlock('header')->getOriginalWelcome();
27 | return $output;
28 | }
29 | }
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Resource/Mysql4/Cms/Page/Store.php:
--------------------------------------------------------------------------------
1 | _init('cms/page_store', 'store_id');
30 | }
31 | }
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/etc/vcl_snippets/deliver.vcl:
--------------------------------------------------------------------------------
1 | # Add an easy way to see whether custom Fastly VCL has been uploaded
2 | if ( req.http.Fastly-Debug ) {
3 | set resp.http.Fastly-Magento-VCL-Uploaded = "1.0.32";
4 | } else {
5 | remove resp.http.Fastly-Module-Enabled;
6 | # remove Varnish/proxy header
7 | remove resp.http.X-Varnish;
8 | remove resp.http.Via;
9 | remove resp.http.X-Purge-URL;
10 | remove resp.http.X-Purge-Host;
11 | remove resp.http.Fastly-page-cacheable;
12 | }
13 |
14 | # Clean up Vary before handing off to the user
15 | if ( !req.http.Fastly-FF ) {
16 | set resp.http.Vary = regsub(resp.http.Vary, "Fastly-Cdn-Env,Https", "Cookie");
17 | remove resp.http.surrogate-keys-set;
18 | }
19 |
20 | if (resp.http.x-esi && !req.http.Fastly-FF) {
21 | # Remove the ESI marker
22 | unset resp.http.x-esi;
23 |
24 | # Tell browsers not to cache the content
25 | set resp.http.Cache-Control = "no-store, no-cache, must-revalidate, post-check=0, pre-check=0";
26 | }
27 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Resource/Mysql4/Catalog/Category/Product.php:
--------------------------------------------------------------------------------
1 | _init('catalog/category_product', 'category_id');
30 | }
31 | }
--------------------------------------------------------------------------------
/app/design/frontend/base/default/template/fastlycdn/geoip/redirect.phtml:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/modman:
--------------------------------------------------------------------------------
1 | README.md app/code/community/Fastly/CDN/README.md
2 | LICENSE.txt app/code/community/Fastly/CDN/LICENSE.txt
3 | composer.json app/code/community/Fastly/CDN/composer.json
4 | modman app/code/community/Fastly/CDN/modman
5 | app/code/community/Fastly/CDN/* app/code/community/Fastly/CDN/
6 | app/design/adminhtml/default/default/layout/fastlycdn.xml app/design/adminhtml/default/default/layout/fastlycdn.xml
7 | app/design/adminhtml/default/default/template/fastlycdn/* app/design/adminhtml/default/default/template/fastlycdn/
8 | app/design/frontend/base/default/layout/fastlycdn.xml app/design/frontend/base/default/layout/fastlycdn.xml
9 | app/design/frontend/base/default/template/fastlycdn/* app/design/frontend/base/default/template/fastlycdn/
10 | app/etc/fastlycdn.xml app/etc/fastlycdn.xml
11 | app/etc/modules/Fastly_CDN.xml app/etc/modules/Fastly_CDN.xml
12 | app/locale/de_DE/Fastly_CDN.csv app/locale/de_DE/Fastly_CDN.csv
13 | app/locale/en_US/Fastly_CDN.csv app/locale/en_US/Fastly_CDN.csv
14 | skin/adminhtml/default/default/css/fastlycdn/fastly.css skin/adminhtml/default/default/css/fastlycdn/fastly.css
15 | skin/adminhtml/default/default/js/fastlycdn/fastly.js skin/adminhtml/default/default/js/fastlycdn/fastly.js
16 |
17 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Esi/Tag/GeoIp/Action.php:
--------------------------------------------------------------------------------
1 | setTemplate('fastlycdn/system/config/io_config_btn.phtml');
12 | }
13 |
14 | /**
15 | * Return element html
16 | *
17 | * @param Varien_Data_Form_Element_Abstract $element
18 | * @return string
19 | */
20 | protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
21 | {
22 | return $this->_toHtml();
23 | }
24 |
25 | /**
26 | * Generate button html
27 | *
28 | * @return string
29 | */
30 | public function getButtonHtml()
31 | {
32 | $button = $this->getLayout()->createBlock('adminhtml/widget_button')
33 | ->setData(array(
34 | 'id' => "io_config_btn",
35 | 'label' => $this->helper('adminhtml')->__('Configure'),
36 | 'onclick' => "Fastly.initDialog('io-config-form'); return false;"
37 | ));
38 |
39 | return $button->toHtml();
40 | }
41 | }
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Esi/Tag/Page/Template/Links.php:
--------------------------------------------------------------------------------
1 | setTemplate('fastlycdn/system/config/error_page_btn.phtml');
12 | }
13 |
14 | /**
15 | * Return element html
16 | *
17 | * @param Varien_Data_Form_Element_Abstract $element
18 | * @return string
19 | */
20 | protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
21 | {
22 | return $this->_toHtml();
23 | }
24 |
25 | /**
26 | * Generate button html
27 | *
28 | * @return string
29 | */
30 | public function getButtonHtml()
31 | {
32 | $button = $this->getLayout()->createBlock('adminhtml/widget_button')
33 | ->setData(array(
34 | 'id' => "fastly_error_page_btn",
35 | 'label' => $this->helper('adminhtml')->__('Set HTML'),
36 | 'onclick' => "Fastly.initDialog('error-page-form'); return false;"
37 | ));
38 |
39 | return $button->toHtml();
40 | }
41 | }
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Block/Adminhtml/System/Config/Fieldset/ToggleIoBtn.php:
--------------------------------------------------------------------------------
1 | setTemplate('fastlycdn/system/config/toggle_io_btn.phtml');
12 | }
13 |
14 | /**
15 | * Return element html
16 | *
17 | * @param Varien_Data_Form_Element_Abstract $element
18 | * @return string
19 | */
20 | protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
21 | {
22 | return $this->_toHtml();
23 | }
24 |
25 | /**
26 | * Generate button html
27 | *
28 | * @return string
29 | */
30 | public function getButtonHtml()
31 | {
32 | $button = $this->getLayout()->createBlock('adminhtml/widget_button')
33 | ->setData(array(
34 | 'id' => "fastly_toggle_io_btn",
35 | 'label' => $this->helper('adminhtml')->__('Enable/Disable'),
36 | 'onclick' => "Fastly.initDialog('toggle-io-form'); return false;"
37 | ));
38 |
39 | return $button->toHtml();
40 | }
41 | }
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Block/Adminhtml/System/Config/Fieldset/ToggleTlsBtn.php:
--------------------------------------------------------------------------------
1 | setTemplate('fastlycdn/system/config/toggle_tls_btn.phtml');
12 | }
13 |
14 | /**
15 | * Return element html
16 | *
17 | * @param Varien_Data_Form_Element_Abstract $element
18 | * @return string
19 | */
20 | protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
21 | {
22 | return $this->_toHtml();
23 | }
24 |
25 | /**
26 | * Generate button html
27 | *
28 | * @return string
29 | */
30 | public function getButtonHtml()
31 | {
32 | $button = $this->getLayout()->createBlock('adminhtml/widget_button')
33 | ->setData(array(
34 | 'id' => "fastly_toggle_tls_btn",
35 | 'label' => $this->helper('adminhtml')->__('Force TLS'),
36 | 'onclick' => "Fastly.initDialog('toggle-tls-form'); return false;"
37 | ));
38 |
39 | return $button->toHtml();
40 | }
41 | }
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Esi/Tag/Page/Html/Notices.php:
--------------------------------------------------------------------------------
1 | getSelect()
32 | ->where('id_path = ?', "category/{$categoryId}");
33 | return $this;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Block/Adminhtml/System/Config/Fieldset/UploadVclBtn.php:
--------------------------------------------------------------------------------
1 | setTemplate('fastlycdn/system/config/upload_vcl_btn.phtml');
12 | }
13 |
14 | /**
15 | * Return element html
16 | *
17 | * @param Varien_Data_Form_Element_Abstract $element
18 | * @return string
19 | */
20 | protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
21 | {
22 | return $this->_toHtml();
23 | }
24 |
25 | /**
26 | * Generate button html
27 | *
28 | * @return string
29 | */
30 | public function getButtonHtml()
31 | {
32 | $button = $this->getLayout()->createBlock('adminhtml/widget_button')
33 | ->setData(array(
34 | 'id' => "fastly_upload_vcl_btn",
35 | 'label' => $this->helper('adminhtml')->__('Upload VCL to Fastly'),
36 | 'onclick' => "Fastly.initDialog('vcl-upload-form'); return false;"
37 | ));
38 |
39 | return $button->toHtml();
40 | }
41 | }
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Helper/Template.php:
--------------------------------------------------------------------------------
1 | getNode('admin/routers/adminhtml/args/frontName')->asArray();
17 | if(!$adminPath || !is_string($adminPath)) {
18 | $adminPath = 'admin';
19 | }
20 |
21 | // Ignore Query params
22 | $queryParams = Mage::getStoreConfig(self::FASTLY_CDN_TEMPLATE_QUERY_PARAMS);
23 | $queryParams = explode(',', $queryParams);
24 | $queryParams = array_filter(array_map('trim', $queryParams));
25 | $queryParams = implode('|', $queryParams);
26 |
27 | $replaceValues = array(
28 | '####ADMIN_PATH####' => $adminPath,
29 | '####QUERY_PARAMETERS####' => $queryParams//'utm_.*|gclid|gdftrk|_ga|mc_.*'
30 | );
31 |
32 | foreach($replaceValues as $search => $replace) {
33 | $value = str_replace($search, $replace, $value);
34 | }
35 |
36 | return $value;
37 | }
38 | }
--------------------------------------------------------------------------------
/app/design/frontend/base/default/template/fastlycdn/cookie/environment.phtml:
--------------------------------------------------------------------------------
1 |
22 |
29 |
--------------------------------------------------------------------------------
/app/design/frontend/base/default/template/fastlycdn/cookie/formkey.phtml:
--------------------------------------------------------------------------------
1 |
22 |
29 | getCookieName();
31 | $_formKeyValue = $this->getFormKeyValue();
32 | ?>
33 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Resource/Mysql4/Cms/Page/Store/Collection.php:
--------------------------------------------------------------------------------
1 | _init('fastlycdn/cms_page_store');
30 | }
31 |
32 | /**
33 | * Add cms page id filter
34 | *
35 | * @param int $id
36 | * @return Fastly_CDN_Model_Resource_Mysql4_Cms_Page_Store_Collection
37 | */
38 | public function addPageFilter($id)
39 | {
40 | $this->getSelect()
41 | ->where('page_id = ?', $id);
42 | return $this;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Processor.php:
--------------------------------------------------------------------------------
1 |
32 | * Mage_Core_Model_Cache::processRequest().
33 | *
34 | * @param string $content
35 | * @return string | false
36 | */
37 | public function extractContent($content)
38 | {
39 | return $content;
40 | }
41 | }
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Helper/Control/Cms/Page.php:
--------------------------------------------------------------------------------
1 | isEnabled() && $this->isPurge();
34 | }
35 |
36 | /**
37 | * Returns true if category should be purged on save
38 | *
39 | * @return boolean
40 | */
41 | public function isPurge()
42 | {
43 | return Mage::getStoreConfigFlag(self::XML_PATH_FASTLY_CDN_CACHE_PURGE);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Helper/Control/Catalog/Product.php:
--------------------------------------------------------------------------------
1 | isEnabled() && $this->isPurge();
34 | }
35 |
36 | /**
37 | * Returns true if CMS page should be purged on save
38 | *
39 | * @return boolean
40 | */
41 | public function isPurge()
42 | {
43 | return Mage::getStoreConfigFlag(self::XML_PATH_FASTLY_CDN_CACHE_PURGE);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Helper/Control/Catalog/Category.php:
--------------------------------------------------------------------------------
1 | isEnabled() && $this->isPurge();
34 | }
35 |
36 | /**
37 | * Returns true if category should be purged on save
38 | *
39 | * @return boolean
40 | */
41 | public function isPurge()
42 | {
43 | return Mage::getStoreConfigFlag(self::XML_PATH_FASTLY_CDN_CACHE_PURGE);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015 Fastly, Inc. (http://www.fastly.com)
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5 |
6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7 |
8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 |
10 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
11 |
12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/Guides/ERROR-MAINTENANCE-PAGE.md:
--------------------------------------------------------------------------------
1 | # Set Error / Maintenance page guide
2 |
3 | The Fastly CDN will sometimes return a 503 error due to various issues that can occur. The generic text associated with a 503 error is “Service Unavailable” and it can mean variety of things. This default error response can be confusing to the customers and have a basic look and feel.
4 |
5 | This guide will show you how to set friendly or prettier 503 custom error page through Fastly module which will be served when:
6 | * When origin returns a response status greater than 500
7 | * When origin is down (i.e unhealthy, timeout, etc)
8 |
9 | To set custom Error page, go to:
10 |
11 | ```
12 | Magento admin > System > Configuration > Services > Fastly CDN
13 | ```
14 |
15 | Under the Fastly Configuration, click on the **Error/Maintenance page:**
16 |
17 | 
18 |
19 | The modal window will pop up. Paste your custom HTML code into the HTML textarea and press the Upload button to save changes.
20 |
21 | 
22 |
23 | Now when Fastly returns 503 error, instead of default error page which looks something like this:
24 |
25 | 
26 |
27 | You will serve your custom error page:
28 |
29 | 
30 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Block/Adminhtml/System/Config/Fieldset/TestConnection.php:
--------------------------------------------------------------------------------
1 | setTemplate('fastlycdn/system/config/test_connection_btn.phtml');
12 | }
13 |
14 | /**
15 | * Return element html
16 | *
17 | * @param Varien_Data_Form_Element_Abstract $element
18 | * @return string
19 | */
20 | protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
21 | {
22 | return $this->_toHtml();
23 | }
24 |
25 | /**
26 | * Return ajax url for button
27 | *
28 | * @return string
29 | */
30 | public function getAjaxCheckUrl()
31 | {
32 | return Mage::helper('adminhtml')->getUrl('*/fastlyCdn/testConnection');
33 | }
34 |
35 | /**
36 | * Generate button html
37 | *
38 | * @return string
39 | */
40 | public function getButtonHtml()
41 | {
42 | $button = $this->getLayout()->createBlock('adminhtml/widget_button')
43 | ->setData(array(
44 | 'id' => 'fastly_test_conn_btn',
45 | 'label' => $this->helper('adminhtml')->__('Test connection'),
46 | 'onclick' => 'javascript:check(); return false;'
47 | ));
48 |
49 | return $button->toHtml();
50 | }
51 | }
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Block/Adminhtml/System/Config/Fieldset/TestConnectionBtn.php:
--------------------------------------------------------------------------------
1 | setTemplate('fastlycdn/system/config/test_connection_btn.phtml');
12 | }
13 |
14 | /**
15 | * Return element html
16 | *
17 | * @param Varien_Data_Form_Element_Abstract $element
18 | * @return string
19 | */
20 | protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
21 | {
22 | return $this->_toHtml();
23 | }
24 |
25 | /**
26 | * Return ajax url for button
27 | *
28 | * @return string
29 | */
30 | public function getAjaxCheckUrl()
31 | {
32 | return Mage::helper('adminhtml')->getUrl('*/fastlyCdn/testConnection');
33 | }
34 |
35 | /**
36 | * Generate button html
37 | *
38 | * @return string
39 | */
40 | public function getButtonHtml()
41 | {
42 | $button = $this->getLayout()->createBlock('adminhtml/widget_button')
43 | ->setData(array(
44 | 'id' => 'fastly_test_conn_btn',
45 | 'label' => $this->helper('adminhtml')->__('Test connection'),
46 | 'onclick' => 'javascript:check(); return false;'
47 | ));
48 |
49 | return $button->toHtml();
50 | }
51 | }
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Resource/Mysql4/Catalog/Product/Relation/Collection.php:
--------------------------------------------------------------------------------
1 | _init('fastlycdn/catalog_product_relation', 'catalog/product_relation');
31 | }
32 |
33 | /**
34 | * Filters collection by child product id
35 | *
36 | * @param int $childId
37 | * @return Fastly_CDN_Model_Resource_Mysql4_Catalog_Product_Relation_Collection
38 | */
39 | public function filterByChildId($childId)
40 | {
41 | $this->getSelect()
42 | ->where('child_id=?', $childId);
43 | return $this;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Esi/Processor/Reports/Product/Viewed.php:
--------------------------------------------------------------------------------
1 | _getHelper()->getEsiParam();
29 | if (empty($listData) === false) {
30 | $productIds = $listData->list;
31 |
32 | // filter current product ID from list
33 | if ($productId = $this->getProductId()) {
34 | $key = array_search($productId, $productIds);
35 | unset($productIds[$key]);
36 | }
37 | $block->setProductIds($productIds);
38 | }
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Resource/Mysql4/Catalog/Category/Product/Collection.php:
--------------------------------------------------------------------------------
1 | _init('fastlycdn/catalog_category_product');
31 | }
32 |
33 | /**
34 | * Filter collection by product ids
35 | *
36 | * @param array $productIds
37 | * @return Fastly_CDN_Model_Resource_Mysql4_Catalog_Category_Product_Collection
38 | */
39 | public function filterAllByProductIds(array $productIds)
40 | {
41 | $this->getSelect()
42 | ->where('product_id in (?)', $productIds)
43 | ->group('category_id');
44 | return $this;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Control/Cms/Page.php:
--------------------------------------------------------------------------------
1 | _canPurge()) {
35 | $surrogateKey = Fastly_CDN_Helper_Tags::SURROGATE_KEY_CMSPAGE_PREFIX . $page->getId();
36 | $this->_getCacheControl()->cleanBySurrogateKey($surrogateKey);
37 |
38 | $this->_getSession()->addSuccess(
39 | Mage::helper('fastlycdn')->__('Fastly CDN for cms page "%s" has been purged.', $page->getTitle())
40 | );
41 | }
42 |
43 | return $this;
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/app/design/adminhtml/default/default/template/fastlycdn/system/config/backends.phtml:
--------------------------------------------------------------------------------
1 |
2 | isEnabled()): ?>
3 |
4 |
5 |
6 |
7 | Name
8 |
9 |
10 |
11 |
12 |
13 | __('Loading...'); ?>
14 |
15 |
16 |
17 |
18 |
27 |
28 |
37 |
38 |
__('Please enable and configure the extension first. ') ?>
39 |
40 |
--------------------------------------------------------------------------------
/app/design/adminhtml/default/default/template/fastlycdn/system/config/toggle_tls_btn.phtml:
--------------------------------------------------------------------------------
1 | getButtonHtml() ?>
2 |
3 |
4 | Current state:
5 |
6 | enabled
7 | disabled
8 | unknown
9 |
10 |
11 |
12 |
21 |
22 |
31 |
32 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Block/Adminhtml/System/Config/Fieldset/EsiTTL.php:
--------------------------------------------------------------------------------
1 | addColumn(
28 | 'regexp', array(
29 | 'label' => Mage::helper('adminhtml')->__('Block'),
30 | 'style' => 'width:180px')
31 | );
32 | $this->addColumn(
33 | 'value', array(
34 | 'label' => Mage::helper('adminhtml')->__('TTL'),
35 | 'style' => 'width:60px')
36 | );
37 | $this->_addAfter = false;
38 | $this->_addButtonLabel = Mage::helper('adminhtml')->__('Add block');
39 | parent::__construct();
40 | }
41 |
42 | protected function _toHtml()
43 | {
44 | return '' . parent::_toHtml() . '
';
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Block/Adminhtml/System/Config/Fieldset/RouteTTL.php:
--------------------------------------------------------------------------------
1 | addColumn(
28 | 'regexp', array(
29 | 'label' => Mage::helper('adminhtml')->__('Route'),
30 | 'style' => 'width:120px')
31 | );
32 | $this->addColumn(
33 | 'value', array(
34 | 'label' => Mage::helper('adminhtml')->__('TTL'),
35 | 'style' => 'width:120px')
36 | );
37 | $this->_addAfter = false;
38 | $this->_addButtonLabel = Mage::helper('adminhtml')->__('Add route');
39 | parent::__construct();
40 | }
41 |
42 | protected function _toHtml()
43 | {
44 | return '' . parent::_toHtml() . '
';
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/design/frontend/base/default/template/fastlycdn/catalog/product.phtml:
--------------------------------------------------------------------------------
1 |
22 |
29 | getProductId()): ?>
30 | getCookieName(); ?>
31 |
48 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Esi/Tag/Reports/Product/Viewed.php:
--------------------------------------------------------------------------------
1 | _getHelper()->isStrictRenderingEnabled()) {
36 | if (($product = Mage::registry('current_product')) && ($product instanceof Mage_Catalog_Model_Product)) {
37 | return array('product_id' => $product->getId());
38 | }
39 | }
40 | return parent::_getAdditionalQueryParams();
41 | }
42 | }
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Esi/Tag/Reports/Product/Compared.php:
--------------------------------------------------------------------------------
1 | _getHelper()->isStrictRenderingEnabled()) {
36 | if (($product = Mage::registry('current_product')) && ($product instanceof Mage_Catalog_Model_Product)) {
37 | return array('product_id' => $product->getId());
38 | }
39 | }
40 | return parent::_getAdditionalQueryParams();
41 | }
42 | }
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Block/Html/Header.php:
--------------------------------------------------------------------------------
1 | canUseEsi()) {
38 | $esiTagModel = Mage::getModel(
39 | 'fastlycdn/esi_tag_page_template_welcome',
40 | array(Mage::helper('fastlycdn')->getLayoutNameParam() => 'page/template_welcome')
41 | );
42 |
43 | $esiTag = $esiTagModel->getEsiIncludeTag($this);
44 |
45 | return $esiTag;
46 | }
47 |
48 | // no esi - use default behaviour
49 | return $this->getOriginalWelcome();
50 | }
51 |
52 |
53 | public function getOriginalWelcome()
54 | {
55 | return parent::getWelcome();
56 | }
57 |
58 | }
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Block/Esi/Catalog/Product.php:
--------------------------------------------------------------------------------
1 | getId();
33 | }
34 | return false;
35 | }
36 |
37 | /**
38 | * Get maximum count of products allowed in the list
39 | * @return int
40 | */
41 | public function getLimit()
42 | {
43 | return Mage::getStoreConfig(Mage_Reports_Block_Product_Viewed::XML_PATH_RECENTLY_VIEWED_COUNT);
44 | }
45 |
46 | /**
47 | * Get cookie name for viewed product ID list
48 | * @return string
49 | */
50 | public function getCookieName()
51 | {
52 | return Mage::helper('fastlycdn')->generateCookieName(
53 | Fastly_CDN_Model_Esi_Tag_Reports_Product_Viewed::COOKIE_NAME
54 | );
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/app/design/adminhtml/default/default/template/fastlycdn/system/config/test_connection_btn.phtml:
--------------------------------------------------------------------------------
1 |
28 |
29 | getButtonHtml() ?>
30 |
31 |
41 |
42 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Tag.php:
--------------------------------------------------------------------------------
1 | ' .
35 | Mage::helper('fastlycdn')->__(
36 | 'Fastly CDN version: %s',
37 | Mage::getConfig()->getNode('modules/Fastly_CDN/version')
38 | ) . ' ' .
39 | Mage::helper('fastlycdn')->__(
40 | 'To contact Fastly support please click here .',
41 | 'mailto:support@fastly.com?subject=[Magento%20Module%20Support]' .
42 | '&body=Installed%20Version%20' .Mage::getConfig()->getNode('modules/Fastly_CDN/version')
43 | ) .
44 | '';
45 |
46 | return $info;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/app/design/adminhtml/default/default/layout/fastlycdn.xml:
--------------------------------------------------------------------------------
1 |
2 |
23 |
24 |
25 |
26 |
27 |
28 | skin_js
29 | js/fastlycdn/fastly.js
30 |
31 |
32 | skin_css
33 | css/fastlycdn/fastly.css
34 |
35 |
36 | lib/prototype/windows/themes/magento.css
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/Guides/FORCE-TLS.md:
--------------------------------------------------------------------------------
1 | # Force TLS guide
2 |
3 | This guide will show how to setup Secure base URL in Magento and turn on Force TLS option.
4 | For this, you will need to have a TLS certificate. You can read [here](https://docs.fastly.com/guides/securing-communications/) on how to order a TLS certificate through Fastly and then set it up.
5 |
6 | Once you're ready, go to:
7 |
8 | ```
9 | Magento admin > System > Configuration > General > Web
10 | ```
11 |
12 | Click on the **Secure** tab and enter your **Secure Base URL**. Also, set **Use Secure URLs in Frontend** and **Use Secure URLs in Admin** options to **Yes**.
13 |
14 | 
15 |
16 | Once you're done, press the Save config button in the upper right corner.
17 |
18 | ### Allowing only TLS connections to your site
19 |
20 | If you want to only allow TLS on your site, we have you covered.
21 | There is an option built into the Fastly module that will allow you to force unencrypted requests over to TLS. It works by returning a 301 Moved Permanently response to any unencrypted request, which redirects to the TLS equivalent. For instance, making a request for http://www.example.com/foo.jpeg would redirect to https://www.example.com/foo.jpeg.
22 |
23 | To enable Force TLS option, go to:
24 |
25 | ```
26 | Magento admin > System > Configuration > Services > Fastly CDN
27 | ```
28 |
29 | Under the **General Settings** tab, press the Force TLS button.
30 |
31 | 
32 |
33 | The modal window with the following content will pop up, press the **Upload** button in the upper right corner:
34 |
35 | 
36 |
37 | Once done, the modal windows will close and you will see a success message. Also, the current state will change to **enabled**.
38 |
39 | 
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Helper/Tags.php:
--------------------------------------------------------------------------------
1 | getButtonHtml() ?>
2 |
3 |
4 | Current state:
5 |
6 | enabled
7 | disabled
8 | unknown
9 |
10 |
11 |
12 |
21 |
22 |
31 |
32 |
41 |
42 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Block/Cookie/Formkey.php:
--------------------------------------------------------------------------------
1 | addData(array(
28 | 'cache_lifetime' => null
29 | ));
30 | }
31 |
32 |
33 | /**
34 | * Return environment cookie name
35 | *
36 | * @return string
37 | */
38 | public function getCookieName()
39 | {
40 | return Fastly_CDN_Helper_Esi::FORMKEY_COOKIE;
41 | }
42 |
43 | /**
44 | * Return the form key esi tag
45 | *
46 | * @return string
47 | */
48 | public function getFormKeyValue()
49 | {
50 | // try to use form key from session
51 | $session = Mage::getSingleton('core/session');
52 | $formKey = $session->getData('_form_key');
53 |
54 | // or create new one via esi
55 | if (empty($formKey)) {
56 | $formKey = Mage::helper('fastlycdn/esi')->getFormKeyEsiTag();
57 | }
58 |
59 | return $formKey;
60 | }
61 |
62 | /**
63 | * Return the cookie lifetime
64 | *
65 | * @return int
66 | */
67 | public function getCookieLifetime()
68 | {
69 | return Mage::getModel('core/cookie')->getLifetime() * 1000;
70 | }
71 | }
--------------------------------------------------------------------------------
/app/design/frontend/base/default/template/fastlycdn/geoip/cookie.phtml:
--------------------------------------------------------------------------------
1 |
22 |
30 |
34 | isGeoIpEnabled()): ?>
35 | getGeoIpCookieName(); ?>
36 |
49 |
50 | getChildHtml('fastlycdn.geoip_getcountry'); ?>
51 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/sql/fastlycdn_setup/install-1.0.1.php:
--------------------------------------------------------------------------------
1 | getConnection();
9 |
10 | $installer->startSetup();
11 |
12 | /**
13 | * Create table 'fastly_statistics'
14 | */
15 |
16 | $table = $connection->newTable($installer->getTable('fastlycdn/statistics')
17 | )->addColumn(
18 | 'stat_id',
19 | Varien_Db_Ddl_Table::TYPE_INTEGER,
20 | null,
21 | ['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true],
22 | 'Stat id'
23 | )->addColumn(
24 | 'action',
25 | Varien_Db_Ddl_Table::TYPE_TEXT,
26 | 30,
27 | ['nullable' => false],
28 | 'Fastly action'
29 | )->addColumn(
30 | 'sent',
31 | Varien_Db_Ddl_Table::TYPE_BOOLEAN,
32 | null,
33 | ['nullable' => false, 'default' => 0],
34 | '1 = Curl req. sent | 0 = Curl req. not sent'
35 | )->addColumn(
36 | 'state',
37 | Varien_Db_Ddl_Table::TYPE_BOOLEAN,
38 | null,
39 | ['nullable' => false, 'default' => 0],
40 | '1 = configured | 0 = not_configured'
41 | )->addColumn(
42 | 'created_at',
43 | Varien_Db_Ddl_Table::TYPE_DATETIME,
44 | null,
45 | [],
46 | 'Action date'
47 | );
48 | $connection->createTable($table);
49 |
50 | /**
51 | * Insert Installed action into the statistic table
52 | */
53 |
54 | $tableName = $installer->getTable('fastly_statistics');
55 |
56 | if($connection->isTableExists($tableName) == true) {
57 |
58 | $statistic = Mage::getModel('fastlycdn/statistic');
59 | $cid = $statistic->generateCid();
60 | Mage::getConfig()->saveConfig('system/full_page_cache/fastly/current_version', Mage::getConfig()->getNode('modules/Fastly_CDN/version'));
61 | Mage::getConfig()->saveConfig('system/full_page_cache/fastly/fastly_ga_cid', $cid);
62 |
63 | $sendInstalledReq = $statistic->sendInstalledReq();
64 |
65 | $installedData = array(
66 | 'action' => $statistic::FASTLY_INSTALLED_FLAG,
67 | 'created_at' => Varien_Date::now(),
68 | 'sent' => $sendInstalledReq
69 | );
70 |
71 | $statistic->setData($installedData);
72 | $statistic->save();
73 | }
74 |
75 | $installer->endSetup();
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/sql/fastlycdn_setup/upgrade-1.0.0-1.0.1.php:
--------------------------------------------------------------------------------
1 | getConnection();
9 |
10 | $installer->startSetup();
11 |
12 | /**
13 | * Create table 'fastly_statistics'
14 | */
15 |
16 | $table = $connection->newTable($installer->getTable('fastlycdn/statistics')
17 | )->addColumn(
18 | 'stat_id',
19 | Varien_Db_Ddl_Table::TYPE_INTEGER,
20 | null,
21 | ['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true],
22 | 'Stat id'
23 | )->addColumn(
24 | 'action',
25 | Varien_Db_Ddl_Table::TYPE_TEXT,
26 | 30,
27 | ['nullable' => false],
28 | 'Fastly action'
29 | )->addColumn(
30 | 'sent',
31 | Varien_Db_Ddl_Table::TYPE_BOOLEAN,
32 | null,
33 | ['nullable' => false, 'default' => 0],
34 | '1 = Curl req. sent | 0 = Curl req. not sent'
35 | )->addColumn(
36 | 'state',
37 | Varien_Db_Ddl_Table::TYPE_BOOLEAN,
38 | null,
39 | ['nullable' => false, 'default' => 0],
40 | '1 = configured | 0 = not_configured'
41 | )->addColumn(
42 | 'created_at',
43 | Varien_Db_Ddl_Table::TYPE_DATETIME,
44 | null,
45 | [],
46 | 'Action date'
47 | );
48 | $connection->createTable($table);
49 |
50 | /**
51 | * Insert Installed action into the statistic table
52 | */
53 |
54 | $tableName = $installer->getTable('fastly_statistics');
55 |
56 | if($connection->isTableExists($tableName) == true) {
57 |
58 | $statistic = Mage::getModel('fastlycdn/statistic');
59 | $cid = $statistic->generateCid();
60 | Mage::getConfig()->saveConfig('system/full_page_cache/fastly/current_version', Mage::getConfig()->getNode('modules/Fastly_CDN/version'));
61 | Mage::getConfig()->saveConfig('system/full_page_cache/fastly/fastly_ga_cid', $cid);
62 |
63 | $sendInstalledReq = $statistic->sendInstalledReq();
64 |
65 | $installedData = array(
66 | 'action' => $statistic::FASTLY_INSTALLED_FLAG,
67 | 'created_at' => Varien_Date::now(),
68 | 'sent' => $sendInstalledReq
69 | );
70 |
71 | $statistic->setData($installedData);
72 | $statistic->save();
73 | }
74 |
75 | $installer->endSetup();
--------------------------------------------------------------------------------
/app/design/frontend/base/default/template/fastlycdn/page/notices_hook.phtml:
--------------------------------------------------------------------------------
1 |
22 |
23 |
24 | isUserNotAllowSaveCookie()): ?>
25 | generateCookieName(
28 | Fastly_CDN_Model_Esi_Tag_Page_Html_Notices::COOKIE_NAME
29 | );
30 | ?>
31 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Control/Catalog/Category.php:
--------------------------------------------------------------------------------
1 | _canPurge()) {
35 | $this->_purgeById($category->getId());
36 | if ($categoryName = $category->getName()) {
37 | $this->_getSession()->addSuccess(
38 | Mage::helper('fastlycdn')->__('Fastly CDN for "%s" has been purged.', $categoryName)
39 | );
40 | }
41 | }
42 | return $this;
43 | }
44 |
45 | /**
46 | * Purge Category by id
47 | *
48 | * @param int $id
49 | * @return Fastly_CDN_Model_Control_Catalog_Category
50 | */
51 | public function purgeById($id)
52 | {
53 | if ($this->_canPurge()) {
54 | $this->_purgeById($id);
55 | }
56 | return $this;
57 | }
58 |
59 | /**
60 | * Purge Category by id
61 | *
62 | * @param int $id
63 | * @return Fastly_CDN_Model_Control_Catalog_Category
64 | */
65 | protected function _purgeById($id)
66 | {
67 | $surrogateKey = Fastly_CDN_Helper_Tags::SURROGATE_KEY_CATEGORY_PREFIX . $id;
68 | $this->_getCacheControl()->cleanBySurrogateKey($surrogateKey);
69 |
70 | return $this;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Hash/Parameters.php:
--------------------------------------------------------------------------------
1 | _domains;
39 | }
40 |
41 | /**
42 | * @param array $domains
43 | *
44 | * @return $this
45 | */
46 | public function setDomains(array $domains)
47 | {
48 | $this->_domains = $domains;
49 | return $this;
50 | }
51 |
52 | /**
53 | * @return string
54 | */
55 | public function getType()
56 | {
57 | return !empty($this->_type) ? $this->_type : '.*';
58 | }
59 |
60 | /**
61 | * @param string $type
62 | *
63 | * @return $this
64 | */
65 | public function setType($type)
66 | {
67 | $this->_type = $type;
68 | return $this;
69 | }
70 |
71 | /**
72 | * @return string
73 | */
74 | public function getRegexp()
75 | {
76 | return !empty($this->_regexp) ? $this->_regexp : '.*';
77 | }
78 |
79 | /**
80 | * @param string $regexp
81 | *
82 | * @return $this
83 | */
84 | public function setRegexp($regexp)
85 | {
86 | $this->_regexp = $regexp;
87 | return $this;
88 | }
89 |
90 | public function isWildcard()
91 | {
92 | return empty($this->_domains) && empty($this->_regexp) && empty($this->_type);
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/app/design/frontend/base/default/layout/fastlycdn.xml:
--------------------------------------------------------------------------------
1 |
2 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | js_css prototype/windows/themes/default.css
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Release-Notes.md:
--------------------------------------------------------------------------------
1 | # Fastly_Cdn Release Notes
2 |
3 | ## 1.0.32
4 |
5 | - Enable processing of ESIs inside CDATA
6 |
7 | ## 1.0.31
8 |
9 | - Fix for https://github.com/fastly/fastly-magento/issues/50
10 |
11 | ## 1.0.30
12 |
13 | - Add FormKey validation
14 |
15 | ## 1.0.29
16 |
17 | - Add VCL to protect against inadvertent gzipping ESIs
18 |
19 |
20 | ## 1.0.28
21 |
22 | - Add Image Optimization UI
23 |
24 | ## 1.0.27
25 |
26 | - Fix for the ESI FASTLY_CDN-cookie replacement logic https://github.com/fastly/fastly-magento/commit/0575218ceba5bc2dba8b8d37c0aa132f6319c727
27 |
28 | ## 1.0.26
29 |
30 | - Change sales_order_view to sales_order_ to handle all routes https://github.com/fastly/fastly-magento/pull/46
31 | - Fix ESI include path, fix translate warnings https://github.com/fastly/fastly-magento/pull/45
32 |
33 | ## 1.0.25
34 |
35 | - Minor VCL changes
36 |
37 | ## 1.0.24
38 |
39 | - Add code to make sure user doesn't enable FPC in conjunction with Fastly module as that leads to bad behavior
40 | https://github.com/fastly/fastly-magento/pull/43
41 |
42 | ## 1.0.23.
43 |
44 | - Fix inability to do purge all via Fastly UI
45 | - insert js css via layout update https://github.com/fastly/fastly-magento/pull/42
46 |
47 | ## 1.0.22
48 |
49 | - Validate error/maintenance page is smaller than 65535 characters https://github.com/fastly/fastly-magento/pull/41
50 | - Add marker to every HTML page generated by Magento so that only those pages are processed by ESI
51 |
52 | ## 1.0.21
53 |
54 | - added support for replacing admin path and query string parametars in vcl templates https://github.com/fastly/fastly-magento/pull/38
55 |
56 | ## 1.0.20
57 |
58 | - Minor VCL fix to make sure 404 images don't end up overwriting user cookies
59 |
60 | ## 1.0.19
61 |
62 | - No changes except a fix for composer.json
63 |
64 | ## 1.0.18
65 |
66 | - Webhooks support
67 | - Fix for Sales View Order ESI tag error https://github.com/fastly/fastly-magento/pull/37
68 |
69 | ## 1.0.17
70 |
71 | - Minor VCL tweaks
72 |
73 | ## 1.0.16
74 |
75 | - Fix for a case where a Fastly service version doesn't have any ACLs or Dictionaries
76 |
77 | ## 1.0.15
78 |
79 | - Add ability to manage Edge Dictionaries and Edge ACLs directly from the Magento Admin UI
80 |
81 | ## 1.0.14
82 |
83 | - Change quotes for ESI includes from " to ' due to modules like ngx_pagespeed corrupting HTML with " present
84 |
85 | ## 1.0.13
86 |
87 | - New documentation guides
88 | - Minor VCL updates
89 |
--------------------------------------------------------------------------------
/app/design/frontend/base/default/template/fastlycdn/geoip/dialog.phtml:
--------------------------------------------------------------------------------
1 |
22 |
29 | getChildHtml('esiPopup')); ?>
30 |
31 |
32 |
33 |
34 |
35 |
49 |
50 |
71 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Block/Adminhtml/Cache/Additional.php:
--------------------------------------------------------------------------------
1 | getUrl('*/fastlyCdn/cleanStore');
38 | }
39 |
40 | /**
41 | * Get clean cache url
42 | *
43 | * @return string
44 | */
45 | public function getCleanContentTypeUrl()
46 | {
47 | return $this->getUrl('*/fastlyCdn/cleanContentType');
48 | }
49 |
50 | /**
51 | * Returns Quick Purge URL
52 | *
53 | * @return string
54 | */
55 | public function getQuickPurgeUrl()
56 | {
57 | return $this->getUrl('*/fastlyCdn/quickPurge');
58 | }
59 |
60 | /**
61 | * Check if block can be displayed
62 | *
63 | * @return bool
64 | */
65 | public function canShowButton()
66 | {
67 | return Mage::helper('fastlycdn')->isEnabled();
68 | }
69 |
70 | /**
71 | * Get store selection
72 | *
73 | * @return string
74 | */
75 | public function getStoreOptions()
76 | {
77 | $stores = Mage::getModel('adminhtml/system_config_source_store')->toOptionArray();
78 | return $stores;
79 | }
80 |
81 | /**
82 | * Get content types
83 | */
84 | public function getContentTypeOptions()
85 | {
86 | foreach (Mage::getModel('fastlycdn/control')->getContentTypes() as $value => $label) {
87 | $options[] = array('value' => $value, 'label' => $label);
88 | }
89 | return $options;
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Control/Abstract.php:
--------------------------------------------------------------------------------
1 | _helperName) {
44 | return false;
45 | }
46 | return Mage::helper($this->_helperName)->canPurge();
47 | }
48 |
49 | /**
50 | * Get fastlyCDN control model
51 | *
52 | * @return Fastly_CDN_Model_Control
53 | */
54 | protected function _getCacheControl()
55 | {
56 | return Mage::helper('fastlycdn')->getCacheControl();
57 | }
58 |
59 | /**
60 | * Get url rewrite collection
61 | *
62 | * @return Fastly_CDN_Model_Resource_Mysql4_Core_Url_Rewrite_Collection
63 | */
64 | protected function _getUrlRewriteCollection()
65 | {
66 | return Mage::getResourceModel('fastlycdn/core_url_rewrite_collection');
67 | }
68 |
69 | /**
70 | * Get product relation collection
71 | *
72 | * @return Fastly_CDN_Model_Resource_Mysql4_Catalog_Product_Relation_Collection
73 | */
74 | protected function _getProductRelationCollection()
75 | {
76 | return Mage::getResourceModel('fastlycdn/catalog_product_relation_collection');
77 | }
78 |
79 | /**
80 | * Get catalog category product relation collection
81 | *
82 | * @return Fastly_CDN_Model_Resource_Mysql4_Catalog_Product_Relation_Collection
83 | */
84 | protected function _getCategoryProductRelationCollection()
85 | {
86 | return Mage::getResourceModel('fastlycdn/catalog_category_product_collection');
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Helper/Esi.php:
--------------------------------------------------------------------------------
1 | ';
28 |
29 | /**
30 | * return if used magento version uses form keys
31 | *
32 | * @return bool
33 | */
34 | public function hasFormKey()
35 | {
36 | $session = Mage::getSingleton('core/session');
37 |
38 | return method_exists($session, 'getFormKey');
39 | }
40 |
41 | /**
42 | * generate esi tag for form keys
43 | *
44 | * @return string
45 | */
46 | public function getFormKeyEsiTag()
47 | {
48 | $url = Mage::getUrl(
49 | self::ESI_FORMKEY_URL,
50 | array(
51 | '_nosid' => true,
52 | '_secure' => false
53 | )
54 | );
55 | $esiTag = self::ESI_INCLUDE_OPEN . preg_replace("/^https/", "http", $url) . self::ESI_INCLUDE_CLOSE;
56 |
57 | return $esiTag;
58 | }
59 |
60 | /**
61 | * Replace form key with esi tag
62 | *
63 | * @param string $content
64 | * @return string
65 | */
66 | public function replaceFormKey($content)
67 | {
68 | /** @var $session Mage_Core_Model_Session */
69 | $session = Mage::getSingleton('core/session');
70 |
71 | // replace all occurrences of form key with esi tag
72 | $content = str_replace(
73 | $session->getFormKey(),
74 | $this->getFormKeyEsiTag(),
75 | $content
76 | );
77 |
78 | return $content;
79 | }
80 |
81 | /**
82 | * Return the form key value stored in a cookie
83 | * or false if it is not set
84 | *
85 | * @return string|false
86 | */
87 | public function getCookieFormKey()
88 | {
89 | return Mage::getSingleton('core/cookie')->get(self::FORMKEY_COOKIE);
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/Guides/ESI.md:
--------------------------------------------------------------------------------
1 | # ESI example implementation
2 |
3 | We'll explain how to customize ESI fragments by implementing a sample `deliverycountdown/deliveryCountdown` fragment.
4 |
5 | First you will need to insert code below in `config.xml`. It needs to be placed inside parent XML node for `fastlycdn_esi_tags`:
6 |
7 | ```
8 |
9 | deliverycountdown/deliveryCountdown
10 | Fastly_CDN_Model_Esi_Tag_DeliveryCountDown
11 |
12 | ```
13 |
14 | Block node contains type of your block and `esi_tag` custom php class which is in charge of replacing block HTML output with ESI tags.
15 |
16 | In custom class (used in `esi_tag` node) `Fastly_CDN_Model_Esi_Tag_DeliveryCountDown` you should declare two constants:
17 |
18 | `COOKIE_NAME` and `ESI_URL`
19 |
20 | Your custom class should something like this
21 |
22 | ```
23 | class Fastly_CDN_Model_Esi_Tag_DeliveryCountDown
24 | extends Fastly_CDN_Model_Esi_Tag_Abstract
25 | {
26 | const COOKIE_NAME = 'deliverycountdown';
27 | const ESI_URL = 'fastlycdn/esi/deliverycountdown';
28 | }
29 | ```
30 |
31 | After you configure it, ESI directives should be present in HTML source and if ESI debug is on you should see the red
32 | box with ESI URL.
33 |
34 | ## Possible issues with ESI directives
35 |
36 | If you don’t see the ESI directives please investigate following
37 |
38 | 1. If caching is turned on, flush cache then check parent blocks
39 | 2. Check does your custom block fire event `core_block_abstract_to_html_after`. All logic for implementation of
40 | ESI is in observer `Fastly_CDN_Model_Observer` and in method `replaceBlockByEsiTag`
41 |
42 |
43 | ## Example of properly configured ESI
44 |
45 | When ESI is properly configured then page HTML should look like the example below (this is example for cart block):
46 |
47 | ```
48 |
49 |
50 |
51 |
52 |
53 | My Cart
54 |
55 |
56 |
57 |
58 |
You have no items in your shopping cart.
59 |
60 |
61 |
62 |
63 |
64 |
65 | ```
66 |
67 | OPTIONAL: You may possible need to configure Fastly VCL snippets for specific ESI call.
68 |
--------------------------------------------------------------------------------
/Guides/BACKEND-SETTINGS.md:
--------------------------------------------------------------------------------
1 | # Backend settings guide
2 |
3 | This guide will show you how to how to fine tune Fastly’s service performance by configuring Origin shielding and timeout settings.
4 |
5 | ### Origin shielding
6 |
7 | Origin shielding is Fastly’s service feature which reduces the load on your origin server by routing all requests to a specfic **Point of Presence** (POP) which you have designated as a shield node to your origin.
8 |
9 | #### How shielding works
10 |
11 | With shielding enabled, when the first request for content arrives at one of the POP’s, for e.g. **POP A**, POP A doesn’t have that content cached. The request is passed to the **Shield POP** which also doesn’t have the content cached and passes request to the customers **Origin server** to fetch the content and store it in cache. The cached content is then passed to the POP A and served to the user.
12 |
13 | Now, when another request arrives at **POP B** instead of POP A, POP B will pass request to the Shield POP, and since the Shield POP already has a cached copy from the first request, no future requests for the content would be passed along to the customer’s origin server until the shield POP’s cached copy of it expires.
14 |
15 | ### Backend timeouts
16 |
17 | A backend is an address (IP or domain) from which Fastly pulls content. Backend timeouts define how long will Fastly wait for backend operations to complete.
18 |
19 | You can set three different timeouts:
20 |
21 | * Connect timeout – how long to wait for a timeout in milliseconds. (default: 1000ms)
22 | * First byte timeout – limits how long the processing time of the backend may be. (default: 10000ms)
23 | * Between bytes timeout – limits how long we will wait between for two subsequent successful reads on the backend connection. (default: 15000ms)
24 |
25 |
26 | ### Fastly configuration
27 |
28 | You can configure Origin shielding and Backend timeout in the Fastly module by going to:
29 |
30 | ```
31 | Magento admin > System > Configuration > Services > Fastly CDN
32 | ```
33 |
34 | Under the Fastly CDN Configuration, click on the **Backend settings:**
35 |
36 | 
37 |
38 | There you will see a list of backends. Click on the Edit button next to the backend for which you want to configure **Shielding.**
39 |
40 | The modal window will pop up with the following content:
41 |
42 | 
43 |
44 | For the Shield value you should select Datacenter close to your backend. As for backend timeout settings, it’s best to leave default values or set them according to your needs. Press the Upload button in the upper right corner to apply your changes.
45 |
46 | That’s it, you have successfully fine tuned your Fastly service.
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Block/Cookie/Environment.php:
--------------------------------------------------------------------------------
1 | addData(array(
34 | 'cache_lifetime' => false,
35 | 'cache_tags' => array(Mage_Core_Model_Store::CACHE_TAG),
36 | ));
37 | }
38 |
39 | /**
40 | * @return Fastly_CDN_Helper_Environment
41 | */
42 | protected function _getHelper()
43 | {
44 | if (is_null($this->_helper)) {
45 | $this->_helper = Mage::helper('fastlycdn/environment');
46 | }
47 | return $this->_helper;
48 | }
49 |
50 | /**
51 | * Get key pieces for caching block content
52 | *
53 | * @return array
54 | */
55 | public function getCacheKeyInfo()
56 | {
57 | $cacheId = array(
58 | 'FASTLYCDN_COOKIE_ENVIRONMENT_',
59 | Mage::app()->getStore()->getId(),
60 | Mage::getDesign()->getPackageName(),
61 | Mage::getDesign()->getTheme('template'),
62 | Mage::getSingleton('customer/session')->getCustomerGroupId(),
63 | Mage::app()->getStore()->getCurrentCurrencyCode(),
64 | 'template' => $this->getTemplate(),
65 | 'name' => $this->getNameInLayout(),
66 | );
67 | return $cacheId;
68 | }
69 |
70 | /**
71 | * Return value for environment cookie if current env differs from default
72 | *
73 | * @return string
74 | */
75 | public function getEnvironmentHash()
76 | {
77 | return $this->_getHelper()->getEnvironmentHash();
78 | }
79 |
80 | /**
81 | * Return cookie lifetime for environment cookie
82 | *
83 | * @return int
84 | */
85 | public function getCookieLifetime()
86 | {
87 | return $this->_getHelper()->getCookieLiftime();
88 | }
89 |
90 | /**
91 | * Return environment cookie name
92 | *
93 | * @return string
94 | */
95 | public function getCookieName()
96 | {
97 | return $this->_getHelper()->getCookieName();
98 | }
99 | }
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Esi/Processor/Abstract.php:
--------------------------------------------------------------------------------
1 | getLayoutName()) {
35 | $block = Mage::app()->getLayout()->getBlock($layoutName);
36 | $this->_initBlock($block);
37 | $this->_block = $block;
38 | }
39 | }
40 |
41 | /**
42 | * Initializes block environment.
43 | *
44 | * @param mixed $block
45 | * @return void
46 | */
47 | protected function _initBlock($block)
48 | {
49 | return $this;
50 | }
51 |
52 | /**
53 | * Return block HTML
54 | *
55 | * @see Mage_Core_Block_Abstract::toHtml
56 | * @return string
57 | */
58 | public function getHtml()
59 | {
60 | $content = '';
61 | if ($this->_block instanceof Mage_Core_Block_Abstract) {
62 | $debug = $this->_getHelper()->isEsiDebugEnabled();
63 | if ($debug) {
64 | $content .= '';
65 | }
66 |
67 | $content .= $this->_block->toHtml();
68 |
69 | if ($debug) {
70 | $content .= '
';
71 | }
72 | }
73 | return $content;
74 | }
75 |
76 | /**
77 | * @return Fastly_CDN_Helper_Data
78 | */
79 | protected function _getHelper()
80 | {
81 | return Mage::helper('fastlycdn');
82 | }
83 |
84 | /**
85 | * Return TTL for given block.
86 | *
87 | * @param $block string
88 | * @return int
89 | */
90 | public function getEsiBlockTtl($block)
91 | {
92 | $ttl = null;
93 |
94 | // get block specific ttl
95 | $esiBlockTtls = unserialize(Mage::getStoreConfig(self::XML_PATH_FASTLY_CDN_ESI_BLOCK_TTL));
96 | if (is_array($esiBlockTtls)) {
97 | foreach ($esiBlockTtls as $esiBlock) {
98 | if ($esiBlock['regexp'] == $block) {
99 | $ttl = $esiBlock['value'];
100 | }
101 | }
102 | }
103 |
104 | // ttl not set for block - use default
105 | if (is_null($ttl)) {
106 | $ttl = Mage::getStoreConfig(self::XML_PATH_FASTLY_CDN_ESI_DEFAULT_TTL);
107 | }
108 |
109 | return (int)$ttl;
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/skin/adminhtml/default/default/css/fastlycdn/fastly.css:
--------------------------------------------------------------------------------
1 | .overlay_dialog {
2 | background-color: #666666;
3 | filter:alpha(opacity=60);
4 | -moz-opacity: 0.6;
5 | opacity: 0.6;
6 | }
7 |
8 | .overlay___invisible__ {
9 | background-color: #666666;
10 | filter:alpha(opacity=0);
11 | -moz-opacity: 0;
12 | opacity: 0;
13 | }
14 |
15 | .dialog_nw {
16 | width: 9px;
17 | height: 23px;
18 | background: transparent url(default/top_left.gif) no-repeat 0 0;
19 | }
20 |
21 | .dialog_n {
22 | background: transparent url(default/top_mid.gif) repeat-x 0 0;
23 | height: 23px;
24 | }
25 |
26 | .dialog_ne {
27 | width: 9px;
28 | height: 23px;
29 | background: transparent url(default/top_right.gif) no-repeat 0 0;
30 | }
31 |
32 | .dialog_e {
33 | width: 2px;
34 | background: transparent url(default/center_right.gif) repeat-y 0 0;
35 | }
36 |
37 | .dialog_w {
38 | width: 2px;
39 | background: transparent url(default/center_left.gif) repeat-y 0 0;
40 | }
41 |
42 | .dialog_sw {
43 | width: 9px;
44 | height: 19px;
45 | background: transparent url(default/bottom_left.gif) no-repeat 0 0;
46 | }
47 |
48 | .dialog_s {
49 | background: transparent url(default/bottom_mid.gif) repeat-x 0 0;
50 | height: 19px;
51 | }
52 |
53 | .dialog_se {
54 | width: 9px;
55 | height: 19px;
56 | background: transparent url(default/bottom_right.gif) no-repeat 0 0;
57 | }
58 |
59 | .dialog_sizer {
60 | width: 9px;
61 | height: 19px;
62 | background: transparent url(default/sizer.gif) no-repeat 0 0;
63 | cursor:se-resize;
64 | }
65 |
66 | .dialog_close {
67 | width: 14px;
68 | height: 14px;
69 | background: transparent url(default/close.gif) no-repeat 0 0;
70 | position:absolute;
71 | top:5px;
72 | left:8px;
73 | cursor:pointer;
74 | z-index:2000;
75 | }
76 |
77 | .dialog_minimize {
78 | width: 14px;
79 | height: 15px;
80 | background: transparent url(default/minimize.gif) no-repeat 0 0;
81 | position:absolute;
82 | top:5px;
83 | left:28px;
84 | cursor:pointer;
85 | z-index:2000;
86 | }
87 |
88 | .dialog_maximize {
89 | width: 14px;
90 | height: 15px;
91 | background: transparent url(default/maximize.gif) no-repeat 0 0;
92 | position:absolute;
93 | top:5px;
94 | left:49px;
95 | cursor:pointer;
96 | z-index:2000;
97 | }
98 |
99 | .dialog_title {
100 | float:left;
101 | height:14px;
102 | font-family: Tahoma, Arial, sans-serif;
103 | font-size:12px;
104 | text-align:center;
105 | width:100%;
106 | color:#000;
107 | }
108 |
109 | .dialog_content {
110 | overflow:auto;
111 | color: #DDD;
112 | font-family: Tahoma, Arial, sans-serif;
113 | font-size: 10px;
114 | background-color:#123;
115 | }
116 |
117 | .top_draggable, .bottom_draggable {
118 | cursor:move;
119 | }
120 |
121 | .status_bar {
122 | font-size:12px;
123 | }
124 | .status_bar input{
125 | font-size:12px;
126 | }
127 |
128 | .wired_frame {
129 | display: block;
130 | position: absolute;
131 | border: 1px #000 dashed;
132 | }
133 |
134 | /* DO NOT CHANGE THESE VALUES*/
135 | .dialog {
136 | display: block;
137 | position: absolute;
138 | }
139 |
140 | .dialog table.table_window {
141 | border-collapse: collapse;
142 | border-spacing: 0;
143 | width: 100%;
144 | margin: 0px;
145 | padding:0px;
146 | }
147 |
148 | .dialog table.table_window td , .dialog table.table_window th {
149 | padding: 0;
150 | }
151 |
152 | .dialog .title_window {
153 | -moz-user-select:none;
154 | }
155 |
156 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Config.php:
--------------------------------------------------------------------------------
1 | _esiTags)) {
39 | foreach (Mage::getConfig()->getNode('fastlycdn_esi_tags')->children() as $key => $config) {
40 | $this->_esiTags[(string)$key] = array(
41 | 'block' => (string)$config->block,
42 | 'esiTag' => (string)$config->esi_tag,
43 | 'processor' => (string)$config->processor
44 | );
45 | }
46 | }
47 | return $this->_esiTags;
48 | }
49 |
50 | /**
51 | * Get ESI Tag model by block type
52 | *
53 | * @param string $blockType
54 | * @return string
55 | */
56 | public function getEsiTagClassByBlockType($blockType)
57 | {
58 | $config = $this->getEsiTags();
59 | foreach ($config as $esiTag) {
60 | if ($esiTag['block'] == $blockType) {
61 | return $esiTag['esiTag'];
62 | }
63 | }
64 | return false;
65 | }
66 |
67 | /**
68 | * Get ESI processor by config key
69 | *
70 | * @param string $configKey
71 | * @return
72 | */
73 | public function getEsiProcessorConfig($configKey)
74 | {
75 | $esiTags = $this->getEsiTags();
76 |
77 | if (isset($esiTags[$configKey])) {
78 | return $esiTags[$configKey];
79 | }
80 | return false;
81 | }
82 |
83 | public function getVclSnippets($path = 'vcl_snippets', $specificFile = null)
84 | {
85 | $snippetsData = array();
86 |
87 | $moduleEtcPath = Mage::getModuleDir('etc', 'Fastly_CDN') . DS . $path . DS;
88 | $fileReader = new Varien_Io_File();
89 | $fileReader->open(array('path' => $moduleEtcPath));
90 | if (!$specificFile) {
91 | $snippets = $fileReader->ls();
92 | if(is_array($snippets))
93 | {
94 | foreach ($snippets as $snippet) {
95 | if ($snippet['filetype'] != 'vcl') {
96 | continue;
97 | }
98 | $snippetFilePath = $moduleEtcPath . $snippet['text'];
99 | $type = explode('.', $snippet['text'])[0];
100 | $snippetsData[$type] = $fileReader->read($snippetFilePath);
101 | }
102 | }
103 | } else {
104 | $snippetFilePath = $moduleEtcPath . '/' . $specificFile;
105 | $type = explode('.', $specificFile)[0];
106 | $snippetsData[$type] = $fileReader->read($snippetFilePath);
107 | }
108 |
109 | return $snippetsData;
110 | }
111 | }
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Esi/Processor/GeoIp/Action.php:
--------------------------------------------------------------------------------
1 | _getHelper()->isGeoIpEnabled()) {
39 | $layout = Mage::app()->getLayout();
40 | if (Mage::getStoreConfigFlag(self::XML_PATH_GEOIP_SHOW_DIALOG)) {
41 | // show a dialog from CMS block
42 | if ($cmsBlockId = $this->_getMapping(self::XML_PATH_GEOIP_MAP_CMS_BLOCKS, 'cms')) {
43 | $cmsBlock = $layout->createBlock('cms/block')->setBlockId($cmsBlockId);
44 | $output = $layout->createBlock('core/template')
45 | ->setTemplate('fastlycdn/geoip/dialog.phtml')
46 | ->setChild('esiPopup', $cmsBlock)
47 | ->toHtml();
48 | }
49 | } else {
50 | // redirect to another store via JavaScript
51 | if ($redirectTo = $this->_getMapping(self::XML_PATH_GEOIP_MAP_REDIRECT, 'store')) {
52 | $store = Mage::getModel('core/store')->load($redirectTo);
53 | /* @var $store Mage_Core_Model_Store */
54 | if ($store->getId()) {
55 | $redirectUrl = $store->getUrl('', array('_nosid' => true));
56 | $output = $layout->createBlock('core/template')
57 | ->setTemplate('fastlycdn/geoip/redirect.phtml')
58 | ->setRedirectUrl($redirectUrl)
59 | ->toHtml();
60 | }
61 | }
62 | }
63 | }
64 |
65 | return $output;
66 | }
67 |
68 | /**
69 | * get the mapping for a county code
70 | *
71 | * @param string $xmlPath configuration path for mapping
72 | * @param string $key column name of mapping value
73 | *
74 | * @return bool|string
75 | */
76 | protected function _getMapping($xmlPath, $key) {
77 | if ($countryCode = Mage::app()->getRequest()->getParam('country_code')) {
78 | if ($map = Mage::getStoreConfig($xmlPath)) {
79 | $map = unserialize($map);
80 |
81 | if (isset($map['country'])) {
82 | // check for direct match
83 | foreach ($map['country'] as $i => $country) {
84 | if (strtolower($country) == strtolower($countryCode)) {
85 | return $map[$key][$i];
86 | }
87 | }
88 | // check for wildcard
89 | foreach ($map['country'] as $i => $country) {
90 | if ($country == '*') {
91 | return $map[$key][$i];
92 | }
93 | }
94 | }
95 | }
96 | }
97 | return false;
98 | }
99 | }
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Helper/Webhooks.php:
--------------------------------------------------------------------------------
1 | isEnabled()) {
83 | return;
84 | }
85 |
86 | $urlEndpoint = $this->getWebhookUrl();
87 | $username = $this->getWebookUsername();
88 | $channel = '#' . $this->getWebHookChannel();
89 | $messagePrefix = $this->getWebhookMessagePrefix();
90 | $storeName = Mage::app()->getStore()->getName();
91 | $storeUrl = Mage::app()->getStore()->getUrl();
92 | $message = $messagePrefix . ' ' . $message.' on <'.$storeUrl.'|Store> | '.$storeName;
93 | $headers = array('Content-type: application/json');
94 |
95 | $body = json_encode(array(
96 | 'text' => $message,
97 | 'username' => $username,
98 | 'channel' => $channel,
99 | 'icon_emoji' => ':airplane:'
100 | ));
101 |
102 | $curl = new Varien_Http_Adapter_Curl();
103 | $curl->setConfig(array(
104 | 'timeout' => 2
105 | ));
106 | $curl->write(Zend_Http_Client::POST, $urlEndpoint, '1.1', $headers, $body);
107 | if ($curl->read()) {
108 | if ($curl->getInfo(CURLINFO_HTTP_CODE) != 200) {
109 | $response = $curl->read();
110 | Mage::log('Failed to send message to the following Webhook: ' . $urlEndpoint . ' - Response: ' . $response);
111 | }
112 | }
113 |
114 | $curl->close();
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Helper/Environment.php:
--------------------------------------------------------------------------------
1 | getDefaultStoreView();
41 | $defaultLimit = Mage::getStoreConfig('catalog/frontend/list_per_page');
42 |
43 | $defaultSettings = array(
44 | 'storeId' => $defaultStore->getId(),
45 | 'currency' => $defaultStore->getDefaultCurrencyCode(),
46 | 'customerGroup' => Mage_Customer_Model_Group::NOT_LOGGED_IN_ID,
47 | 'limit' => $defaultLimit,
48 | );
49 |
50 | // get current store settings
51 | $currentStore = Mage::app()->getStore();
52 | $currentSettings = array(
53 | 'storeId' => $currentStore->getId(),
54 | 'currency' => $currentStore->getCurrentCurrencyCode(),
55 | 'customerGroup' => Mage::getSingleton('customer/session')->getCustomerGroupId(),
56 | 'limit' => $this->_getCurrentLimit($defaultLimit),
57 | );
58 |
59 | $cookieValue = '';
60 | // only set cookie value if not in default environment
61 | if (array_diff($defaultSettings, $currentSettings)) {
62 | $cookieValue = md5(serialize($currentSettings));
63 | }
64 |
65 | return $cookieValue;
66 | }
67 |
68 | /**
69 | * Return cookie lifetime in ms
70 | *
71 | * @return int
72 | */
73 | public function getCookieLiftime()
74 | {
75 | return (intval($this->_getCookie()->getLifetime() * 1000));
76 | }
77 |
78 | /**
79 | * Sets environment cookie
80 | *
81 | * @return void
82 | */
83 | public function setEnvironmentCookie()
84 | {
85 | if ($envHash = $this->getEnvironmentHash()) {
86 | $this->_getCookie()->set(
87 | self::ENVIRONMENT_COOKIE,
88 | $envHash,
89 | $this->getCookieLiftime()
90 | );
91 | } else {
92 | $this->_getCookie()->delete(self::ENVIRONMENT_COOKIE);
93 | }
94 | }
95 |
96 | /**
97 | * Return the name of the cookie
98 | *
99 | * @return string
100 | */
101 | public function getCookieName()
102 | {
103 | return self::ENVIRONMENT_COOKIE;
104 | }
105 |
106 | /**
107 | * @return Mage_Core_Model_Cookie
108 | */
109 | protected function _getCookie()
110 | {
111 | return Mage::getSingleton('core/cookie');
112 | }
113 |
114 | /**
115 | * Return current pagination limit
116 | *
117 | * @param int $defaultLimit
118 | *
119 | * @return int
120 | */
121 | protected function _getCurrentLimit($defaultLimit)
122 | {
123 | $currentLimit = Mage::getSingleton('catalog/session')->getLimitPage();
124 | if (is_null($currentLimit) === false) {
125 | return $currentLimit;
126 | }
127 |
128 | return $defaultLimit;
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/app/design/adminhtml/default/default/template/fastlycdn/cache/additional.phtml:
--------------------------------------------------------------------------------
1 |
22 |
23 | canShowButton()): ?>
24 |
44 |
45 |
65 |
66 |
82 |
83 |
88 |
89 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Controller/Router.php:
--------------------------------------------------------------------------------
1 | getEvent()->getFront();
32 | /* @var $front Mage_Core_Controller_Varien_Front */
33 | $front->addRouter('fastlyCDN', $this);
34 | }
35 |
36 | /**
37 | * Validate and Match Cms Page and modify request
38 | *
39 | * @param Zend_Controller_Request_Http $request
40 | * @return bool
41 | */
42 | public function match(Zend_Controller_Request_Http $request)
43 | {
44 | $front = $this->getFront();
45 | $path = trim($request->getPathInfo(), '/');
46 |
47 | if ($path) {
48 | $p = explode('/', $path);
49 | }
50 |
51 | // get module name
52 | if ($request->getModuleName()) {
53 | $module = $request->getModuleName();
54 | } else {
55 | if (!empty($p[0])) {
56 | $module = $p[0];
57 | }
58 | }
59 |
60 | if ($module != 'fastlycdn') {
61 | return false;
62 | }
63 |
64 | // we only handle Fastly CDN requests
65 | $realModule = 'Fastly_CDN';
66 |
67 | $request->setRouteName($this->getRouteByFrontName($module));
68 |
69 | // get controller name
70 | if ($request->getControllerName()) {
71 | $controller = $request->getControllerName();
72 | } else {
73 | if (!empty($p[1])) {
74 | $controller = $p[1];
75 | } else {
76 | $controller = $front->getDefault('controller');
77 | $request->setAlias(
78 | Mage_Core_Model_Url_Rewrite::REWRITE_REQUEST_PATH_ALIAS,
79 | ltrim($request->getOriginalPathInfo(), '/')
80 | );
81 | }
82 | }
83 |
84 | // get action name
85 | if (empty($action)) {
86 | if ($request->getActionName()) {
87 | $action = $request->getActionName();
88 | } else {
89 | $action = !empty($p[2]) ? $p[2] : $front->getDefault('action');
90 | }
91 | }
92 |
93 | $controllerClassName = $this->_validateControllerClassName($realModule, $controller);
94 | if (!$controllerClassName) {
95 | return false;
96 | }
97 |
98 | // instantiate controller class
99 | $controllerInstance = Mage::getControllerInstance($controllerClassName, $request, $front->getResponse());
100 |
101 | if (!$controllerInstance->hasAction($action)) {
102 | $action = 'processor';
103 | }
104 |
105 | // set values only after all the checks are done
106 | $request->setModuleName($module);
107 | $request->setControllerName($controller);
108 | $request->setActionName($action);
109 | $request->setControllerModule($realModule);
110 |
111 | // set parameters from pathinfo
112 | for ($i = 3, $l = sizeof($p); $i < $l; $i += 2) {
113 | $request->setParam($p[$i], isset($p[$i+1]) ? urldecode($p[$i+1]) : '');
114 | }
115 |
116 | // dispatch action
117 | $request->setDispatched(true);
118 | $controllerInstance->dispatch($action);
119 |
120 | return true;
121 | }
122 | }
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Esi/Processor/GeoIp/Getcountry.php:
--------------------------------------------------------------------------------
1 | getRemoteAddr()) {
36 | // reduce multiple ip list to only first ip
37 | if (strpos($clientIP, ',')) {
38 | list($clientIP) = explode(',', $clientIP);
39 | }
40 |
41 | // try to get current country code
42 | if (function_exists('geoip_country_code_by_name')) {
43 | // by ip address
44 | $clientCountry = @geoip_country_code_by_name($clientIP);
45 | } else {
46 | // try to use the accepted language instead
47 | // this is based on customer browser settings
48 | // !!! this is not the country but the language !!!
49 | $clientCountry = $this->_getAcceptedLanguages();
50 | }
51 | }
52 |
53 | if($clientCountry) {
54 | // normalize client country to ISO 3166
55 | if(!is_array($clientCountry)) {
56 | $clientCountry = array($clientCountry);
57 | }
58 | $countries = array();
59 | foreach($clientCountry as $country) {
60 | $country = substr($country, 0, 2);
61 | if (!in_array($country, $countries)) {
62 | $countries[] = $country;
63 | }
64 | }
65 |
66 | // build ESI tag
67 | $esiUrl = Mage::app()->getStore()->getUrl(
68 | 'fastlycdn/esi/getcountryaction',
69 | array(
70 | '_query' => array(
71 | 'country_code' => strtoupper($countries[0])
72 | ),
73 | '_nosid' => true
74 | )
75 | );
76 | $output = Fastly_CDN_Helper_Esi::ESI_INCLUDE_OPEN
77 | . preg_replace("/^https/", "http", $esiUrl)
78 | . Fastly_CDN_Helper_Esi::ESI_INCLUDE_CLOSE;
79 | }
80 |
81 | return $output;
82 | }
83 |
84 | /**
85 | * get the list of accepted languages from the browser
86 | *
87 | * @return array
88 | */
89 | protected function _getAcceptedLanguages()
90 | {
91 | $acceptedLanguages = array();
92 |
93 | if ($acceptLanguage = Mage::helper('core/http')->getHttpAcceptLanguage()) {
94 | // iterate over accepted languages
95 | $languageList = explode(',', $acceptLanguage);
96 | foreach ($languageList as $accept) {
97 | // extract language parts
98 | // we only deal with the primary language tag
99 | if (preg_match('/([a-z]+)(;q=([0-9.]+))?/', trim($accept), $parts)) {
100 | $acceptedLanguages[] = $parts[1];
101 | $quality[] = (isset($parts[3]) ? (float)$parts[3] : 1.0);
102 | }
103 | }
104 |
105 | // order the codes by quality
106 | array_multisort($quality, SORT_NUMERIC, SORT_DESC, $acceptedLanguages);
107 | }
108 |
109 | return $acceptedLanguages;
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/Guides/INSTALLATION.md:
--------------------------------------------------------------------------------
1 | # Installation guide
2 |
3 | This guide will show you how to install and configure Fastly CDN extension for Magento 1.
4 |
5 | You may choose between two installation methods – composer installation and manual installation by downloading the zip file.
6 |
7 | We will go with a second approach - manually downloading the [zip file](https://github.com/fastly/fastly-magento/releases]).
8 |
9 | 1. Download the zip archive of this repository to a temporary location on your server and extract it.
10 | 2. Copy the contents of the app directory in the archive to the app directory of your Magento instance.
11 | 3. Go to the Magento backend and open the Cache Management (System -> Cache Management) and refresh the configuration and layout cache.
12 | 3. Due to Magento's permission system, please log out and log in again before continuing with the next step.
13 |
14 | If you want to install via composer, you can read step by step instructions [here](../README.md#installation-using-composerjson).
15 |
16 | That’s it, you have successfully installed the Fastly CDN extension. Let’s move to configuration.
17 |
18 | ###Configuration
19 |
20 | In order to use the Fastly Cdn extension, you will have to [register a free Fastly account](https://www.fastly.com/signup).
21 |
22 | Once you register and verify your account, login to Fastly:
23 |
24 | 
25 |
26 | You will see a welcome wizard with two input fields which you should fill with:
27 |
28 | * Your website domain for Fastly to use when routing requests
29 | * The hostname (or IP address) and port number for your origin server
30 |
31 | On the next screen, Fastly is offering you to enable gzip, logging and health check of your origin – you can enable this later. Click continue.
32 |
33 | 
34 |
35 | On the final screen, you will have to **point your CNAME to Fastly.** Doing this, you will direct traffic from the Internet through Fastly instead of immediately through your store. You can read more here on how to achieve this.
36 |
37 | 
38 |
39 | Once you’ve finished with pointing your CNAME to Fastly, let’s configure Magento.
40 |
41 | Login to you Magento admin and go to:
42 | ```
43 | System > Configuration > Services > Fastly CDN
44 | ```
45 |
46 | Under the **General Settings** tab, set **Enable cache module** to **Yes** and then enter your **Fastly Service ID*** and **Fastly API key****.
47 |
48 | 
49 |
50 | **To find out you Service ID, login to the Fastly dashboard, locate your **Service name** and click on the **Show Service ID** link.*
51 |
52 | 
53 |
54 | ***To find out your API key, while in the Fastly dashboard, select **Account** from the user menu and scroll way down to the bottom of the page. In the **Account API Key** area, click the **Show** button.*
55 |
56 | 
57 |
58 | You can press the **Test credentials** button just to make sure that you have entered valid credentials.
59 |
60 | 
61 |
62 | If you have received a success message, press the **Save Config** button.
63 |
64 | 
65 |
66 | The final step is to upload the **VCL to Fastly.** You can do this by pressing the **Upload VCL to Fastly** button.
67 |
68 | The modal window will pop up, make sure that the **Activate VCL after upload** is ticked and press the **Upload** button in the top right corner:
69 |
70 | 
71 |
72 | Once the upload process is done, the modal window will automatically close and the success message will show:
73 |
74 | 
75 |
76 | That’s it, you have successfully configured your Magento store with the Fastly CDN.
77 |
78 | ### General settings
79 |
80 | You can read more about general settings [here](../README.md#31-general-settings).
81 |
82 | ### Purging
83 |
84 | You can purge Fastly CDN content through the Magento admin by going to System > Cache Management. You can purge content by the following options:
85 |
86 | * Purge by content type
87 | * Purge by store
88 | * Purge a URL
89 | * Purge all
90 |
91 | You can read more about purging [here](../README.md#4-cache-cleaning-purge-requests).
92 |
93 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/sql/fastlycdn_setup/install-0.1.0.php:
--------------------------------------------------------------------------------
1 | getCollection()->addFieldToFilter('identifier', $data['identifier']);
32 |
33 | foreach($_blocks as $_block) {
34 | $block = Mage::getModel('cms/block')->load($_block->getId());
35 | if (count(array_intersect($block->getStores(), $data['stores'])) == count($block->getStores())) {
36 | $found = true;
37 |
38 | foreach ($data as $key => $value) {
39 | $block->setData($key, $value);
40 | }
41 | $block->save();
42 |
43 | break;
44 | }
45 | }
46 |
47 | if ($found == false) {
48 | Mage::getModel('cms/block')->setData($data)->save();
49 | }
50 | }
51 | }
52 |
53 | $installer = $this;
54 | /* @var $installer Mage_Core_Model_Resource_Setup */
55 |
56 | $installer->startSetup();
57 |
58 | $cmsBlockGeoIp_EN = '
59 |
65 |
66 |
✖
67 |
Notice
68 |
This shop will not sell to your country. Please visit one of our other online shops.
69 |
please select country Deutschland
70 |
load
71 |
72 | ';
73 |
74 | $cmsBlockGeoIp_DE = '
75 |
81 |
82 |
✖
83 |
Notice
84 |
Dieser Shop liefert nicht in Ihr Land. Bitte besuchen Sie einen unserer anderen Online-Shops.
85 |
please select country United Kingdom
86 |
weiter
87 |
88 | ';
89 |
90 | /**
91 | * add CMS blocks for GeoIP modal windows
92 | */
93 | saveCmsBlocks(array(
94 | array(
95 | 'title' => 'Fastly CDN GeoIp dialog in English',
96 | 'identifier' => 'fastly_cdn_geoip_dialog_EN',
97 | 'content' => $cmsBlockGeoIp_EN,
98 | 'is_active' => 1,
99 | 'stores' => array(0)
100 | ),
101 | array(
102 | 'title' => 'Fastly CDN GeoIp dialog in German',
103 | 'identifier' => 'fastly_cdn_geoip_dialog_DE',
104 | 'content' => $cmsBlockGeoIp_DE,
105 | 'is_active' => 1,
106 | 'stores' => array(0)
107 | ),
108 | ));
109 |
110 |
111 | $installer->endSetup();
112 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/etc/vcl_snippets/fetch.vcl:
--------------------------------------------------------------------------------
1 | if (beresp.status >= 500 && beresp.status < 600) {
2 | /* deliver stale if the object is available */
3 | if (stale.exists) {
4 | return(deliver_stale);
5 | }
6 |
7 | if (req.restarts < 1 && (req.request == "GET" || req.request == "HEAD")) {
8 | restart;
9 | }
10 |
11 | /* else go to vcl_error to deliver a synthetic */
12 | error beresp.status beresp.response;
13 |
14 | }
15 |
16 | if (beresp.http.X-Esi) {
17 | # enable ESI feature for Magento response by default
18 | esi;
19 | if (!beresp.http.Vary ~ "Fastly-Cdn-Env,Https") {
20 | if (beresp.http.Vary) {
21 | set beresp.http.Vary = beresp.http.Vary ",Fastly-Cdn-Env,Https";
22 | } else {
23 | set beresp.http.Vary = "Fastly-Cdn-Env,Https";
24 | }
25 | }
26 | # Since varnish doesn't compress ESIs we need to hint to the HTTP/2 terminators to
27 | # compress it
28 | set beresp.http.x-compress-hint = "on";
29 | } else {
30 | # enable gzip for all static content
31 | if (http_status_matches(beresp.status, "200,404") && (beresp.http.content-type ~ "^(application\/x\-javascript|text\/css|text\/html|application\/javascript|text\/javascript|application\/json|application\/vnd\.ms\-fontobject|application\/x\-font\-opentype|application\/x\-font\-truetype|application\/x\-font\-ttf|application\/xml|font\/eot|font\/opentype|font\/otf|image\/svg\+xml|image\/vnd\.microsoft\.icon|text\/plain)\s*($|;)" || req.url.ext ~ "(?i)(css|js|html|eot|ico|otf|ttf|json)" ) ) {
32 | # always set vary to make sure uncompressed versions dont always win
33 | if (!beresp.http.Vary ~ "Accept-Encoding") {
34 | if (beresp.http.Vary) {
35 | set beresp.http.Vary = beresp.http.Vary ", Accept-Encoding";
36 | } else {
37 | set beresp.http.Vary = "Accept-Encoding";
38 | }
39 | }
40 | if (req.http.Accept-Encoding == "gzip") {
41 | set beresp.gzip = true;
42 | }
43 | }
44 | }
45 |
46 | # Just in case the Request Setting for x-pass is missing
47 | if (req.http.x-pass) {
48 | return (pass);
49 | }
50 |
51 | # Force any responses with private, no-cache or no-store in Cache-Control to pass
52 | if (beresp.http.Cache-Control ~ "private|no-cache|no-store") {
53 | set req.http.Fastly-Cachetype = "PRIVATE";
54 | return (pass);
55 | }
56 |
57 | # Varnish sets default TTL if none of these are present. Assume if they are not present that we don't want to cache
58 | if (!beresp.http.Expires && !beresp.http.Surrogate-Control ~ "max-age" && !beresp.http.Cache-Control ~ "(s-maxage|max-age)") {
59 | set beresp.ttl = 0s;
60 | set beresp.cacheable = false;
61 | }
62 |
63 | # If origin provides TTL for an object we cache it
64 | if ( beresp.ttl > 0s && (req.request == "GET" || req.request == "HEAD") && !req.http.x-pass ) {
65 | # Don't cache cookies - this is here because Magento sets cookies even for anonymous users
66 | # which busts cache
67 | unset beresp.http.set-cookie;
68 |
69 | # If surrogate keys have been set do not set them again
70 | if ( !beresp.http.surrogate-keys-set ) {
71 | if (beresp.http.x-esi) {
72 | # init surrogate keys
73 | if (beresp.http.Surrogate-Key) {
74 | set beresp.http.Surrogate-Key = beresp.http.Surrogate-Key " text";
75 | } else {
76 | set beresp.http.Surrogate-Key = "text";
77 | }
78 | } else if (beresp.http.Content-Type ~ "(image|script|css)") {
79 | # set surrogate keys by content type if they are image/script or CSS
80 | if (beresp.http.Surrogate-Key) {
81 | set beresp.http.Surrogate-Key = beresp.http.Surrogate-Key " " re.group.1;
82 | } else {
83 | set beresp.http.Surrogate-Key = re.group.1;
84 | }
85 | }
86 |
87 | set beresp.http.surrogate-keys-set = "1";
88 | }
89 |
90 | }
91 |
92 | # If for whatever reason we get a 404 on static asset requests make sure we strip out set-cookies. Otherwise we run
93 | # the risk of resetting the session since we strip out user cookies for static paths
94 | if (beresp.status == 404 && req.url.path ~ "^/(media|js|skin)/.*\.(png|jpg|jpeg|gif|css|js|swf|ico|webp|svg)$") {
95 | unset beresp.http.set-cookie;
96 | }
97 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Control/Catalog/Product.php:
--------------------------------------------------------------------------------
1 | _canPurge()) {
37 | $idsToPurge = array();
38 | $categoryIdsToPurge = array();
39 | $idsToPurge[] = $product->getId();
40 | $this->_getSession()->addSuccess(
41 | Mage::helper('fastlycdn')->__('Fastly CDN for "%s" has been purged.', $product->getName())
42 | );
43 |
44 | if ($purgeParentProducts) {
45 | // purge parent products
46 | $productRelationCollection = $this->_getProductRelationCollection()
47 | ->filterByChildId($product->getId());
48 | foreach ($productRelationCollection as $productRelation) {
49 | $idsToPurge[] = $productRelation->getParentId();
50 | }
51 | // purge categories of parent products
52 | if ($purgeCategories) {
53 | $categoryProductCollection = $this->_getCategoryProductRelationCollection()
54 | ->filterAllByProductIds($productRelationCollection->getAllIds());
55 |
56 | foreach ($categoryProductCollection as $categoryProduct) {
57 | $categoryIdsToPurge[] = $categoryProduct->getCategoryId();
58 | }
59 | }
60 | }
61 |
62 | $this->_purgeByIds($idsToPurge);
63 |
64 | if ($purgeCategories) {
65 | foreach ($product->getCategoryCollection() as $category) {
66 | $categoryIdsToPurge[] = $category->getId();
67 | }
68 | $this->_getSession()->addSuccess(
69 | Mage::helper('fastlycdn')->__('Fastly CDN for the product\'s categories has been purged.')
70 | );
71 | }
72 |
73 | $this->_purgeCategoriesByIds($categoryIdsToPurge);
74 | }
75 | return $this;
76 | }
77 |
78 | /**
79 | * Purge product by id
80 | *
81 | * @param int $id
82 | * @param bool $purgeParentProducts
83 | * @param bool $purgeCategories
84 | * @return Fastly_CDN_Model_Control_Catalog_Product
85 | */
86 | public function purgeById($id, $purgeParentProducts = false, $purgeCategories = false)
87 | {
88 | $product = Mage::getModel('catalog/product')->load($id);
89 | return $this->purge($product, $purgeParentProducts, $purgeCategories);
90 | }
91 |
92 | /**
93 | * Purge product by ids
94 | *
95 | * @param $ids
96 | *
97 | * @return Fastly_CDN_Model_Control_Catalog_Product
98 | */
99 | protected function _purgeCategoriesByIds($ids)
100 | {
101 | foreach ($ids as $id) {
102 | $surrogateKey = Fastly_CDN_Helper_Tags::SURROGATE_KEY_CATEGORY_PREFIX . $id;
103 | $this->_getCacheControl()->cleanBySurrogateKey($surrogateKey);
104 | }
105 | }
106 |
107 | /**
108 | * Purge product by ids
109 | *
110 | * @param $ids
111 | *
112 | * @return Fastly_CDN_Model_Control_Catalog_Product
113 | */
114 | protected function _purgeByIds($ids)
115 | {
116 | foreach ($ids as $id) {
117 | $surrogateKey = Fastly_CDN_Helper_Tags::SURROGATE_KEY_PRODUCT_PREFIX . $id;
118 | $this->_getCacheControl()->cleanBySurrogateKey($surrogateKey);
119 | }
120 |
121 | return $this;
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/controllers/EsiController.php:
--------------------------------------------------------------------------------
1 | _getHelper()->getActionFromRequest()) {
33 |
34 | $processor = $this->_getHelper()->getProcessorByAction($action);
35 | if ($processor === false) {
36 | $processor = self::DEFAULT_PROCESSOR_NAME;
37 | }
38 | /* @var $processor Fastly_CDN_Model_Esi_Processor_Abstract */
39 |
40 | $this->_prepareLayout();
41 |
42 | $requestParams = $this->getRequest()->getParams();
43 | $this->_emulateSecureRequest($requestParams);
44 |
45 | $processorModel = Mage::getModel($processor, $requestParams);
46 | // get block content
47 | if ($processorModel instanceof Fastly_CDN_Model_Esi_Processor_Abstract) {
48 | $content = $processorModel->getHtml();
49 | }
50 |
51 | Mage::helper('fastlycdn/cache')->setTtlHeader($processorModel->getEsiBlockTtl($action));
52 | Mage::register(Fastly_CDN_Helper_Cache::REGISTRY_VAR_FASTLY_CDN_CONTROL_HEADERS_SET_FLAG, 1);
53 |
54 | } else {
55 | $content = Mage::helper('fastlycdn')->__('No Fastly CDN ESI action given');
56 | }
57 |
58 | $this->getResponse()->setBody($content);
59 | }
60 |
61 | /**
62 | * @return Fastly_CDN_Helper_Data
63 | */
64 | protected function _getHelper()
65 | {
66 | return Mage::helper('fastlycdn');
67 | }
68 |
69 | /**
70 | * Layout necessary layout handles
71 | *
72 | * @return void
73 | */
74 | protected function _prepareLayout()
75 | {
76 | if ($layoutHandles = $this->getRequest()->getParam($this->_getHelper()->getLayoutHandlesParam())) {
77 | // set fake category and product
78 | Mage::register('current_category', Mage::getModel('catalog/category'));
79 | Mage::register('product', Mage::getModel('catalog/product'));
80 |
81 | // if current product id exists, register current product
82 | if($currentProductId = $this->getRequest()->getParam($this->_getHelper()->getCurrentProductIdParam())) {
83 | $currentProduct = Mage::getModel('catalog/product')
84 | ->setStoreId(Mage::app()->getStore()->getId())
85 | ->load($currentProductId);
86 |
87 | Mage::register('current_product', $currentProduct);
88 | }
89 |
90 | // add handles
91 | $update = $this->getLayout()->getUpdate();
92 | $existingHandles = $update->getHandles();
93 |
94 | foreach (explode(',', $layoutHandles) as $handle) {
95 | if (!in_array($handle, $existingHandles)) {
96 | $update->addHandle($handle);
97 | }
98 | }
99 |
100 | // update layout blocks
101 | $this->loadLayoutUpdates();
102 | $this->generateLayoutXml()->generateLayoutBlocks();
103 | } else {
104 | $this->loadLayout();
105 | }
106 | }
107 |
108 | /**
109 | * If is_secure param is set emulate secure request to get correct URLs in block
110 | *
111 | * @see Mage_Core_Model_Store::isCurrentlySecure
112 | * @param array request parameters
113 | * @return void
114 | */
115 | protected function _emulateSecureRequest(Array $params)
116 | {
117 | $isSecureParam = $this->_getHelper()->getIsSecureParam();
118 | if (isset($params[$isSecureParam]) && $params[$isSecureParam] === '1') {
119 | // hard set HTTPS server environment variable to "on"
120 | $_SERVER['HTTPS'] = 'on';
121 | }
122 | }
123 | }
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Model/Esi/Tag/Abstract.php:
--------------------------------------------------------------------------------
1 | ';
25 | const ESI_REMOVE_END_TAG = '';
26 | const COOKIE_NAME = '';
27 | const ESI_URL = '';
28 |
29 | /**
30 | * Return ESI include tag with params for this block.
31 | *
32 | * @param Mage_Core_Block_Abstract
33 | * @return string
34 | */
35 | public function getEsiIncludeTag(Mage_Core_Block_Abstract $block)
36 | {
37 | $esiTag = '';
38 |
39 | if (($esiUrl = $this->_getEsiUrl()) && ($cookieName = $this->_getEsiCookieName())) {
40 |
41 | // check if current product exists in registry and obtain current product id
42 | $currentProductId = null;
43 |
44 | if(Mage::registry('current_product')) {
45 | $currentProductId = Mage::registry('current_product')->getId();
46 | }
47 |
48 | // set ESI parameters to determine block properties in URL
49 | $query = array(
50 | $this->_getHelper()->getLayoutNameParam() => $this->getLayoutName(),
51 | $this->_getHelper()->getEsiDataParam() => $cookieName,
52 | $this->_getHelper()->getLayoutHandlesParam() => $this->_getLayoutHandles($block),
53 | $this->_getHelper()->getIsSecureParam() => Mage::app()->getStore()->isCurrentlySecure() ? '1' : '0',
54 | $this->_getHelper()->getCurrentProductIdParam() => $currentProductId
55 | );
56 |
57 | // add additional (block specific) query params
58 | if ($additionalQueryParams = $this->_getAdditionalQueryParams()) {
59 | $query = array_merge($query, $additionalQueryParams);
60 | }
61 |
62 | $url = Mage::getUrl($esiUrl, array('_nosid' => true, '_query' => $query));
63 |
64 | // make url relative
65 | $url = str_replace(Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB), '/', $url);
66 |
67 | $esiTag = Fastly_CDN_Helper_Esi::ESI_INCLUDE_OPEN
68 | . preg_replace("/^https/", "http", $url)
69 | . Fastly_CDN_Helper_Esi::ESI_INCLUDE_CLOSE;
70 |
71 | // add plain ESI include URL for debugging
72 | if ($this->_getHelper()->isEsiDebugEnabled()) {
73 | $esiTag .= '' . $url . ' ';
74 | }
75 | }
76 |
77 | return $esiTag;
78 | }
79 |
80 | /**
81 | * @return string
82 | */
83 | public function getStartRemoveTag()
84 | {
85 | return self::ESI_REMOVE_START_TAG;
86 | }
87 |
88 | /**
89 | * @return string
90 | */
91 | public function getEndRemoveTag()
92 | {
93 | return self::ESI_REMOVE_END_TAG;
94 | }
95 |
96 | /**
97 | * @return string
98 | */
99 | protected function _getEsiUrl()
100 | {
101 | return $this::ESI_URL;
102 | }
103 |
104 | /**
105 | * @return string
106 | */
107 | protected function _getEsiCookieName()
108 | {
109 | return $this::COOKIE_NAME;
110 | }
111 |
112 | /**
113 | * Get active layout handles
114 | *
115 | * @param Mage_Core_Block_Abstract
116 | * @return array
117 | */
118 | protected function _getLayoutHandles(Mage_Core_Block_Abstract $block)
119 | {
120 | // get all layout handles of current page
121 | $handles = $block->getLayout()->getUpdate()->getHandles();
122 |
123 | /**
124 | * skip these layout handles as they are causing to many unnecessary ESI block variants when added to the URL.
125 | */
126 | $skipHandles = array('CATEGORY_', 'PRODUCT_', 'STORE_', 'customer_', 'THEME_', 'SHORTCUT_', 'page_','cms_', 'catalogsearch_', 'sales_order_');
127 | foreach ($handles as $key => $val) {
128 | // remove category handle
129 | foreach ($skipHandles as $skipHandle) {
130 | if (strpos($val, $skipHandle) === 0) {
131 | unset($handles[$key]);
132 | }
133 | }
134 | }
135 |
136 | return implode(',', $handles);
137 | }
138 |
139 | /**
140 | * @return Fastly_CDN_Helper_Data
141 | */
142 | protected function _getHelper()
143 | {
144 | return Mage::helper('fastlycdn');
145 | }
146 |
147 | /**
148 | * @return null|array
149 | */
150 | protected function _getAdditionalQueryParams()
151 | {
152 | return null;
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/Block/Adminhtml/System/Config/Fieldset/StoreMap.php:
--------------------------------------------------------------------------------
1 | setElement($element);
35 |
36 | $html = '';
37 | $html .= $this->_getRowTemplateHtml(-1);
38 | $html .= '
';
39 |
40 | $html .= '';
41 | $html .= '
';
42 |
43 | $html .= '';
44 | $html .= ''.$this->__('Country').' ';
45 | $html .= ''.$this->__('Store').' ';
46 | $html .= ' ';
47 | $html .= ' ';
48 |
49 | if ($this->_getValue('store')) {
50 | foreach ($this->_getValue('store') as $i=>$f) {
51 | if ($i) {
52 | $html .= $this->_getRowTemplateHtml($i);
53 | }
54 | }
55 | }
56 | $html .= '
';
57 | $html .= $this->_getAddRowButtonHtml('fastlycdn_geoip_map_redirect',
58 | 'fastlycdn_geoip_map_redirect_template', $this->__('Add mapping'));
59 | $html .= '
';
60 |
61 | return $html;
62 | }
63 |
64 | /**
65 | * @param int $i
66 | * @return string
67 | */
68 | protected function _getRowTemplateHtml($i=0)
69 | {
70 | $html = '';
71 |
72 | $html .= '';
73 | $html .= ' ';
74 | $html .= ' ';
75 |
76 | $html .= '';
77 | $html .= '';
78 | $html .= ''.$this->__('* Select store').' ';
79 | foreach ($this->_getStore() as $store) {
80 | $html .= '_getSelected('store/'.$i, $store['value']).' >'.$store['label'].' ';
81 | }
82 | $html .= ' ';
83 | $html .= ' ';
84 |
85 | $html .= '';
86 | $html .= $this->_getRemoveRowButtonHtml();
87 | $html .= ' ';
88 |
89 | $html .= ' ';
90 |
91 | return $html;
92 | }
93 |
94 | /**
95 | * @return mixed
96 | */
97 | protected function _getStore()
98 | {
99 | return Mage::getModel('Mage_Adminhtml_Model_System_Config_Source_Store')->toOptionArray();
100 | }
101 |
102 | /**
103 | * @return string
104 | */
105 | protected function _getDisabled()
106 | {
107 | return $this->getElement()->getDisabled() ? ' disabled' : '';
108 | }
109 |
110 | /**
111 | * @param $key
112 | * @return mixed
113 | */
114 | protected function _getValue($key)
115 | {
116 | return $this->getElement()->getData('value/'.$key);
117 | }
118 |
119 | /**
120 | * @param $key
121 | * @param $value
122 | * @return string
123 | */
124 | protected function _getSelected($key, $value)
125 | {
126 | return $this->getElement()->getData('value/'.$key)==$value ? 'selected="selected"' : '';
127 | }
128 |
129 | /**
130 | * @param $container
131 | * @param $template
132 | * @param string $title
133 | * @return mixed
134 | */
135 | protected function _getAddRowButtonHtml($container, $template, $title='Add')
136 | {
137 | if (!isset($this->_addRowButtonHtml[$container])) {
138 | $this->_addRowButtonHtml[$container] = $this->getLayout()->createBlock('adminhtml/widget_button')
139 | ->setType('button')
140 | ->setClass('add '.$this->_getDisabled())
141 | ->setLabel($this->__($title))
142 | ->setOnClick("Element.insert($('".$container."'), {bottom: $('".$template."').innerHTML})")
143 | ->setDisabled($this->_getDisabled())
144 | ->toHtml();
145 | }
146 | return $this->_addRowButtonHtml[$container];
147 | }
148 |
149 | /**
150 | * @param string $selector
151 | * @param string $title
152 | * @return array
153 | */
154 | protected function _getRemoveRowButtonHtml($selector='tr', $title='Delete')
155 | {
156 | if (!$this->_removeRowButtonHtml) {
157 | $this->_removeRowButtonHtml = $this->getLayout()->createBlock('adminhtml/widget_button')
158 | ->setType('button')
159 | ->setClass('delete v-middle '.$this->_getDisabled())
160 | ->setLabel($this->__($title))
161 | ->setOnClick("Element.remove($(this).up('".$selector."'))")
162 | ->setDisabled($this->_getDisabled())
163 | ->toHtml();
164 | }
165 | return $this->_removeRowButtonHtml;
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/app/code/community/Fastly/CDN/etc/vcl_snippets/recv.vcl:
--------------------------------------------------------------------------------
1 | # Fixup for Varnish ESI not dealing with https:// absolute URLs well
2 | if (req.is_esi_subreq && req.url ~ "/https://([^/]+)(/.*)$") {
3 | set req.http.Host = re.group.1;
4 | set req.url = re.group.2;
5 | }
6 |
7 | # Pass any checkout, cart or customer/myaccount urls
8 | if (req.url.path ~ "/(cart|checkout|customer)") {
9 | set req.http.x-pass = "1";
10 | # Pass all admin actions
11 | } else if (req.url.path ~ "^/(index\.php/)?####ADMIN_PATH####/") {
12 | set req.http.x-pass = "1";
13 | # bypass language switcher
14 | } else if (req.url.qs ~ "(?i)___from_store=.*&___store=.*") {
15 | set req.http.x-pass = "1";
16 | }
17 |
18 | # set HTTPS header for offloaded TLS
19 | if (req.http.Fastly-SSL) {
20 | set req.http.Https = "on";
21 | }
22 |
23 | if (req.http.cookie:FASTLY_CDN_ENV) {
24 | set req.http.Fastly-Cdn-Env = req.http.cookie:FASTLY_CDN_ENV;
25 | } else {
26 | unset req.http.Fastly-Cdn-Env;
27 | }
28 |
29 | ############################################################################################################
30 | # Following code block controls purge by URL. By default we want to protect all URL purges. In general this
31 | # is addressed by adding Fastly-Purge-Requires-Auth request header in vcl_recv however this runs the risk of
32 | # exposing API tokens if user attempts to purge non-https URLs. For this reason inside the Magento module
33 | # we use X-Purge-Token. Unfortunately this breaks purge from the Fastly UI. Therefore in the next code block
34 | # we check for presence of X-Purge-Token. If it's not present we force the Fastly-Purge-Requires-Auth
35 | if (req.request == "FASTLYPURGE") {
36 | # extract token signature and expiration
37 | if (req.http.X-Purge-Token && req.http.X-Purge-Token ~ "^([^_]+)_(.*)" ) {
38 |
39 | declare local var.X-Exp STRING;
40 | declare local var.X-Sig STRING;
41 | /* extract token expiration and signature */
42 | set var.X-Exp = re.group.1;
43 | set var.X-Sig = re.group.2;
44 |
45 | /* validate signature */
46 | if (var.X-Sig == regsub(digest.hmac_sha1(req.service_id, req.url.path var.X-Exp), "^0x", "")) {
47 | /* check that expiration time has not elapsed */
48 | if (time.is_after(now, std.integer2time(std.atoi(var.X-Exp)))) {
49 | error 410;
50 | }
51 | } else {
52 | error 403;
53 | }
54 | } else {
55 | set req.http.Fastly-Purge-Requires-Auth = "1";
56 | }
57 | }
58 |
59 | # disable ESI processing on Origin Shield
60 | if (req.http.Fastly-FF) {
61 | set req.esi = false;
62 | # Needed for proper handling of stale while revalidated when shielding is involved
63 | set req.max_stale_while_revalidate = 0s;
64 | } else {
65 | set esi.allow_inside_cdata = true;
66 | }
67 |
68 | # static files are always cacheable. remove SSL flag and cookie
69 | if (req.url.path ~ "^/(media|js|skin)/.*\.(png|jpg|jpeg|gif|css|js|swf|ico|webp|svg)$") {
70 | unset req.http.Https;
71 | unset req.http.Cookie;
72 | }
73 |
74 | # formkey lookup
75 | if (req.url.path ~ "/fastlycdn/getformkey/") {
76 | # check if we have a formkey cookie and that it's validly formed
77 | if (req.http.Cookie:FASTLY_CDN_FORMKEY &&
78 | std.strlen(req.http.Cookie:FASTLY_CDN_FORMKEY) < 40 && req.http.Cookie:FASTLY_CDN_FORMKEY ~ "^[a-zA-Z0-9-_]*$" ) {
79 | set req.http.Formkey = req.http.Cookie:FASTLY_CDN_FORMKEY;
80 | } else {
81 | # create formkey
82 | set req.http.seed = req.http.Cookie client.ip remote.port client.geo.longitude client.geo.latitude client.geo.postal_code;
83 | set req.http.Formkey = regsub(digest.hash_md5(req.http.seed), "^0x", "");
84 | }
85 | error 760 req.http.Formkey;
86 | }
87 |
88 | # client.geo lookup
89 | if (req.url.path ~ "fastlycdn/esi/getcountry/") {
90 | # check if GeoIP has been already processed by client
91 | if (req.http.Cookie:FASTLY_CDN_GEOIP_PROCESSED) {
92 | error 200 "";
93 | } else {
94 | # modify req.url and restart request processing
95 | error 750 client.geo.country_code;
96 | }
97 | }
98 |
99 | # client.geo get country code
100 | if (req.url.path ~ "fastlycdn/esi/getcountrycode/") {
101 | # create and set req.http.X-Country-Code
102 | error 755 client.geo.country_code;
103 | }
104 |
105 | # check for ESI calls
106 | if (req.url.qs ~ "esi_data=") {
107 | # check for valid cookie data
108 | declare local var.esi_data_field STRING;
109 | declare local var.cookie_data STRING;
110 | # Based on esi_data value requested we will need to search for cookie FASTLY_CDN- e.g. FASTLY_CDN-customer_quote
111 | set var.esi_data_field = "FASTLY_CDN-" subfield(req.url.qs, "esi_data", "&");
112 | # We can't use variables in either subfield or regex so we need to use this workaround
113 | # to extract value of cookie that we compiled in esi_data_field
114 | set var.cookie_data = std.strstr(req.http.Cookie,var.esi_data_field);
115 | set var.cookie_data = regsub(var.cookie_data,"^[^=]*=([^;]*).*","\1");
116 | # If found a value we replace the query string with the contents of that cookie
117 | if ( var.cookie_data != "" ) {
118 | set req.url = querystring.set(req.url, "esi_data", var.cookie_data);
119 | }
120 | }
121 |
122 | # Per suggestions in https://github.com/sdinteractive/SomethingDigital_PageCacheParams
123 | # we'll strip out query parameters used in Google AdWords, Mailchimp tracking
124 | set req.http.Magento-Original-URL = req.url;
125 | set req.url = querystring.regfilter(req.url, "^(####QUERY_PARAMETERS####)");
126 | # Sort the query arguments to increase cache hit ratio with query arguments that
127 | # may be out of order however only on URLs that are not being passed.
128 | if ( !req.http.x-pass ) {
129 | set req.url = boltsort.sort(req.url);
130 | }
131 |
--------------------------------------------------------------------------------