diff --git a/core/lib/Drupal/Core/Access/CsrfAccessCheck.php b/core/lib/Drupal/Core/Access/CsrfAccessCheck.php
index 9744d6c..9a935c3 100644
--- a/core/lib/Drupal/Core/Access/CsrfAccessCheck.php
+++ b/core/lib/Drupal/Core/Access/CsrfAccessCheck.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\Routing\Access\AccessInterface as RoutingAccessInterface;
+use Drupal\Core\RequestInfo;
 use Symfony\Component\Routing\Route;
 use Symfony\Component\HttpFoundation\Request;
 
@@ -44,7 +45,7 @@ function __construct(CsrfTokenGenerator $csrf_token) {
   public function access(Route $route, Request $request, AccountInterface $account) {
     // If this is the controller request, check CSRF access as normal.
     if ($request->attributes->get('_controller_request')) {
-      return $this->csrfToken->validate($request->query->get('token'), $request->attributes->get('_system_path')) ? static::ALLOW : static::KILL;
+      return $this->csrfToken->validate($request->query->get('token'), RequestInfo::get($request)->getSystemPath()) ? static::ALLOW : static::KILL;
     }
 
     // Otherwise, this could be another requested access check that we don't
diff --git a/core/lib/Drupal/Core/Controller/ExceptionController.php b/core/lib/Drupal/Core/Controller/ExceptionController.php
index d79567c..7a256a5 100644
--- a/core/lib/Drupal/Core/Controller/ExceptionController.php
+++ b/core/lib/Drupal/Core/Controller/ExceptionController.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Page\HtmlPageRendererInterface;
 use Drupal\Core\StringTranslation\TranslationInterface;
+use Drupal\Core\RequestInfo;
 use Symfony\Component\DependencyInjection\ContainerAwareInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpFoundation\Request;
@@ -135,7 +136,7 @@ public function on405Html(FlattenException $exception, Request $request) {
    *   A response object.
    */
   public function on403Html(FlattenException $exception, Request $request) {
-    $system_path = $request->attributes->get('_system_path');
+    $system_path = RequestInfo::get($request)->getSystemPath();
     watchdog('access denied', $system_path, NULL, WATCHDOG_WARNING);
 
     $system_config = $this->container->get('config.factory')->get('system.site');
@@ -200,7 +201,8 @@ public function on403Html(FlattenException $exception, Request $request) {
    *   A response object.
    */
   public function on404Html(FlattenException $exception, Request $request) {
-    watchdog('page not found', String::checkPlain($request->attributes->get('_system_path')), NULL, WATCHDOG_WARNING);
+    $system_path = RequestInfo::get($request)->getSystemPath();
+    watchdog('page not found', String::checkPlain($system_path), NULL, WATCHDOG_WARNING);
 
     // Check for and return a fast 404 page if configured.
     $config = \Drupal::config('system.performance');
@@ -215,7 +217,6 @@ public function on404Html(FlattenException $exception, Request $request) {
       }
     }
 
-    $system_path = $request->attributes->get('_system_path');
 
     // Keep old path for reference, and to allow forms to redirect to it.
     if (!$request->query->has('destination')) {
diff --git a/core/lib/Drupal/Core/EventSubscriber/PathListenerBase.php b/core/lib/Drupal/Core/EventSubscriber/PathListenerBase.php
index 39cc101..636b1f3 100644
--- a/core/lib/Drupal/Core/EventSubscriber/PathListenerBase.php
+++ b/core/lib/Drupal/Core/EventSubscriber/PathListenerBase.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\EventSubscriber;
 
+use Drupal\Core\RequestInfo;
 use Symfony\Component\HttpFoundation\Request;
 
 /**
@@ -15,7 +16,7 @@
 abstract class PathListenerBase {
 
   public function extractPath(Request $request) {
-    $path = $request->attributes->get('_system_path');
+    $path = RequestInfo::get($request)->getSystemPath();
     return isset($path) ? $path : trim($request->getPathInfo(), '/');
   }
 
diff --git a/core/lib/Drupal/Core/Form/FormBuilder.php b/core/lib/Drupal/Core/Form/FormBuilder.php
index 1231689..caa4734 100644
--- a/core/lib/Drupal/Core/Form/FormBuilder.php
+++ b/core/lib/Drupal/Core/Form/FormBuilder.php
@@ -19,6 +19,7 @@
 use Drupal\Core\Routing\UrlGeneratorInterface;
 use Drupal\Core\StringTranslation\TranslationInterface;
 use Drupal\Core\Url;
+use Drupal\Core\RequestInfo;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 use Symfony\Component\HttpFoundation\Request;
@@ -812,7 +813,7 @@ public function validateForm($form_id, &$form, &$form_state) {
     // matches the current user's session.
     if (isset($form['#token'])) {
       if (!$this->csrfToken->validate($form_state['values']['form_token'], $form['#token'])) {
-        $path = $this->request->attributes->get('_system_path');
+        $path = RequestInfo::get($this->request)->getSystemPath();
         $query = UrlHelper::filterQueryParameters($this->request->query->all());
         $url = $this->urlGenerator->generateFromPath($path, array('query' => $query));
 
@@ -944,7 +945,7 @@ public function redirectForm($form_state) {
           }
         }
       }
-      $url = $this->urlGenerator->generateFromPath($this->request->attributes->get('_system_path'), array(
+      $url = $this->urlGenerator->generateFromPath(RequestInfo::get($this->request)->getSystemPath(), array(
         'query' => $this->request->query->all(),
         'absolute' => TRUE,
       ));
diff --git a/core/lib/Drupal/Core/RequestInfo.php b/core/lib/Drupal/Core/RequestInfo.php
new file mode 100644
index 0000000..bba0121
--- /dev/null
+++ b/core/lib/Drupal/Core/RequestInfo.php
@@ -0,0 +1,86 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\Routing\RequestContext.
+ */
+
+namespace Drupal\Core;
+
+use Symfony\Cmf\Component\Routing\RouteObjectInterface;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Provides easy access to some routing related request information.
+ */
+class RequestInfo {
+
+  /**
+   * The request.
+   *
+   * @var \Symfony\Component\HttpFoundation\Request
+   */
+  protected $request;
+
+  /**
+   * Constructs a new RequestInfo.
+   *
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The request.
+   */
+  public function __construct(Request $request) {
+    $this->request = $request;
+  }
+
+  /**
+   * Gets a new instance of a request context.
+   *
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *
+   * @return static
+   *   An instance of the routing request context.
+   */
+  public static function get(Request $request) {
+    return new RequestInfo($request);
+  }
+
+  /**
+   * Get the route name.
+   *
+   * @return string
+   */
+  public function getRouteName() {
+    return $this->request->attributes->get(RouteObjectInterface::ROUTE_NAME);
+  }
+
+  /**
+   * Get the route object.
+   *
+   * @return \Symfony\Component\Routing\Route
+   */
+  public function getRouteObject() {
+    return $this->request->attributes->get(RouteObjectInterface::ROUTE_OBJECT);
+  }
+
+  /**
+   * Gets the internal path.
+   *
+   * @return string
+   *   The internal requested path without path aliases.
+   */
+  public function getSystemPath() {
+    return $this->request->attributes->get('_system_path');
+  }
+
+  /**
+   * Gets the raw variables.
+   *
+   * @return \Symfony\Component\HttpFoundation\ParameterBag
+   *   The original variables prior to conversion by the ParamConverterManager.
+   */
+  public function getRawVariables() {
+    return $this->request->attributes->get('_raw_variables');
+  }
+
+}
+
diff --git a/core/lib/Drupal/Core/Routing/RouteProvider.php b/core/lib/Drupal/Core/Routing/RouteProvider.php
index 20b0ec1..9d68995 100644
--- a/core/lib/Drupal/Core/Routing/RouteProvider.php
+++ b/core/lib/Drupal/Core/Routing/RouteProvider.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\Routing;
 
 use Drupal\Component\Utility\String;
+use Drupal\Core\RequestInfo;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\Routing\Exception\RouteNotFoundException;
@@ -100,7 +101,7 @@ public function getRouteCollectionForRequest(Request $request) {
     // @todo Consider abstracting this to a separate object.
     if ($request->attributes->has('_system_path')) {
       // _system_path never has leading or trailing slashes.
-      $path = '/' . $request->attributes->get('_system_path');
+      $path = '/' . RequestInfo::get($request)->getSystemPath();
     }
     else {
       // getPathInfo() always has leading slash, and might or might not have a
diff --git a/core/modules/block/block.module b/core/modules/block/block.module
index 1bca18b..c638c1c 100644
--- a/core/modules/block/block.module
+++ b/core/modules/block/block.module
@@ -7,6 +7,7 @@
 
 use Drupal\block\BlockInterface;
 use Drupal\Component\Plugin\Exception\PluginException;
+use Drupal\Core\RequestInfo;
 use Symfony\Cmf\Component\Routing\RouteObjectInterface;
 
 /**
@@ -119,7 +120,7 @@ function block_page_build(&$page) {
 
   // Fetch a list of regions for the current theme.
   $all_regions = system_region_list($theme);
-  if (\Drupal::request()->attributes->get(RouteObjectInterface::ROUTE_NAME) != 'block.admin_demo') {
+  if (RequestInfo::get(\Drupal::request())->getRouteName() != 'block.admin_demo') {
     // Load all region content assigned via blocks.
     foreach (array_keys($all_regions) as $region) {
       // Assign blocks to region.
diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Menu/LocalAction/CustomBlockAddLocalAction.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Menu/LocalAction/CustomBlockAddLocalAction.php
index af9b359..3422217 100644
--- a/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Menu/LocalAction/CustomBlockAddLocalAction.php
+++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Menu/LocalAction/CustomBlockAddLocalAction.php
@@ -8,6 +8,7 @@
 namespace Drupal\custom_block\Plugin\Menu\LocalAction;
 
 use Drupal\Core\Menu\LocalActionDefault;
+use Drupal\Core\RequestInfo;
 use Symfony\Cmf\Component\Routing\RouteObjectInterface;
 use Symfony\Component\HttpFoundation\Request;
 
@@ -26,11 +27,11 @@ public function getOptions(Request $request) {
       $options['query']['theme'] = $request->attributes->get('theme');
     }
     // Adds a destination on custom block listing.
-    if ($request->attributes->get(RouteObjectInterface::ROUTE_NAME) == 'custom_block.list') {
+    if (RequestInfo::get($request)->getRouteName() == 'custom_block.list') {
       $options['query']['destination'] = 'admin/structure/block/custom-blocks';
     }
     // Adds a destination on custom block listing.
-    if ($request->attributes->get(RouteObjectInterface::ROUTE_NAME) == 'custom_block.list') {
+    if (RequestInfo::get($request)->getRouteName() == 'custom_block.list') {
       $options['query']['destination'] = 'admin/structure/block/custom-blocks';
     }
     return $options;
diff --git a/core/modules/block/lib/Drupal/block/Theme/AdminDemoNegotiator.php b/core/modules/block/lib/Drupal/block/Theme/AdminDemoNegotiator.php
index d175b91..48c655b 100644
--- a/core/modules/block/lib/Drupal/block/Theme/AdminDemoNegotiator.php
+++ b/core/modules/block/lib/Drupal/block/Theme/AdminDemoNegotiator.php
@@ -8,6 +8,7 @@
 namespace Drupal\block\Theme;
 
 use Drupal\Core\Theme\ThemeNegotiatorInterface;
+use Drupal\Core\RequestInfo;
 use Symfony\Cmf\Component\Routing\RouteObjectInterface;
 use Symfony\Component\HttpFoundation\Request;
 
@@ -20,7 +21,7 @@ class AdminDemoNegotiator implements ThemeNegotiatorInterface {
    * {@inheritdoc}
    */
   public function applies(Request $request) {
-    return $request->attributes->get(RouteObjectInterface::ROUTE_NAME) == 'block.admin_demo';
+    return RequestInfo::get($request)->getRouteName() == 'block.admin_demo';
   }
 
   /**
diff --git a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationController.php b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationController.php
index 0235678..ebed292 100644
--- a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationController.php
+++ b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationController.php
@@ -15,6 +15,7 @@
 use Drupal\Core\ParamConverter\ParamNotConvertedException;
 use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
 use Drupal\Core\Session\AccountInterface;
+use Drupal\Core\RequestInfo;
 use Symfony\Cmf\Component\Routing\RouteObjectInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpFoundation\Request;
@@ -170,7 +171,7 @@ public function itemPage(Request $request, $plugin_id) {
         $route_request = $this->getRequestForPath($request, $mapper->getBasePath());
         $edit_access = FALSE;
         if (!empty($route_request)) {
-          $route_name = $route_request->attributes->get(RouteObjectInterface::ROUTE_NAME);
+          $route_name = RequestInfo::get($route_request)->getRouteName();
           // Note that the parameters don't really matter here since we're
           // passing in the request which already has the upcast attributes.
           $parameters = array();
diff --git a/core/modules/edit/edit.module b/core/modules/edit/edit.module
index 1aea385..7c5b138 100644
--- a/core/modules/edit/edit.module
+++ b/core/modules/edit/edit.module
@@ -13,6 +13,7 @@
 
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
+use Drupal\Core\RequestInfo;
 
 /**
  * Implements hook_permission().
@@ -37,7 +38,7 @@ function edit_page_build(&$page) {
   }
 
   // In-place editing is only supported on the front-end.
-  $path = \Drupal::request()->attributes->get('_system_path');
+  $path = RequestInfo::get(\Drupal::request())->getSystemPath();
   if (path_is_admin($path)) {
     return;
   }
diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module
index ba0b04a..e2fe92a 100644
--- a/core/modules/shortcut/shortcut.module
+++ b/core/modules/shortcut/shortcut.module
@@ -5,6 +5,7 @@
  * Allows users to manage customizable lists of shortcut links.
  */
 
+use Drupal\Core\RequestInfo;
 use Drupal\Core\Routing\UrlMatcher;
 use Drupal\Core\Url;
 use Drupal\shortcut\ShortcutSetInterface;
@@ -366,7 +367,7 @@ function shortcut_preprocess_page(&$variables) {
   $request = \Drupal::request();
   $item = array();
   if ($route = $request->attributes->get(RouteObjectInterface::ROUTE_NAME)) {
-    $item['href'] = $request->attributes->get('_system_path');
+    $item['href'] = RequestInfo::get($request)->getSystemPath();
     // @todo What should be done on a 404/403 page?
     $item['access'] = TRUE;
   }
diff --git a/core/modules/system/lib/Drupal/system/Plugin/Block/SystemHelpBlock.php b/core/modules/system/lib/Drupal/system/Plugin/Block/SystemHelpBlock.php
index f669e61..0fb3c08 100644
--- a/core/modules/system/lib/Drupal/system/Plugin/Block/SystemHelpBlock.php
+++ b/core/modules/system/lib/Drupal/system/Plugin/Block/SystemHelpBlock.php
@@ -10,6 +10,7 @@
 use Drupal\block\BlockBase;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\Core\RequestInfo;
 use Drupal\Core\Session\AccountInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpFoundation\Request;
@@ -90,7 +91,7 @@ public function access(AccountInterface $account) {
    */
   protected function getActiveHelp(Request $request) {
     $output = '';
-    $router_path = $request->attributes->get('_system_path');
+    $router_path = RequestInfo::get($request)->getSystemPath();
     // We will always have a path unless we are on a 403 or 404.
     if (!$router_path) {
       return '';
diff --git a/core/modules/system/tests/modules/menu_test/lib/Drupal/menu_test/EventSubscriber/MaintenanceModeSubscriber.php b/core/modules/system/tests/modules/menu_test/lib/Drupal/menu_test/EventSubscriber/MaintenanceModeSubscriber.php
index 2071a37..5973084 100644
--- a/core/modules/system/tests/modules/menu_test/lib/Drupal/menu_test/EventSubscriber/MaintenanceModeSubscriber.php
+++ b/core/modules/system/tests/modules/menu_test/lib/Drupal/menu_test/EventSubscriber/MaintenanceModeSubscriber.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\menu_test\EventSubscriber;
 
+use Drupal\Core\RequestInfo;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
 use Symfony\Component\HttpKernel\KernelEvents;
@@ -25,7 +26,7 @@ class MaintenanceModeSubscriber implements EventSubscriberInterface {
   public function onKernelRequestMaintenance(GetResponseEvent $event) {
     $request = $event->getRequest();
     // Allow access to menu_login_callback even if in maintenance mode.
-    if ($request->attributes->get('_maintenance') == MENU_SITE_OFFLINE && $request->attributes->get('_system_path') == 'menu_login_callback') {
+    if ($request->attributes->get('_maintenance') == MENU_SITE_OFFLINE && RequestInfo::get($request)->getSystemPath() == 'menu_login_callback') {
       $request->attributes->set('_maintenance', MENU_SITE_ONLINE);
     }
   }
diff --git a/core/modules/system/tests/modules/system_test/system_test.module b/core/modules/system/tests/modules/system_test/system_test.module
index 4d3601b..44d0dc8 100644
--- a/core/modules/system/tests/modules/system_test/system_test.module
+++ b/core/modules/system/tests/modules/system_test/system_test.module
@@ -1,6 +1,7 @@
 <?php
 
 use Drupal\Core\Extension\Extension;
+use Drupal\Core\RequestInfo;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 
 /**
@@ -107,7 +108,7 @@ function system_test_lock_exit() {
  * Implements hook_page_build().
  */
 function system_test_page_build(&$page) {
-  $menu_item['path'] = \Drupal::request()->attributes->get('_system_path');
+  $menu_item['path'] = RequestInfo::get(\Drupal::request())->getSystemPath();
   $main_content_display = &drupal_static('system_main_content_added', FALSE);
 
   if ($menu_item['path'] == 'system-test/main-content-handling') {
diff --git a/core/modules/system/tests/modules/theme_test/lib/Drupal/theme_test/EventSubscriber/ThemeTestSubscriber.php b/core/modules/system/tests/modules/theme_test/lib/Drupal/theme_test/EventSubscriber/ThemeTestSubscriber.php
index d3676e0..678a662 100644
--- a/core/modules/system/tests/modules/theme_test/lib/Drupal/theme_test/EventSubscriber/ThemeTestSubscriber.php
+++ b/core/modules/system/tests/modules/theme_test/lib/Drupal/theme_test/EventSubscriber/ThemeTestSubscriber.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\theme_test\EventSubscriber;
 
+use Drupal\Core\RequestInfo;
 use Symfony\Component\DependencyInjection\ContainerAware;
 use Symfony\Component\HttpKernel\KernelEvents;
 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
@@ -31,7 +32,7 @@ class ThemeTestSubscriber extends ContainerAware implements EventSubscriberInter
    */
   public function onRequest(GetResponseEvent $event) {
     $request = $event->getRequest();
-    $current_path = $request->attributes->get('_system_path');
+    $current_path = RequestInfo::get($request)->getSystemPath();
     if ($current_path == 'theme-test/request-listener') {
       // First, force the theme registry to be rebuilt on this page request.
       // This allows us to test a full initialization of the theme system in
@@ -56,7 +57,7 @@ public function onRequest(GetResponseEvent $event) {
    */
   public function onView(GetResponseEvent $event) {
     $request = $event->getRequest();
-    $current_path = $request->attributes->get('_system_path');
+    $current_path = RequestInfo::get($request)->getSystemPath();
     if (strpos($current_path, 'user/autocomplete') === 0) {
       if ($this->container->initialized('theme.registry')) {
         throw new \Exception('registry initialized');
diff --git a/core/modules/user/lib/Drupal/user/EventSubscriber/MaintenanceModeSubscriber.php b/core/modules/user/lib/Drupal/user/EventSubscriber/MaintenanceModeSubscriber.php
index 3c478f7..495af72 100644
--- a/core/modules/user/lib/Drupal/user/EventSubscriber/MaintenanceModeSubscriber.php
+++ b/core/modules/user/lib/Drupal/user/EventSubscriber/MaintenanceModeSubscriber.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\user\EventSubscriber;
 
+use Drupal\Core\RequestInfo;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
@@ -27,7 +28,7 @@ public function onKernelRequestMaintenance(GetResponseEvent $event) {
     $user = \Drupal::currentUser();
     $request = $event->getRequest();
     $site_status = $request->attributes->get('_maintenance');
-    $path = $request->attributes->get('_system_path');
+    $path = RequestInfo::get($request)->getSystemPath();
     if ($site_status == MENU_SITE_OFFLINE) {
       // If the site is offline, log out unprivileged users.
       if ($user->isAuthenticated() && !$user->hasPermission('access site in maintenance mode')) {
