Skip to main content
Last Reviewed: August 01, 2022

Advanced Redirects and Restrictions

Configure custom redirect logic for specific scenarios.


Basic domain and HTTPS redirection can be handled by the Primary Domain feature. PHP redirects can be used if these configurations are not an option, or when you need specific redirect logic. Depending on the needs of the site, you may need none, only one, or several of the following configurations.

Redirect logic should be added to wp-config.php for WordPress sites, and settings.php for Drupal sites.

Warning:
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 (or if set, remove the Primary Domain).

Redirect to HTTPS

The following configuration will redirect HTTP requests to HTTPS, such as http://env-site-name.pantheonsite.io to https://env-site-name.pantheonsite.io or http://example.com to https://example.com.

If you're setting HSTS in pantheon.yml, you don't need additional PHP redirection, simply run the following code:

wp-config.php or settings.php
// Require HTTPS across all Pantheon environments
// Check if Drupal or WordPress is running via command line
if (isset($_SERVER['PANTHEON_ENVIRONMENT']) && ($_SERVER['HTTPS'] === 'OFF') && (php_sapi_name() != "cli")) {
  if (!isset($_SERVER['HTTP_USER_AGENT_HTTPS']) || (isset($_SERVER['HTTP_USER_AGENT_HTTPS']) && $_SERVER['HTTP_USER_AGENT_HTTPS'] != 'ON')) {

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

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

    exit();
  }
}

Redirect from Subdomain to Subdirectory Path

The following configuration will redirect requests for subdomain.example.com to https://example.com/subdirectory/.

  1. Remove the primary domain from the environment.

  2. Run the following code:

wp-config.php or settings.php
// Redirect subdomain to a specific path.
// Check if Drupal or WordPress is running via command line
if (isset($_ENV['PANTHEON_ENVIRONMENT']) && ($_SERVER['HTTP_HOST'] == 'subdomain.example.com') && (php_sapi_name() != "cli")) {
  $newurl = 'https://www.example.com/subdirectory'. $_SERVER['REQUEST_URI'];
  header('HTTP/1.0 301 Moved Permanently');
  header("Location: $newurl");

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

  exit();
}

Redirect One Path to Another

The following configuration will redirect requests for example.com/old to https://example.com/new:

wp-config.php or settings.php
// 301 Redirect from /old to /new
// Check if Drupal or WordPress is running via command line
if (($_SERVER['REQUEST_URI'] == '/old') && (php_sapi_name() != "cli")) {
  header('HTTP/1.0 301 Moved Permanently');
  header('Location: https://'. $_SERVER['HTTP_HOST'] . '/new');

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

  exit();
}

Redirect Multiple Paths

The following configuration will redirect requests for example.com, example.com/old, example.com/another/path, and example.com/old-path to https://example.com/new-path-for-all:

wp-config.php or settings.php
$redirects = array(
  "/",
  "/old",
  "/another/path",
  "/old-path");

// 301 Redirect from multiple paths
// Check if Drupal or WordPress is running via command line
if ((in_array($_SERVER['REQUEST_URI'], $redirects)) && (php_sapi_name() != "cli")) {
  header('HTTP/1.0 301 Moved Permanently');
  header('Location: https://'. $_SERVER['HTTP_HOST'] . '/new-path-for-all');

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

  exit();
}

Redirect Multiple URLs

The following configuration will redirect requests for:

  • example.com/old-url1 to example.com/new-url1
  • example.com/old-url2 to example.com/new-url2
  • example.com/old-url3 to example.com/new-url3
wp-config.php or settings.php
// You can easily put a list of many 301 url redirects in this format
// Trailing slashes matters here so /old-url1 is different from /old-url1/
$redirect_targets = array(
  '/old-url1' => '/new-url1',
  '/old-url2' => '/new-url2',
  '/old-url3' => '/new-url3',
);

if ( (isset($redirect_targets[ $_SERVER['REQUEST_URI'] ] ) ) && (php_sapi_name() != "cli") ) {
  header('HTTP/1.0 301 Moved Permanently');
  header('Location: https://'. $_SERVER['HTTP_HOST'] . $redirect_targets[ $_SERVER['REQUEST_URI'] ]);

  if (extension_loaded('newrelic')) {
    newrelic_name_transaction("redirect");
  }
  exit();
}

Redirect Multiple Subdomains

Info:
Note

If you've configured your primary domain at the platform level and can add these subdomains to the same environment, redirection will happen automatically.

The following configuration will redirect requests for sub1.example.com, sub2.example.com, sub3.example.com, and sub4.example.com to https://new.example.com:

