/** * Handles the redirect if any found. * * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event * The event to process. */ public function onKernelRequestCheckRedirect(GetResponseEvent $event) { $request = $event->getRequest(); if (!$this->checker->canRedirect($request)) { return; } // Get URL info and process it to be used for hash generation. parse_str($request->getQueryString(), $request_query); $path = ltrim($request->getPathInfo(), '/'); $this->context->fromRequest($request); try { $redirect = $this->redirectRepository->findMatchingRedirect($path, $request_query, $this->languageManager->getCurrentLanguage()->getId()); } catch (RedirectLoopException $e) { \Drupal::logger('redirect')->warning($e->getMessage()); $response = new Response(); $response->setStatusCode(503); $response->setContent('Service unavailable'); $event->setResponse($response); return; } if (!empty($redirect)) { // Handle internal path. $url = $redirect->getRedirectUrl(); if ($this->config->get('passthrough_querystring')) { $url->setOption('query', (array) $url->getOption('query') + $request_query); } $headers = ['X-Redirect-ID' => $redirect->id(), 'X-Drupal-Cache-Tags' => implode(' ', $redirect->getCacheTags())]; $response = new TrustedRedirectResponse($url->setAbsolute()->toString(), $redirect->getStatusCode(), $headers); $event->setResponse($response); } }
/** * Tests redirects being automatically created upon path alias change. */ public function testAutomaticRedirects() { $this->drupalLogin($this->adminUser); // Create a node and update its path alias which should result in a redirect // being automatically created from the old alias to the new one. $node = $this->drupalCreateNode(array('type' => 'article', 'langcode' => Language::LANGCODE_NOT_SPECIFIED, 'path' => array('alias' => '/node_test_alias'))); $this->drupalPostForm('node/' . $node->id() . '/edit', array('path[0][alias]' => '/node_test_alias_updated'), t('Save')); $redirect = $this->repository->findMatchingRedirect('node_test_alias', array(), Language::LANGCODE_NOT_SPECIFIED); $this->assertEqual($redirect->getRedirectUrl()->toString(), Url::fromUri('base:node_test_alias_updated')->toString()); // Test if the automatically created redirect works. $this->assertRedirect('node_test_alias', 'node_test_alias_updated'); // Test that changing the path back deletes the first redirect, creates // a new one and does not result in a loop. $this->drupalPostForm('node/' . $node->id() . '/edit', array('path[0][alias]' => '/node_test_alias'), t('Save')); $redirect = $this->repository->findMatchingRedirect('node_test_alias', array(), Language::LANGCODE_NOT_SPECIFIED); $this->assertTrue(empty($redirect)); \Drupal::service('path.alias_manager')->cacheClear(); $redirect = $this->repository->findMatchingRedirect('node_test_alias_updated', array(), Language::LANGCODE_NOT_SPECIFIED); $this->assertEqual($redirect->getRedirectUrl()->toString(), Url::fromUri('base:node_test_alias')->toString()); // Test if the automatically created redirect works. $this->assertRedirect('node_test_alias_updated', 'node_test_alias'); // Test that the redirect will be deleted upon node deletion. $this->drupalPostForm('node/' . $node->id() . '/delete', array(), t('Delete')); $redirect = $this->repository->findMatchingRedirect('node_test_alias_updated', array(), Language::LANGCODE_NOT_SPECIFIED); $this->assertTrue(empty($redirect)); // Create a term and update its path alias and check if we have a redirect // from the previous path alias to the new one. $term = $this->createTerm($this->createVocabulary()); $this->drupalPostForm('taxonomy/term/' . $term->id() . '/edit', array('path[0][alias]' => '/term_test_alias_updated'), t('Save')); $redirect = $this->repository->findMatchingRedirect('term_test_alias'); $this->assertEqual($redirect->getRedirectUrl()->toString(), Url::fromUri('base:term_test_alias_updated')->toString()); // Test if the automatically created redirect works. $this->assertRedirect('term_test_alias', 'term_test_alias_updated'); // Test the path alias update via the admin path form. $this->drupalPostForm('admin/config/search/path/add', array('source' => '/node', 'alias' => '/aaa_path_alias'), t('Save')); // Note that here we rely on fact that we land on the path alias list page // and the default sort is by the alias, which implies that the first edit // link leads to the edit page of the aaa_path_alias. $this->clickLink(t('Edit')); $this->drupalPostForm(NULL, array('alias' => '/aaa_path_alias_updated'), t('Save')); $redirect = $this->repository->findMatchingRedirect('aaa_path_alias', array(), 'en'); $this->assertEqual($redirect->getRedirectUrl()->toString(), Url::fromUri('base:aaa_path_alias_updated')->toString()); // Test if the automatically created redirect works. $this->assertRedirect('aaa_path_alias', 'aaa_path_alias_updated'); // Test the automatically created redirect shows up in the form correctly. $this->drupalGet('admin/config/search/redirect/edit/' . $redirect->id()); $this->assertFieldByName('redirect_source[0][path]', 'aaa_path_alias'); $this->assertFieldByName('redirect_redirect[0][uri]', '/node'); }
/** * Handles the redirect if any found. * * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event * The event to process. */ public function onKernelRequestCheckRedirect(GetResponseEvent $event) { // Get a clone of the request. During inbound processing the request // can be altered. Allowing this here can lead to unexpected behavior. // For example the path_processor.files inbound processor provided by // the system module alters both the path and the request; only the // changes to the request will be propagated, while the change to the // path will be lost. $request = clone $event->getRequest(); if (!$this->checker->canRedirect($request)) { return; } // Get URL info and process it to be used for hash generation. parse_str($request->getQueryString(), $request_query); // Do the inbound processing so that for example language prefixes are // removed. $path = $this->pathProcessor->processInbound($request->getPathInfo(), $request); $path = ltrim($path, '/'); $this->context->fromRequest($request); try { $redirect = $this->redirectRepository->findMatchingRedirect($path, $request_query, $this->languageManager->getCurrentLanguage()->getId()); } catch (RedirectLoopException $e) { \Drupal::logger('redirect')->warning($e->getMessage()); $response = new Response(); $response->setStatusCode(503); $response->setContent('Service unavailable'); $event->setResponse($response); return; } if (!empty($redirect)) { // Handle internal path. $url = $redirect->getRedirectUrl(); if ($this->config->get('passthrough_querystring')) { $url->setOption('query', (array) $url->getOption('query') + $request_query); } $headers = ['X-Redirect-ID' => $redirect->id()]; $response = new TrustedRedirectResponse($url->setAbsolute()->toString(), $redirect->getStatusCode(), $headers); $response->addCacheableDependency($redirect); $event->setResponse($response); } }