diff -u b/core/lib/Drupal/Core/EventSubscriber/RouteNormalizerRequestSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/RouteNormalizerRequestSubscriber.php --- b/core/lib/Drupal/Core/EventSubscriber/RouteNormalizerRequestSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/RouteNormalizerRequestSubscriber.php @@ -127 +127 @@ -} \ No newline at end of file +} diff -u b/core/lib/Drupal/Core/Routing/UrlGenerator.php b/core/lib/Drupal/Core/Routing/UrlGenerator.php --- b/core/lib/Drupal/Core/Routing/UrlGenerator.php +++ b/core/lib/Drupal/Core/Routing/UrlGenerator.php @@ -162,8 +162,8 @@ * The route name or other identifying string from ::getRouteDebugMessage(). * * @return string - * The URL-encoded path, without any base path, without the query string, not URL - * encoded. + * The URL-encoded path, without any base path, without the query string, + * not URL encoded. * * @throws MissingMandatoryParametersException * When some parameters are missing that are mandatory for the route. @@ -238,8 +238,8 @@ * $parameters merged in. * * @return string - * The URL-encoded path corresponding to the route, without the base path, not URL - * encoded. + * The URL-encoded path corresponding to the route, without the base path, + * not URL encoded. */ protected function getInternalPathFromRoute($name, SymfonyRoute $route, $parameters = [], &$query_params = []) { // The Route has a cache of its own and is not recompiled as long as it does diff -u b/core/lib/Drupal/Core/Routing/UrlGeneratorInterface.php b/core/lib/Drupal/Core/Routing/UrlGeneratorInterface.php --- b/core/lib/Drupal/Core/Routing/UrlGeneratorInterface.php +++ b/core/lib/Drupal/Core/Routing/UrlGeneratorInterface.php @@ -21,8 +21,8 @@ * \Symfony\Component\Routing\Generator\UrlGeneratorInterface::generate(). * * @return string - * The internal Drupal URL-encoded path corresponding to the route. This string is - * not urlencoded and will be an empty string for the front page. + * The internal Drupal URL-encoded path corresponding to the route. This + * string is not urlencoded and will be an empty string for the front page. */ public function getPathFromRoute($name, $parameters = []); diff -u b/core/tests/Drupal/FunctionalTests/Routing/RouteNormalizerTest.php b/core/tests/Drupal/FunctionalTests/Routing/RouteNormalizerTest.php --- b/core/tests/Drupal/FunctionalTests/Routing/RouteNormalizerTest.php +++ b/core/tests/Drupal/FunctionalTests/Routing/RouteNormalizerTest.php @@ -116 +116 @@ -} \ No newline at end of file +} only in patch2: unchanged: --- a/core/lib/Drupal/Core/PathProcessor/PathProcessorAlias.php +++ b/core/lib/Drupal/Core/PathProcessor/PathProcessorAlias.php @@ -2,6 +2,7 @@ namespace Drupal\Core\PathProcessor; +use Drupal\Component\Utility\UrlHelper; use Drupal\Core\Path\AliasManagerInterface; use Drupal\Core\Render\BubbleableMetadata; use Symfony\Component\HttpFoundation\Request; @@ -42,7 +43,7 @@ public function processInbound($path, Request $request) { public function processOutbound($path, &$options = [], Request $request = NULL, BubbleableMetadata $bubbleable_metadata = NULL) { if (empty($options['alias'])) { $langcode = isset($options['language']) ? $options['language']->getId() : NULL; - $path = $this->aliasManager->getAliasByPath($path, $langcode); + $path = UrlHelper::encodePath($this->aliasManager->getAliasByPath(rawurldecode($path), $langcode)); } return $path; } only in patch2: unchanged: --- a/core/lib/Drupal/Core/Url.php +++ b/core/lib/Drupal/Core/Url.php @@ -776,7 +776,7 @@ public function toRenderArray() { * This path will not include any prefixes, fragments, or query strings. * * @return string - * The internal path for this route. + * The internal URL-encoded path for this route. * * @throws \UnexpectedValueException. * If this is a URI with no corresponding system path. only in patch2: unchanged: --- a/core/lib/Drupal/Core/Utility/UnroutedUrlAssembler.php +++ b/core/lib/Drupal/Core/Utility/UnroutedUrlAssembler.php @@ -109,6 +109,9 @@ protected function buildLocalUrl($uri, array $options = [], $collect_bubbleable_ // https://www.drupal.org/node/2417459 $uri = substr($uri, 5); + // The path should be URl-encoded before possible path processing. + $uri = UrlHelper::encodePath($uri); + // Allow (outbound) path processing, if needed. A valid use case is the path // alias overview form: // @see \Drupal\path\Controller\PathController::adminOverview(). @@ -150,7 +153,7 @@ protected function buildLocalUrl($uri, array $options = [], $collect_bubbleable_ $prefix = empty($uri) ? rtrim($options['prefix'], '/') : $options['prefix']; - $uri = str_replace('%2F', '/', rawurlencode($prefix . $uri)); + $uri = UrlHelper::encodePath($prefix) . $uri; $query = $options['query'] ? ('?' . UrlHelper::buildQuery($options['query'])) : ''; $url = $base . $options['script'] . $uri . $query . $options['fragment']; return $collect_bubbleable_metadata ? $generated_url->setGeneratedUrl($url) : $url; only in patch2: unchanged: --- a/core/modules/book/tests/src/Functional/BookTest.php +++ b/core/modules/book/tests/src/Functional/BookTest.php @@ -432,6 +432,10 @@ public function testBookNavigationBlock() { // Test correct display of the block. $nodes = $this->createBook(); + // It may happen that user is redirected to the front page during the + // logout, so the front page may be already cached and we did no action to + // clear the cache so far. Do it now. + Cache::invalidateTags(['rendered']); $this->drupalGet(''); $this->assertText($block->label(), 'Book navigation block is displayed.'); $this->assertText($this->book->label(), format_string('Link to book root (@title) is displayed.', ['@title' => $nodes[0]->label()])); only in patch2: unchanged: --- a/core/modules/image/src/PathProcessor/PathProcessorImageStyles.php +++ b/core/modules/image/src/PathProcessor/PathProcessorImageStyles.php @@ -65,6 +65,9 @@ public function processInbound($path, Request $request) { // Set the file as query parameter. $request->query->set('file', $file); + // Disable route normalizer since we changed the request object. + $request->attributes->set('_disable_route_normalizer', TRUE); + return $path_prefix . $image_style . '/' . $scheme; } else { only in patch2: unchanged: --- a/core/modules/language/tests/src/Functional/LanguageListTest.php +++ b/core/modules/language/tests/src/Functional/LanguageListTest.php @@ -149,6 +149,10 @@ public function testLanguageList() { 'direction' => Language::DIRECTION_LTR, ]; $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language')); + // As we changed the amount of languages, rebuilt the container so that + // \Drupal\language\LanguageServiceProvider (un)register its services and we + // can construct the correct URL. + $this->rebuildContainer(); $this->assertUrl(\Drupal::url('entity.configurable_language.collection', [], ['absolute' => TRUE])); $this->assertText($name, 'Name found.'); only in patch2: unchanged: --- a/core/modules/path/tests/src/Functional/PathAliasTest.php +++ b/core/modules/path/tests/src/Functional/PathAliasTest.php @@ -33,6 +33,12 @@ protected function setUp() { * Tests the path cache. */ public function testPathCache() { + + // Disable the route normalizer, because otherwise internal paths are + // redirected to their aliases and no "preload-paths:" cache is set. + $this->setContainerParameter('route_normalizer_enabled', FALSE); + $this->rebuildContainer(); + // Create test node. $node1 = $this->drupalCreateNode(); only in patch2: unchanged: --- a/core/modules/simpletest/src/Tests/BrowserTest.php +++ b/core/modules/simpletest/src/Tests/BrowserTest.php @@ -38,6 +38,10 @@ protected function setUp() { * Test \Drupal\simpletest\WebTestBase::getAbsoluteUrl(). */ public function testGetAbsoluteUrl() { + + // Change the frontpage to something else than the default "/user/login". + $this->config('system.site')->set('page.front', '/user/password')->save(); + $url = 'user/login'; $this->drupalGet($url); only in patch2: unchanged: --- a/core/modules/simpletest/src/Tests/SimpleTestBrowserTest.php +++ b/core/modules/simpletest/src/Tests/SimpleTestBrowserTest.php @@ -56,6 +56,7 @@ public function testInternalBrowser() { $this->assertEqual(0, $this->container->get('current_user')->id(), 'Current user service updated.'); // Test the maximum redirection option. + $maximum_redirects_original = $this->maximumRedirects; $this->maximumRedirects = 1; $edit = [ 'name' => $user->getUsername(), @@ -66,6 +67,7 @@ public function testInternalBrowser() { ]); $headers = $this->drupalGetHeaders(TRUE); $this->assertEqual(count($headers), 2, 'Simpletest stopped following redirects after the first one.'); + $this->maximumRedirects = $maximum_redirects_original; // Remove the Simpletest private key file so we can test the protection // against requests that forge a valid testing user agent to gain access