wp-config.php or settings.php
// Redirect multiple subdomains to a single domain.
// Check if Drupal or WordPress is running via command line
if (isset($_ENV['PANTHEON_ENVIRONMENT']) && ($_ENV['PANTHEON_ENVIRONMENT'] === 'live') && (php_sapi_name() != "cli")) {
  if (in_array($_SERVER['HTTP_HOST'], array(
    'sub1.example.com',
    'sub2.example.com',
    'sub3.example.com',
    'sub4.example.com'
  ))) {
    header('HTTP/1.0 301 Moved Permanently');
    header('Location: https://new.example.com'. $_SERVER['REQUEST_URI']);

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

    exit();
  }
}

Wildcard Redirect From One Subfolder to Another

The following configuration will redirect requests pointed to any page in example.com/old/ to the same page in example.com/new/. For example, example.com/old/contributors.html will redirect to example.com/new/contributors.html:

wp-config.php or settings.php
$uri = $_SERVER['REQUEST_URI'];
$url_to_match = '/old';
$subdirectory_toredirect = '/new';
if( strpos( $uri, $url_to_match ) === 0) {

  $redirect_uri = str_replace( $url_to_match , "", $uri );
  if ( ( php_sapi_name() != "cli" ) ) {
    header( 'HTTP/1.0 301 Moved Permanently');
    header( 'Location: https://' . $_SERVER[ 'HTTP_HOST' ] . $subdirectory_toredirect . $redirect_uri );

    if (extension_loaded('newrelic')) {
      newrelic_name_transaction("redirect");
    }

    exit();
  }

}

Redirect Legacy UNIX-Style User Home Folder Paths

When transitioning from a system that used a tilde to indicate a home directory, the syntax is slightly different. Run the following code to parse out the username and relative path that the request was made for:

wp-config.php or settings.php
$request_parts = explode('/', $_SERVER['REQUEST_URI']);
$legacy_username = $legacy_path = '';
if (isset($request_parts[1]) && strpos($request_parts[1], '~') === 0) {
  $legacy_username = substr($request_parts[1], 1);
  // If FALSE, then the request was just to the username.
  $legacy_path = substr($_SERVER['REQUEST_URI'], (strlen($request_parts[1]) + 1));
}
if ($legacy_username) {
  // Your custom logic.
}

Redirect to Force Lowercase Letters

WordPress automatically forces lowercase letters within URLs using the sanitize_title_with_dashes() function in core.

Redirect Files

Because Drupal and WordPress aren't bootstrapped when static assets (e.g, images, PDFs, HTML files) are served, the PHP redirects used above will not work when these files are requested directly. You can use CloudFlare or another stacked CDN to handle file redirects.

Alternatively, you can remove the file entirely from the old location. In this case, the request will run through Drupal or WordPress. You can let the CMS serve a 404, or you can utilize a redirect in wp-config.php or settings.php as shown in the examples above.

Redirects and Rewrites with PHP

Pantheon uses nginx for HTTP/HTTPS instead of Apache. You can recreate Apache mod_redirects and mod_rewrites on the Pantheon platform using the code in the Pantheon htacess Rewrites repository.

The file must be included at the very beginning of your Drupal settings.php or WordPress wp-config.php file. The code will perform rewrites and redirects prior to full WordPress or Drupal bootstrap.

Restrict Access to Paths Based on IP

If you want to restrict access to files based on the source IP address of the request, you can do so with PHP.

The following example restricts access to /wp-admin/ and /wp-login.php based on the IP addresses listed in the $trusted_ips array:

wp-config.php
function ip_in_list($ips) {
    foreach(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']) as $check_ip) {
        foreach($ips as $ip) {
          if(FALSE !== strpos($check_ip, $ip)) {
            return true;
          }
        }
    }

    return false;
}
  
function is_from_trusted_ip() {
    //Replace the IPs in this array with those you want to restrict access to
    $trusted_ips = array(
        '192.0.2.38',
        '198.51.100.12',
        '208.0.113.159',
        '98b9:1da9:71f7:0953:f012:8574:3d58:9ac9',
    );

    return ip_in_list($trusted_ips);
}

if (isset($_SERVER['PANTHEON_ENVIRONMENT']) && (php_sapi_name() !== 'cli') && !is_from_trusted_ip()) {
    // Check if the path should be locked down
    $to_lockdown = false;

    $disallow_uri = array(
        '/wp-login.php',
        '/wp-admin/',
    );

    $allow_uri = array(
        '/wp-admin/admin-ajax.php',
        '/wp-admin/admin-post.php',
    );

    foreach ($disallow_uri as $prefix) {
        if (stripos($_SERVER['REQUEST_URI'], $prefix) === 0) {
            $to_lockdown = true;

            break;
        }
    }

    foreach ($allow_uri as $prefix) {
        if (stripos($_SERVER['REQUEST_URI'], $prefix) === 0) {
           $to_lockdown = false;

           break;
        }
    }

    if ($to_lockdown) {
        header('HTTP/1.0 403 Forbidden');
        echo 'Access denied.';

        exit();
    }
}

For more advanced security and optimization, consider the Advanced CDN service from our Professional Services team.