{"id":8590,"date":"2017-11-20T04:00:50","date_gmt":"2017-11-20T08:00:50","guid":{"rendered":"https:\/\/blog.litespeedtech.com\/?p=8590"},"modified":"2017-11-20T04:00:50","modified_gmt":"2017-11-20T08:00:50","slug":"magento-monday-litemage-cdns-and-tokens","status":"publish","type":"post","link":"https:\/\/lswp.store\/index.php\/2017\/11\/20\/magento-monday-litemage-cdns-and-tokens\/","title":{"rendered":"Magento Monday: LiteMage, CDNs, and Tokens"},"content":{"rendered":"<p><img fetchpriority=\"high\" decoding=\"async\" title=\"\" src=\"https:\/\/lswp.store\/wp-content\/uploads\/2017\/11\/null-11.png\" alt=\"\" width=\"640\" height=\"320\" \/><\/p>\n<p>Welcome to the first installment of <a href=\"http:\/\/blog.litespeedtech.com\/tag\/magento-monday\">Magento Monday<\/a>! We\u2019ve enjoyed bringing you <a href=\"http:\/\/blog.litespeedtech.com\/tag\/wordpress-wednesday\">WordPress Wednesday<\/a> every week, and so we thought it would be fun to also share some helpful Magento and <a href=\"https:\/\/www.litespeedtech.com\/products\/cache-plugins\/magento-acceleration\">LiteMage<\/a> tips here sometimes.<\/p>\n<p>Let\u2019s kick off this series by talking about Content Delivery Networks, how the custom CDN cache rules you have defined may be breaking your Magento 1.x store, and what you can do to fix the problem.<\/p>\n<p><em>Note: This particular issue is only a Magento 1 issue. It does not apply to Magento 2. <\/em><\/p>\n<h2>It\u2019s all about the Tokens<\/h2>\n<p>Magento 1.x uses a session variable called <code>form_key<\/code> as <a href=\"https:\/\/www.owasp.org\/index.php\/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet\">a CSRF token to prevent CSRF injection<\/a>. The <code>form_key<\/code> value is stored in the user session and is unique for every user. When a shopper adds a new product to the cart, or a new item to compare, Magento looks for the <code>form_key<\/code> token in the dynamically-generated HTML, and uses it in the validation process.<\/p>\n<p><strong>If there is no caching solution enabled at all, then this process works.<\/strong> It\u2019s slow and painful, but it works.<\/p>\n<p><strong>If LiteMage is caching the dynamic pages, then this process also works.<\/strong> LiteMage is smart enough to know that it must use ESI to \u201chole-punch\u201d the correct unique <code>form_key<\/code> token value for each user into the generated HTML, so that it may be used for validation.<\/p>\n<p><strong>If a CDN is caching the dynamic pages, then this process falls apart.<\/strong> Content Delivery Networks are not smart enough for hole-punching. They cache only one version of the page, which means they save only one <code>form_key<\/code> token for every shopper to share. This can\u2019t possibly work, and validation is broken.<\/p>\n<p>We recommend that you turn off all caching of dynamic pages in your CDN. CDNs are great for static content, like CSS, JavaScript, and image files, so by all means, leave that type of caching enabled, but <em>let LiteMage handle the dynamic page-caching duties<\/em>.<\/p>\n<h2>Diagnosing and Fixing the Problem<\/h2>\n<p>How can you tell whether your page is being served from CDN cache or LiteMage Cache? Take a look at the Response Headers.<\/p>\n<p>What you want to see is something like this:<\/p>\n<pre>\n\nX-LiteSpeed-Cache: hit,litemage\n\n<\/pre>\n<p>This shows that LiteMage is in control of caching the page.<\/p>\n<p>If you see headers like the following:<\/p>\n<pre>\n\ncache-control:public, max-ago=14400\ncf-cache-status: HIT\n\n<\/pre>\n<p>then the CDN (in this case Cloudflare) is doing the caching.<\/p>\n<p>Here\u2019s how to stop that from happening:<\/p>\n<p>From the Magento admin area, navigate to <strong>System &gt; Configuration &gt; General &gt; Web<\/strong> and open the <strong>Unsecure<\/strong> and <strong>Secure<\/strong> sections.<\/p>\n<p><img decoding=\"async\" title=\"\" src=\"https:\/\/lswp.store\/wp-content\/uploads\/2017\/11\/null-12.png\" alt=\"\" width=\"672\" height=\"593\" \/><\/p>\n<p>While it may be easier to just set Base URL to the CDN\u2019s address, and let the CDN sort out what content should be served from where, doing so is highly inefficient and will slow down your site. Why send a request to the CDN only to have it bounced back to your own site for fulfillment?<\/p>\n<p>Setting it up properly in this section ensures that requests are routed to the proper locations right from the start, with no time wasted with unnecessary travel back-and-forth.<\/p>\n<p>Set the <strong>Base URL<\/strong> to your site\u2019s address, <em>not<\/em> the CDN\u2019s.<\/p>\n<p>The <strong>Skin<\/strong>, <strong>Media<\/strong>, and <strong>JavaScript URL<\/strong>s refer to static content, and those may point to your CDN.<\/p>\n<p>A note about the <strong>Unsecure<\/strong> section: Technically, you can use <code>http:\/\/<\/code> in these fields, but with LiteSpeed\u2019s emphasis on HTTP\/2 and QUIC, you have the ability to use <code>https:\/\/<\/code> everywhere. These days security is a big deal, so why wouldn\u2019t you use it?<\/p>\n<h2>So, Why Don\u2019t CDN Cache Rules Work?<\/h2>\n<p>If you know about Magento 1.x\u2019s session cookies (<code>frontend<\/code> for HTTP and <code>frontend_cid<\/code> for HTTPS), you may have tried to use them to configure the CDN\u2019s cache rules as follows: if there is no session cookie, it means the user hasn\u2019t started shopping yet, and the page can be cached by the CDN. If there is a session cookie, then the request must be sent to the Magento backend.<\/p>\n<p>It\u2019s a clever idea, but unfortunately it doesn\u2019t work, and this is why:<\/p>\n<p>The form key is irrelevant while the user is simply browsing, and so it seems fine to serve the page from CDN cache. However, as soon as they try to act (add an item to the cart, or to compare), the form key becomes important. And because of the fact that they are performing that first action from the cached page, <em>they will be looking at the cached <code>form_key<\/code> value instead of a form key that&#8217;s been generated specifically for them<\/em>. As a result, the action will fail.<\/p>\n<p>If the user reloads the page, the CDN recognizes that they now have a session key, and so their request hits the backend, the correct form key is generated, and they are able to shop normally.<\/p>\n<p><strong>The problem works itself out on the second attempt, but the damage to user experience has already been done.<\/strong> Some shoppers will reload and keep going, but others will leave after the first error. Can you afford to lose those customers?<\/p>\n<p><img decoding=\"async\" title=\"\" src=\"https:\/\/lswp.store\/wp-content\/uploads\/2017\/11\/null-2.jpeg\" alt=\"\" width=\"672\" height=\"448\" \/><\/p>\n<p>Even if the session cookie idea <em>had<\/em> worked, it\u2019s hard to see what would be gained from having the CDN handle the caching of that page. LiteMage, which was built specifically for Magento, can manage your shop\u2019s cache in a much more efficient way than a Content Delivery Network can. As we\u2019ve already seen, LiteMage can punch holes for private content, making it possible to store a single copy of the page in public cache, and then serve it with the personalized information in the punched holes.<\/p>\n<p><strong>With the CDN in charge, users who are actively shopping cannot benefit from caching, but with LiteMage, they can.<\/strong><\/p>\n<p>Additionally, LiteMage can take advantage of tag-based purging, making sure that all of the necessary pages (and <em>only<\/em> the necessary pages) are purged when a product is updated.<\/p>\n<p>If you are running LiteMage, it\u2019s best to let LiteMage handle all of the page-caching that it was built to handle. Your Content Delivery Network can easily deal with the rest.<\/p>\n<p>&#8212;<\/p>\n<p>Have some of your own ideas for future <a href=\"http:\/\/blog.litespeedtech.com\/tag\/magento-monday\">Magento Monday<\/a> topics? Leave us a comment!<\/p>\n<p>If you enjoyed this, here are a few other things you can do:<\/p>\n<ul>\n<li>Subscribe to the <a href=\"http:\/\/blog.litespeedtech.com\/tag\/magento-monday\/feed\">Magento Monday RSS feed<\/a><\/li>\n<li>Download <a href=\"https:\/\/www.litespeedtech.com\/support\/wiki\/doku.php\/litespeed_wiki:cache:litemage:installation\">LiteMage Cache for Magento 1<\/a><\/li>\n<li>Download <a href=\"https:\/\/github.com\/litespeedtech\/magento2-LiteSpeed_LiteMage\">LiteMage Cache for Magento 2<\/a> from the GitHub Repository<\/li>\n<li>Learn more about the plugin <a href=\"https:\/\/www.litespeedtech.com\/products\/cache-plugins\/magento-acceleration\">on our website<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>In the inaugural issue of Magento Monday, we talk about the Magento 1.x form_key, how CDNs get it wrong, and how LiteMage gets it right.<\/p>\n","protected":false},"author":1,"featured_media":8592,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[25,28],"tags":[175,178],"class_list":["post-8590","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-litemage","category-cache","tag-magento","tag-magento-monday"],"jetpack_featured_media_url":"https:\/\/lswp.store\/wp-content\/uploads\/2017\/11\/null-11.png","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/lswp.store\/index.php\/wp-json\/wp\/v2\/posts\/8590","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lswp.store\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lswp.store\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lswp.store\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lswp.store\/index.php\/wp-json\/wp\/v2\/comments?post=8590"}],"version-history":[{"count":0,"href":"https:\/\/lswp.store\/index.php\/wp-json\/wp\/v2\/posts\/8590\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/lswp.store\/index.php\/wp-json\/wp\/v2\/media\/8592"}],"wp:attachment":[{"href":"https:\/\/lswp.store\/index.php\/wp-json\/wp\/v2\/media?parent=8590"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lswp.store\/index.php\/wp-json\/wp\/v2\/categories?post=8590"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lswp.store\/index.php\/wp-json\/wp\/v2\/tags?post=8590"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}