diff --git a/redirect.api.php b/redirect.api.php
index 9ec1bdf..376b32b 100644
--- a/redirect.api.php
+++ b/redirect.api.php
@@ -54,6 +54,31 @@
  */
 
 /**
+ * Act on a redirect response when it is triggered.
+ *
+ * This hook is invoked before the response is sent to the user. The redirect
+ * entity itself is sent as well for inspection.
+ *
+ * @param \Symfony\Component\HttpFoundation\RedirectResponse $response
+ *   The generated redirect response object before it is delivered.
+ * @param \Drupal\redirect\Entity\Redirect $redirect
+ *   The redirect entity used to generate the response object.
+ *
+ * @ingroup redirect_api_hooks
+ */
+function hook_redirect_response_alter(\Symfony\Component\HttpFoundation\RedirectResponse $response, \Drupal\redirect\Entity\Redirect $redirect) {
+  // Set a drupal message.
+  if (!$redirect->getRedirectUrl()->isExternal()) {
+    drupal_set_message(t('You are not being directed off-site.'), 'status');
+  }
+
+  // If `some condition`, send to Drupal.org.
+  if (FALSE) {
+    $response->setTrustedTargetUrl('http://drupal.org');
+  }
+}
+
+/**
  * Act on redirects being loaded from the database.
  *
  * This hook is invoked during redirect loading, which is handled by
@@ -122,21 +147,5 @@ function hook_redirect_prepare($redirect) {
 }
 
 /**
- * Act on a redirect being redirected.
- *
- * This hook is invoked from redirect_redirect() before the redirect callback
- * is invoked.
- *
- * @param $redirect
- *   The redirect that is being used for the redirect.
- *
- * @see redirect_redirect()
- * @see drupal_page_is_cacheable()
- * @ingroup redirect_api_hooks
- */
-function hook_redirect_alter($redirect) {
-}
-
-/**
  * @} End of "addtogroup hooks".
  */
