Configure Redirects

Review considerations and recommendations on how to handle redirect logic via Primary Domains or PHP.

Tweet

This page describes how to configure domain redirects with the Primary Domain setting, and page-level redirects within settings.php (Drupal) or wp-config.php (WordPress), adjusting placeholder values within snippets as needed (e.g., example.com).

Considerations

htaccess

Pantheon does not support managing redirects in .htaccess files, since they are ignored by NGINX for reduced resource consumption and increased efficiency. This configuration is standard across all Pantheon sites, and modifications to the nginx.conf file are not supported.

Using .htaccess is generally not recommended - even for sites running Apache. Instead, we suggest handling domain-level redirects by setting a primary domain, and handling page-level redirects in PHP within your site's configuration file.

Advantages of redirecting via Primary Domain + PHP instead of .htaccess include:

  • Logic and decisions can be made that a web server would have no context for, as it's executable code with application state awareness. Conditional logic, regular expressions, and much more are possible.
  • Configuration tends to be more maintainable as Drupal and WordPress developers are typically more familiar with PHP than Apache rewrite rules.
  • Since settings.php and wp-config.php are parsed very early in the bootstrap process, redirects like this are "cheap" with low overhead. If you use a 301 redirect, the Pantheon Global CDN will cache it as well.

Avoid Excessive Redirects

When using multiple snippets, be sure to step through the logic. This is particularly important when redirecting to a common domain while also incorporating redirects for specific pages. All if conditional statements need to be in the correct order. For example, a wholesale redirect executed prior to redirects for specific pages would likely prevent the second statement from being evaluated.

Redirect to HTTPS

The standard best practice when using HTTPS is to set an HSTS header to force connections over HTTPS only.

These redirect configuration are considered best practice and recommended as part of the going live procedure. Configure these settings after connecting a custom domain in the Site Dashboard when you're ready to launch the site.

Set HSTS with Pantheon.yml

This is the preferred method of setting HTTPS & HSTS for your site. Find the enforce_https setting in your site's pantheon.yml file.

 Note

Before adjusting enforce_https, review and understand the configuration options and all considerations to avoid unintended consequences.

If you use a plugin or module to set your HSTS header, it will create a duplicate header. Disable enforce_https in pantheon.yml to avoid an invalid policy.

Use of the HSTS header is defined by the enforce_https directive, and takes five possible values which are handled by Pantheon as shown below:

enforce_https:RedirectHSTSStrict-Transport-SecurityincludeSubdomainspreload
offDisabledNot set by Pantheon
transitional (default)Enforcedmax-age=300
transitional+subdomainsEnforcedmax-age=300
full Enforcedmax-age=31622400
full+subdomains Enforcedmax-age=31622400

For example, to set enforce_https as off:

enforce_https: off

