How to create a 301 redirect using Fastly in Magento

How to create a 301 redirect using Fastly in Magento

1st May 2018 Gregor Pollak

Recently, we've built a Magento 2 store on Magento Cloud without the usage of migration tools to migrate the data from Magento 1. One of the things that has changed, was a category name that was used as a top-level category. In Magento 1 the URL was /elements/subcategory.html and in Magento 2 the client requested a change to /parts/subcategory.html. So we had to change only the top-level category url part, the subcategory url part staied the same. There are few ways of doing that.

1. Magento URL rewrites

Magento has a core functionality which allows you to add URL rewrites.

Magento URL rewrites

This is useful when we have only few rewrites to enter. In our case, there was a long list of subcategories, so manual entries were not an option.

2. Inserting URL rewrites directly into DB

Next option builds on first solution by still using Magento core functionality of URL rewrites. The only change is the input method. We insert the rewrites directly into a database. This solution is for developers who are familiar with Magento DB structure and relations between the tables. The easiest way is to create a CSV file with old & new values:

Database row

Once the file is ready, we use a DB tool (for example Sequel Pro on Mac) which already has a useful tool for importing CSV data:

CSV snippet

We align the fields and set default values for our import and run the import.

Align the fields

3. Usage of .htaccess rewrite rules

Developers who are familiar with apache usage of .htaccess files would use Rewrite engine:

   RewriteEngine On
   RewriteRule ^elements/(.*) /parts/$1 [R=301,NC,L]

All those methods work fine and execute the 301 direct as we want it. But with high-load sites, each request to the server counts. Our clients using Magento Commerce on Magento Cloud have the benefit of the Fastly CDN.

Fastly CDN approach

Fastly is a CDN based on Varnish caching, basically a cloud varnish service. When working with Fastly, you are also working directly with a heavily customized version of Varnish (2.1). Fastly with Varnish caches your site pages, assets, CSS, and more in backend datacenters you set up. As customers access your site and stores, the requests hit Fastly to load cached pages faster.

For Magento Commerce (Cloud), you receive Fastly CDN and DDoS services. When you update products, catalogs, content, and more, Fastly purges that specific cached content to refresh and provide the latest changes.

Fastly CDN is also available for Magento Open Source edition. Installation & setup is explained in Fastly extension page on GitHub so we won't go into details here. Once you have Fastly serving you content, we can create a 301 redirect in Fastly. Information on how to update Fastly VCL thru CLI is listed on Magento DevDocs. The important part is the JSON snippets we create to get the 301 working. To understand how things run in Fastly, we take a quick peek at how Fastly processes a request:

Fastly processes a request

Each request first goes thru VCL_RECV snippets. In our case, the JSON snippet would look like this:

   {
     "name": "Redirect _elements_ to _parts_ to correct path RECV",
     "dynamic": "0",
     "type": "recv",
     "priority": "10",
     "content": "if (req.url ~ \"/elements/\") { error 975; }"
   }

The trick here is the "error 975". We are telling Fastly, that if request URL contains "/elements/" we throw an error 975 – the error number must be high enough that is not valid. This way we make sure that no other VCL parts will intercept. Next JSON snippet is the error snippet which takes care of the redirect:

   {
     "name": "Redirect _elements_ to _parts_ to correct path ERROR",
     "dynamic": "0",
     "type": "error",
     "priority": "10",
     "content": "if (obj.status == 975) { set obj.http.Location = \"https://\" + req.http.host + regsub(req.url, \"/elements/\", \"/parts/\"); set obj.status = 301; set obj.response = \"Moved Permanently\"; synthetic {\"\"}; return (deliver); }"
   }

In here, we check the error code. If its 975, that means it came from RECV snippet we are using. This snippet replaces "/elements/" with "/parts/" in the URL and sends 301 header back to the browser which then redirects to the correct URL. The "return(deliver)" is the command which tells the Fastly to stop processing the request and deliver the request back. We save both JSON files and repeat Add Snippet twice (for each of the JSON files) and continue following Magento DevDocs. Once we have our new version of VCL active, we can test the new 301.

Conclusion

The beauty of this approach is that we handle the redirect on Fastly so we benefit twice:

1. The 301 request never reaches our server so we lower the server load
2. The 301 request is faster as it doesn't need to pass through Fastly before hitting the server