So... I think I have solved this, although cache testing has not yet been done (any thoughts on how to do this welcome!).
Credit to this post for the outline solution, and also to this one for D8 redirects.
First, I create a custom module called mysite_homepage_redirect - it needs the following mysite_homepage_redirect.services.yml
file (apparently a priority > 200 means it gets fired before the cache):
services:
http_middleware.mysite_homepage_redirect:
class: Drupal\mysite_homepage_redirect\StackMiddleware\MysiteHomepageRedirect
tags:
- { name: http_middleware, priority: 250, responder: true }
Then we need the following in src/mysite_homepage_redirect/StackMiddleware/MysiteHomepageRedirect.php
:
<?php
namespace Drupal\mysite_homepage_redirect\StackMiddleware;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
/**
* Provides a HTTP middleware.
*/
class MysiteHomepageRedirect implements HttpKernelInterface {
/**
* Map of pages that should be redirected to from home
* this coulde ultimately be put into config with an admin screen
*/
private $navigation_map = array(
'/employers',
'/students',
);
/**
* The wrapped HTTP kernel.
*
* @var \Symfony\Component\HttpKernel\HttpKernelInterface
*/
protected $httpKernel;
/**
* Constructs a MyModule object.
*
* @param \Symfony\Component\HttpKernel\HttpKernelInterface $kernel
* The decorated kernel.
* @param mixed $optional_argument
* (optional) An optional argument.
*/
public function __construct(HttpKernelInterface $http_kernel) {
$this->httpKernel = $http_kernel;
}
/**
* {@inheritdoc}
*/
public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) {
$current = $request->server->get('REQUEST_URI');
$source = $request->server->get('HTTP_REFERER');
$host = $request->server->get('HTTP_HOST');
//cut the host string out of the referer
$x = strpos($source, $host);
if($x) {
$source = substr($source, $x + strlen($host));
}
$redir = isset($_COOKIE['mysite_homepage_redirect']) ? $_COOKIE['mysite_homepage_redirect'] : false;
if($current == '/' && strpos($source, $host) === false && $redir) {
$response = new RedirectResponse($redir, 302);
$response->send();
return;
}
elseif(in_array($current, $this->navigation_map) && $source == '/') {
//need to use native setcookie() because user_cookie_save relies on the user module which is not yet loaded
//expires in 30 days
setcookie('mysite_homepage_redirect', $current, time() + 86400 * 30);
\Drupal::logger('mysite_homepage_redirect')->notice("saved redirect cookie: " . $current);
}
return $this->httpKernel->handle($request, $type, $catch);
}
}
That seems to work as expected. The cookie seemed the simplest way to save the redirect. Any further thoughts welcome!