Too Many Redirects Error Topic points to hit on: What does the error of “too many redirects” mean? Explain the process of what happens with too many redirects. (pic of redirect error) Write on some common reasons why a redirect loop can occur. (SSL, Wordpress URL, .htaccess file, wp-config,  Wordpress plugins) What are some ways the users can troubleshoot? (provide as much detail as possible with this section) Keywords & Phrases: how do you fix, Wordpress, how to, redirects, SSL, URL, Wordpress, hosting.htaccess, wp-config, plugins Audience:Intermediate Tone of Voice: Instructional & Helpful Length: 1,000 words, ideally 1,500-2,000 words ----- Redirect checker #!/bin/bash echo for domain in $@; do echo -------------------- echo $domain echo -------------------- curl -sILk $domain | egrep 'HTTP|Loc' | sed 's/Loc/ -> Loc/g' echo done # redirects.sh liquidweb.com -------------------- liquidweb.com -------------------- HTTP/1.1 301 Moved Permanently -> Location: https://liquidweb.com/ HTTP/1.1 301 Moved Permanently -> Location: https://www.liquidweb.com/ HTTP/1.1 200 OK #Example of infinite redirect redirects.sh http://www.example.com -------------------- http://www.example.com -------------------- HTTP/1.1 301 Moved Permanently -> Location: https://www.example.com/ HTTP/1.1 301 Moved Permanently -> Location: http://www.example.com/ HTTP/1.1 301 Moved Permanently -> Location: https://www.example.com/ HTTP/1.1 301 Moved Permanently -> Location: http://www.example.com/ HTTP/1.1 301 Moved Permanently .... -> Location: https://www.example.com/ HTTP/1.1 301 Moved Permanently -> Location: http://www.example.com/ HTTP/1.1 301 Moved Permanently -> Location: https://www.example.com/ HTTP/1.1 301 Moved Permanently -> Location: http://www.example.com/ HTTP/1.1 301 Moved Permanently -> Location: https://www.example.com/ #Curl Error curl -svILk https://www.example.com .... * Maximum (50) redirects followed ----- Too many redirects means that the website keeps being redirected back and forth between different addresses in a way that will never complete. Often this is the result of competing redirects trying to force https (ssl) and another redirecting back to http (non-ssl). If you are using a CMS like Wordpres, Magento, etc that utilizes a base_url or url type configuration within the site, you can end up with the configuration in the code or database conflicting with a redirect in a .htaccess file, and these will flip flop and never complete. Your browser protects you from this by only allowing a number of redirects back and forth before it gives up and give the error message "Too many redirects" This shows up differently between Chrome (img), Firefox (img), and other browsers. Even the test utility curl gives up after 50 redirects. ----- .htaccess .htaccess is a configuration file used to modify Apache server behavior per directory on a website/server. This is a user level configuration file. You can have multiple .htaccess files that cascade over a series of directories. If you have an .htaccess in a parent directory, and another in a sub-directory they will both affect the sub-directory, so it is important to remember where you have .htaccess files in order to prevent conflicts between multiple of these configuration files. Below are a series of redirect examples. These are not the only ways to do these kinds of redirects, but these should show you what the most common redirects look like, so you can recognize them if they are in an .htaccess file you are working with. This first redirect checks if the request came into the server using http or https, if the request did not use https, then the configuration will tell the browser to redirect over to the https version of the same website and url that was requested before not using https. #Force HTTPS RewriteEngine On RewriteCond %{HTTPS} off RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] Sometimes you may be using a proxy like a Load Balancer, or a web firewall like CloudFlare, Incapsula, or Sucuri. These can be configured to use SSL on the front end, but not use SSL on the back end. To allow this to work correctly, you need to check not just for https in the request, but also if the proxy passed original https request to the server using just http. This following rule checks if the request was forwarded from https, and if so does not try to redirect an additional time.d #Force HTTPS when behind a load balancer or proxy (CloudFlare/Incapsula/Sucuri/etc.) RewriteEngine On RewriteCond %{HTTPS} off RewriteCond %{HTTP:X-Forwarded-Proto} =http RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] This redirect only checks if the website name was requested with www at the start of the domain name. If the WWW is included it rewrites the request and tells the browser to redirect over to the non-WWW version of the domain name. #Force non-www RewriteEngine On RewriteCond %{HTTP_HOST} ^www\. [NC] RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] This last redirect checks if the website name was not requested with www at the start of the domain name. If the WWW is not included, it rewrites the request and tells the browser to redirect over to the WWW version of the domain. #Force www RewriteEngine On RewriteCond %{HTTP_HOST} !^www\. [NC] RewriteRule (.*) http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L] ----- Wordpress The Wordpress CMS uses a .htaccess files and also defines the url of the website as a value in the database. If you do not already know the name of the database that is being used on the site, you can look it up in the main configuration for Wordpress. You can just open the file in a text editor and look for these values, but from an ssh connection you can also just use the program grep. grep DB wp-config.php define('DB_NAME', 'wordpress_database'); define('DB_USER', 'wordpress_username'); define('DB_PASSWORD', 'Password'); define('DB_HOST', 'localhost'); define('DB_CHARSET', 'utf8'); define('DB_COLLATE', ''); Once you know the name of the database, you can then look at the options table of the Wordpress database to see what the url is set to in the database. The options table can have any prefix at the beginning of the table name, but it is often "wp_" by default, so the full name of the options table is usually wp_options. The two lines that are important are the home and siteurl lines in the options table. You can find these using phpMyAdmin, or another database management utility, but from the command line you can also just run the following mysql command. wp_options table mysql -e 'show tables' wordpress_database | grep options #Checking the configured URL mysql -e 'select * from wp_options where option_name rlike "home|siteurl"' wordpress_database +-----------+-------------+----------------------------------+----------+ | option_id | option_name | option_value | autoload | +-----------+-------------+----------------------------------+----------+ | 36 | home | http://www.example.com | yes | | 1 | siteurl | http://www.example.com | yes | +-----------+-------------+----------------------------------+----------+ #Updating the configured URL mysql -e 'update wp_options set option_value="https://www.example.com" where option_name rlike "home|siteurl"' wordpress_database ----- Magento The database name is configured in one of these files. You can also configure a prefix for the table names of the Magento database, but it is usually not set, so the expected name for the main configuration table of the datbase is core_config_data. # Version 1.x app/etc/local.xml # Version 2.x app/etc/env.php # Base_urls are configured within the core_config_data table There are many potential urls that can be configured but they all have "base_url" as part of the line in the datbase. You can again find these using a databse managment utility, but from the command line you can run something like the following. The primary urls configured with be the secure and unsecure urls, but you can also setup urls for images, theme files, or even setup a separate url for the administration area of the site. mysql -e 'select * from core_config_data where path rlike "base_url"' robotzom_mage19 +-----------+---------+----------+-----------------------+----------------------------+ | config_id | scope | scope_id | path | value | +-----------+---------+----------+-----------------------+----------------------------+ | 3 | default | 0 | web/unsecure/base_url | http://www.example.com | | 4 | default | 0 | web/secure/base_url | http://www.example.com | +-----------+---------+----------+-----------------------+----------------------------+ So as part of these urls being configured in the database as exemplified by Wordpress and Magento, these CMS's also provide their own redirect methods within the CMS themselves. If for example you have a .htaccess redirect that is redirecting to something that does not align with what's in the database, you can end up with the infinite redirect loop as described earlier. Now that you know what some common .htaccess redirects look like, and where to find the configured urls in the database of some CMS software, you can confirm if these things are working in concert or if they may be working at cross purposes.