diff --git a/redirect.module b/redirect.module
index 79131a5..d9208ed 100644
--- a/redirect.module
+++ b/redirect.module
@@ -27,7 +27,7 @@ use Drupal\redirect\Entity\Redirect;
  * Implements hook_hook_info().
  */
 function redirect_hook_info() {
-  $hooks = array(
+  $hooks = [
     'redirect_load',
     'redirect_load_by_source_alter',
     'redirect_access',
@@ -38,7 +38,8 @@ function redirect_hook_info() {
     'redirect_update',
     'redirect_delete',
     'redirect_alter',
-  );
+    'redirect_response',
+  ];
 
   return array_fill_keys($hooks, array('group' => 'redirect'));
 }
diff --git a/redirect.services.yml b/redirect.services.yml
index 743bd93..43cb8e3 100644
--- a/redirect.services.yml
+++ b/redirect.services.yml
@@ -11,7 +11,7 @@ services:
     arguments: ['@config.factory', '@state', '@access_manager', '@current_user', '@router.route_provider']
   redirect.request_subscriber:
     class: Drupal\redirect\EventSubscriber\RedirectRequestSubscriber
-    arguments: ['@redirect.repository', '@language_manager', '@config.factory', '@path.alias_manager', '@module_handler', '@entity.manager', '@redirect.checker', '@router.request_context', '@path_processor_manager']
+    arguments: ['@redirect.repository', '@language_manager', '@config.factory', '@module_handler', '@redirect.checker', '@router.request_context', '@path_processor_manager']
     tags:
       - { name: event_subscriber }
   redirect.settings_cache_tag:
diff --git a/src/EventSubscriber/RedirectRequestSubscriber.php b/src/EventSubscriber/RedirectRequestSubscriber.php
index a31fa22..26cce95 100644
--- a/src/EventSubscriber/RedirectRequestSubscriber.php
+++ b/src/EventSubscriber/RedirectRequestSubscriber.php
@@ -2,21 +2,15 @@
 
 namespace Drupal\redirect\EventSubscriber;
 
-use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\Config\ConfigFactoryInterface;
-use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Language\LanguageManagerInterface;
-use Drupal\Core\Logger\RfcLogLevel;
-use Drupal\Core\Path\AliasManager;
 use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
 use Drupal\Core\Routing\TrustedRedirectResponse;
-use Drupal\Core\Url;
 use Drupal\redirect\Exception\RedirectLoopException;
 use Drupal\redirect\RedirectChecker;
 use Drupal\redirect\RedirectRepository;
 use Symfony\Component\HttpFoundation\Response;
-use Symfony\Component\HttpKernel\HttpKernelInterface;
 use Symfony\Component\HttpKernel\KernelEvents;
 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
@@ -41,21 +35,11 @@ class RedirectRequestSubscriber implements EventSubscriberInterface {
   protected $config;
 
   /**
-   * @var \Drupal\Core\Path\AliasManager
-   */
-  protected $aliasManager;
-
-  /**
    * @var \Drupal\Core\Extension\ModuleHandlerInterface
    */
   protected $moduleHandler;
 
   /**
-   * @var \Drupal\Core\Entity\EntityManagerInterface
-   */
-  protected $entityManager;
-
-  /**
    * @var \Drupal\redirect\RedirectChecker
    */
   protected $checker;
@@ -85,20 +69,16 @@ class RedirectRequestSubscriber implements EventSubscriberInterface {
    *   The alias manager service.
    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
    *   The module handler service.
-   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
-   *   The entity manager service.
    * @param \Drupal\redirect\RedirectChecker $checker
    *   The redirect checker service.
    * @param \Symfony\Component\Routing\RequestContext
    *   Request context.
    */
-  public function __construct(RedirectRepository $redirect_repository, LanguageManagerInterface $language_manager, ConfigFactoryInterface $config, AliasManager $alias_manager, ModuleHandlerInterface $module_handler, EntityManagerInterface $entity_manager, RedirectChecker $checker, RequestContext $context, InboundPathProcessorInterface $path_processor) {
+  public function __construct(RedirectRepository $redirect_repository, LanguageManagerInterface $language_manager, ConfigFactoryInterface $config, ModuleHandlerInterface $module_handler, RedirectChecker $checker, RequestContext $context, InboundPathProcessorInterface $path_processor) {
     $this->redirectRepository = $redirect_repository;
     $this->languageManager = $language_manager;
     $this->config = $config->get('redirect.settings');
-    $this->aliasManager = $alias_manager;
     $this->moduleHandler = $module_handler;
-    $this->entityManager = $entity_manager;
     $this->checker = $checker;
     $this->context = $context;
     $this->pathProcessor = $path_processor;
@@ -157,32 +137,10 @@ class RedirectRequestSubscriber implements EventSubscriberInterface {
       ];
       $response = new TrustedRedirectResponse($url->setAbsolute()->toString(), $redirect->getStatusCode(), $headers);
       $response->addCacheableDependency($redirect);
-      $event->setResponse($response);
-    }
-  }
-
-  /**
-   * Prior to set the response it check if we can redirect.
-   *
-   * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
-   *   The event object.
-   * @param \Drupal\Core\Url $url
-   *   The Url where we want to redirect.
-   */
-  protected function setResponse(GetResponseEvent $event, Url $url) {
-    $request = $event->getRequest();
-    $this->context->fromRequest($request);
 
-    parse_str($request->getQueryString(), $query);
-    $url->setOption('query', $query);
-    $url->setAbsolute(TRUE);
+      // Invoke hook_redirect_response_alter().
+      $this->moduleHandler->alter('redirect_response', $response, $redirect);
 
-    // We can only check access for routed URLs.
-    if (!$url->isRouted() || $this->checker->canRedirect($request, $url->getRouteName())) {
-      // Add the 'rendered' cache tag, so that we can invalidate all responses
-      // when settings are changed.
-      $response = new TrustedRedirectResponse($url->toString(), 301);
-      $response->addCacheableDependency(CacheableMetadata::createFromRenderArray([])->addCacheTags(['rendered']));
       $event->setResponse($response);
     }
   }
diff --git a/src/Tests/GlobalRedirectTest.php b/src/Tests/GlobalRedirectTest.php
index c457f82..9696e2a 100644
--- a/src/Tests/GlobalRedirectTest.php
+++ b/src/Tests/GlobalRedirectTest.php
@@ -2,9 +2,7 @@
 
 namespace Drupal\redirect\Tests;
 
-use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Language\Language;
-use Drupal\simpletest\WebTestBase;
 use Drupal\language\Entity\ConfigurableLanguage;
 
 /**
@@ -12,7 +10,7 @@ use Drupal\language\Entity\ConfigurableLanguage;
  *
  * @group redirect
  */
-class GlobalRedirectTest extends WebTestBase {
+class GlobalRedirectTest extends RedirectTestBase {
 
   /**
    * Modules to enable.
@@ -235,42 +233,4 @@ class GlobalRedirectTest extends WebTestBase {
     // Test multilingual redirect.
     $this->assertRedirect('es/node/' . $spanish_node->id(), 'es/spanish-test-node');
   }
-
-  /**
-   * Asserts the redirect from $path to the $expected_ending_url.
-   *
-   * @param string $path
-   *   The request path.
-   * @param $expected_ending_url
-   *   The path where we expect it to redirect. If NULL value provided, no
-   *   redirect is expected.
-   * @param string $expected_ending_status
-   *   The status we expect to get with the first request.
-   */
-  public function assertRedirect($path, $expected_ending_url, $expected_ending_status = 'HTTP/1.1 301 Moved Permanently') {
-    $this->drupalHead($GLOBALS['base_url'] . '/' . $path);
-    $headers = $this->drupalGetHeaders(TRUE);
-
-    $ending_url = isset($headers[0]['location']) ? $headers[0]['location'] : NULL;
-    $message = SafeMarkup::format('Testing redirect from %from to %to. Ending url: %url', array(
-      '%from' => $path,
-      '%to' => $expected_ending_url,
-      '%url' => $ending_url,
-    ));
-
-
-    if ($expected_ending_url == '<front>') {
-      $expected_ending_url = $GLOBALS['base_url'] . '/';
-    }
-    elseif (!empty($expected_ending_url)) {
-      $expected_ending_url = $GLOBALS['base_url'] . '/' . $expected_ending_url;
-    }
-    else {
-      $expected_ending_url = NULL;
-    }
-
-    $this->assertEqual($expected_ending_url, $ending_url);
-
-    $this->assertEqual($headers[0][':status'], $expected_ending_status);
-  }
 }
diff --git a/src/Tests/RedirectTestBase.php b/src/Tests/RedirectTestBase.php
new file mode 100644
index 0000000..a526662
--- /dev/null
+++ b/src/Tests/RedirectTestBase.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace Drupal\redirect\Tests;
+
+use Drupal\Component\Utility\SafeMarkup;
+use Drupal\simpletest\WebTestBase;
+
+abstract class RedirectTestBase extends WebTestBase {
+
+  /**
+   * Asserts the redirect from $path to the $expected_ending_url.
+   *
+   * @param string $path
+   *   The request path.
+   * @param $expected_ending_url
+   *   The path where we expect it to redirect. If NULL value provided, no
+   *   redirect is expected.
+   * @param string $expected_ending_status
+   *   The status we expect to get with the first request.
+   */
+  public function assertRedirect($path, $expected_ending_url, $expected_ending_status = 'HTTP/1.1 301 Moved Permanently') {
+    $this->drupalHead($GLOBALS['base_url'] . '/' . $path);
+    $headers = $this->drupalGetHeaders(TRUE);
+
+    $ending_url = isset($headers[0]['location']) ? $headers[0]['location'] : NULL;
+    $message = SafeMarkup::format('Testing redirect from %from to %to. Ending url: %url', array(
+      '%from' => $path,
+      '%to' => $expected_ending_url,
+      '%url' => $ending_url,
+    ));
+
+
+    if ($expected_ending_url == '<front>') {
+      $expected_ending_url = $GLOBALS['base_url'] . '/';
+    }
+    elseif (!empty($expected_ending_url)) {
+      $expected_ending_url = $GLOBALS['base_url'] . '/' . $expected_ending_url;
+    }
+    else {
+      $expected_ending_url = NULL;
+    }
+
+    $this->assertEqual($expected_ending_url, $ending_url);
+
+    $this->assertEqual($headers[0][':status'], $expected_ending_status);
+  }
+
+}
diff --git a/tests/modules/redirect_test/redirect_test.info.yml b/tests/modules/redirect_test/redirect_test.info.yml
new file mode 100644
index 0000000..422ce52
--- /dev/null
+++ b/tests/modules/redirect_test/redirect_test.info.yml
@@ -0,0 +1,7 @@
+name: 'Redirect module tests'
+type: module
+description: 'Support module for redirect testing.'
+package: Testing
+core: 8.x
+dependencies:
+  - drupal:redirect
diff --git a/tests/modules/redirect_test/redirect_test.module b/tests/modules/redirect_test/redirect_test.module
new file mode 100644
index 0000000..37cfd7f
--- /dev/null
+++ b/tests/modules/redirect_test/redirect_test.module
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * @file
+ * A test module for testing the redirect module.
+ */
+
+use Drupal\redirect\Entity\Redirect;
+use Symfony\Component\HttpFoundation\RedirectResponse;
+
+/**
+ * Implements hook_redirect_response_alter().
+ */
+function redirect_test_redirect_response_alter(RedirectResponse $response, Redirect $redirect) {
+  $path = 'test/redirect/2/successful';
+  $replace = 'test/redirect/other';
+  if ($redirect->getRedirect()['uri'] == "internal:/" . $path) {
+    $response->setTargetUrl(str_replace($path, $replace, $redirect->getRedirectUrl()->setAbsolute()->toString()));
+  }
+}
diff --git a/tests/src/Functional/RedirectHooksTest.php b/tests/src/Functional/RedirectHooksTest.php
new file mode 100644
index 0000000..578dd90
--- /dev/null
+++ b/tests/src/Functional/RedirectHooksTest.php
@@ -0,0 +1,55 @@
+<?php
+
+namespace Drupal\Tests\redirect\Functional;
+
+use Drupal\redirect\Tests\RedirectTestBase;
+use Drupal\redirect\Entity\Redirect;
+
+/**
+ * Test the functionality of the Redirect module hooks.
+ *
+ * @ingroup redirect_api_hooks
+ *
+ * @group redirect
+ */
+class RedirectHooksTest extends RedirectTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = ['redirect_test'];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $profile = 'minimal';
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+
+    // Create two redirects.
+    $redirect = Redirect::create();
+    $redirect->setSource('/test/redirect/1');
+    $redirect->setRedirect('/test/redirect/1/successful');
+    $redirect->setStatusCode(301);
+    $redirect->save();
+
+    $redirect = Redirect::create();
+    $redirect->setSource('/test/redirect/2');
+    $redirect->setRedirect('/test/redirect/2/successful');
+    $redirect->setStatusCode(301);
+    $redirect->save();
+  }
+
+  /**
+   * Test the redirects.
+   */
+  public function testRedirectResponseHook() {
+    $this->assertRedirect('test/redirect/1', 'test/redirect/1/successful');
+    $this->assertRedirect('test/redirect/2', 'test/redirect/other');
+  }
+
+}