Considerations

  • Use of full or full+subdomains should be treated as a commitment. HSTS headers are cached by browsers for the duration of the max-age period. If your site is unable to serve HTTPS (e.g. by moving to a host that doesn't support HTTPS), visitors will be unable to access your site.
  • Any option with +subdomains should only be used if you want to enforce HTTPS for all subdomains, even those not connected to Pantheon.
  • To prepare your site to serve all content via HTTPS, follow the Switching Sites from HTTP to HTTPS doc.

Set the Primary Domain

Set a Primary Domain via the Dashboard

 Warning

With a Primary Domain set at the platform level, all other domains (except the platform domain) will be pointed to your Primary domain at the root level. If you want to redirect secondary domains to specific pages on your site (for example, olddomain.com to newdomain.com/old-landing-page), do not set a Primary Domain. Instead use PHP redirects.

  1. From the environment you want to set a primary domain for (typically Test or Live), navigate to Domains / HTTPS.

  2. Ensure that all domains have been added and are listed.

  3. In the Choose Primary Domain section, select the domain to which traffic should be redirected, and click Save Configuration.

Set a Primary Domain with Terminus

  1. Install or upgrade to the latest version of Terminus.

  2. Use Terminus to add the primary domain. In this example, replace:

    • my-site with your site name,
    • live if you'd like to set it for a different environment
    • www.example.com with your primary domain:
    terminus domain:primary:add my-site.live www.example.com

Update or Remove Primary Domain

Update the Primary Domain using either method provided in the previous section.

Remove an existing selection for the Primary Domain on any environment using Terminus:

terminus domain:primary:remove my-site.live

Replace my-site with your site name, and live with the environment you're removing a primary domain from.

Verify

You can confirm that the Primary Domain has been removed with cURL pointed at one of your other custom domains, which would previously have been redirected:

curl -I https://example.com
HTTP/2 301
retry-after: 0
server: Pantheon
location: https://www.example.com/
x-pantheon-redirect: primary-domain-policy-docdate: Wed, 05 Feb 2020 16:43:21 GMT
x-served-by: cache-mdw17355-MDW
x-cache: HIT
x-cache-hits: 0
x-timer: S1580921002.586800,VS0,VE1
age: 0
accept-ranges: bytes
via: 1.1 varnish
content-length: 0

The presence of x-pantheon-redirect: primary-domain-policy-doc indicates that the domain is still being pointed at the former Primary Domain. Contact support if this value persists.

Redirect with PHP

If your site configuration prevents you from setting the primary domain from the platform level, you can use PHP redirects:

Add the following to wp-config.php, usually placed above /* That's all, stop editing! Happy Pressing. */. Don't forget to replace www.example.com:

wp-config.php
if (isset($_ENV['PANTHEON_ENVIRONMENT']) && php_sapi_name() != 'cli') {
  // Redirect to https://$primary_domain in the Live environment
  if ($_ENV['PANTHEON_ENVIRONMENT'] === 'live') {
    // Replace www.example.com with your registered domain name.
    $primary_domain = 'www.example.com';
  }
  else {
    // Redirect to HTTPS on every Pantheon environment.
    $primary_domain = $_SERVER['HTTP_HOST'];
  }

  $requires_redirect = false;
  
  // Ensure the site is being served from the primary domain.
  if ($_SERVER['HTTP_HOST'] != $primary_domain) {
    $requires_redirect = true;
  }

  // If you're not using HSTS in the pantheon.yml file, uncomment this next block.
  // if (!isset($_SERVER['HTTP_USER_AGENT_HTTPS'])
  //     || $_SERVER['HTTP_USER_AGENT_HTTPS'] != 'ON') {
  //   $requires_redirect = true;
  // }

  if ($requires_redirect === true) {

    // Name transaction "redirect" in New Relic for improved reporting (optional).
    if (extension_loaded('newrelic')) {
      newrelic_name_transaction("redirect");
    }

    header('HTTP/1.0 301 Moved Permanently');
    header('Location: https://'. $primary_domain . $_SERVER['REQUEST_URI']);
    exit();
  }
}

WordPress users should also run a search and replace to update any references to the platform domain.

Add the following to the end of your settings.php file (replace www.example.com):

settings.php
if (isset($_ENV['PANTHEON_ENVIRONMENT']) && php_sapi_name() != 'cli') {
  // Redirect to https://$primary_domain in the Live environment
  if ($_ENV['PANTHEON_ENVIRONMENT'] === 'live') {
    // Replace www.example.com with your registered domain name.
    $primary_domain = 'www.example.com';
  }
  else {
    // Redirect to HTTPS on every Pantheon environment.
    $primary_domain = $_SERVER['HTTP_HOST'];
  }

  $requires_redirect = FALSE;

  // Ensure the site is being served from the primary domain.
  if ($_SERVER['HTTP_HOST'] != $primary_domain) {
    $requires_redirect = TRUE;
  }

  // If you're not using HSTS in the pantheon.yml file, uncomment this next block.
  // if (!isset($_SERVER['HTTP_USER_AGENT_HTTPS'])
  //     || $_SERVER['HTTP_USER_AGENT_HTTPS'] != 'ON') {
  //   $requires_redirect = TRUE;
  // }

  if ($requires_redirect === TRUE) {

    // Name transaction "redirect" in New Relic for improved reporting (optional).
    if (extension_loaded('newrelic')) {
      newrelic_name_transaction("redirect");
    }

    header('HTTP/1.0 301 Moved Permanently');
    header('Location: https://'. $primary_domain . $_SERVER['REQUEST_URI']);
    exit();
  }
  // Drupal 8 Trusted Host Settings
  if (is_array($settings)) {
    $settings['trusted_host_patterns'] = array('^'. preg_quote($primary_domain) .'$');
  }
}

Add the following to the end of your settings.php file (replace www.example.com):

settings.php
if (isset($_ENV['PANTHEON_ENVIRONMENT']) && php_sapi_name() != 'cli') {
  // Redirect to https://$primary_domain in the Live environment
  if ($_ENV['PANTHEON_ENVIRONMENT'] === 'live') {
    // Replace www.example.com with your registered domain name.
    $primary_domain = 'www.example.com';
  }
  else {
    // Redirect to HTTPS on every Pantheon environment.
    $primary_domain = $_SERVER['HTTP_HOST'];
  }

  $requires_redirect = false;
  
  // Ensure the site is being served from the primary domain.
  if ($_SERVER['HTTP_HOST'] != $primary_domain) {
    $requires_redirect = true;
  }

  // If you're not using HSTS in the pantheon.yml file, uncomment this next block.
  // if (!isset($_SERVER['HTTP_USER_AGENT_HTTPS'])
  //     || $_SERVER['HTTP_USER_AGENT_HTTPS'] != 'ON') {
  //   $requires_redirect = true;
  // }

  if ($requires_redirect === true) {

    // Name transaction "redirect" in New Relic for improved reporting (optional).
    if (extension_loaded('newrelic')) {
      newrelic_name_transaction("redirect");
    }

    header('HTTP/1.0 301 Moved Permanently');
    header('Location: https://'. $primary_domain . $_SERVER['REQUEST_URI']);
    exit();
  }
}

Additional Redirects

For additional redirect examples to fit the custom requirements of your site, see Advanced Redirects.

See Also