diff --git a/core/includes/common.inc b/core/includes/common.inc
index 79f16db..eb3bac1 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -210,11 +210,15 @@ function drupal_get_html_head($render = TRUE) {
  * previous request, that destination is returned. As such, a destination can
  * persist across multiple pages.
  *
- * @return
+ * @return array
  *   An associative array containing the key:
- *   - destination: The path provided via the destination query string or, if
- *     not available, the current path.
+ *   - destination: The value of the current request's 'destination' query
+ *     parameter, if present. This can be either a relative or absolute URL.
+ *     However, for security, redirection to external URLs is not performed.
+ *     If the query parameter isn't present, then the URL of the current
+ *     request is returned.
  *
+ * @see \Drupal\Core\EventSubscriber\RedirectResponseSubscriber::checkRedirectUrl()
  * @ingroup form_api
  */
 function drupal_get_destination() {
@@ -229,7 +233,7 @@ function drupal_get_destination() {
     $destination = array('destination' => $query->get('destination'));
   }
   else {
-    $path = \Drupal::routeMatch()->getRouteName() ? Url::fromRouteMatch(\Drupal::routeMatch())->getInternalPath() : '';
+    $path = \Drupal::routeMatch()->getRouteObject() ? Url::fromRouteMatch(\Drupal::routeMatch())->toString() : '';
     $query = UrlHelper::buildQuery(UrlHelper::filterQueryParameters($query->all()));
     if ($query != '') {
       $path .= '?' . $query;
diff --git a/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php
index bcab538..1a468f1 100644
--- a/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php
@@ -52,7 +52,8 @@ public function checkRedirectUrl(FilterResponseEvent $event) {
     if ($response instanceOf RedirectResponse) {
       $options = array();
 
-      $destination = $event->getRequest()->query->get('destination');
+      $request = $event->getRequest();
+      $destination = $request->query->get('destination');
       // A destination from \Drupal::request()->query always overrides the
       // current RedirectResponse. We do not allow absolute URLs to be passed
       // via \Drupal::request()->query, as this can be an attack vector, with
@@ -61,15 +62,28 @@ public function checkRedirectUrl(FilterResponseEvent $event) {
       //   base path) are allowed.
       if ($destination) {
         if (!UrlHelper::isExternal($destination)) {
-          $destination = UrlHelper::parse($destination);
-
-          $path = $destination['path'];
-          $options['query'] = $destination['query'];
-          $options['fragment'] = $destination['fragment'];
-          // The 'Location' HTTP header contain an absolute URL.
-          $options['absolute'] = TRUE;
-
-          $response->setTargetUrl($this->urlGenerator->generateFromPath($path, $options));
+          // The destination query parameter can be a relative URL in the sense
+          // of not including the scheme and host, but its path is expected to
+          // be absolute (start with a '/'). For such a case, prepend the
+          // scheme and host, because the 'Location' header must be absolute.
+          if (strpos($destination, '/') === 0) {
+            $destination = $request->getSchemeAndHttpHost() . $destination;
+          }
+          else {
+            // Legacy destination query parameters can be relative paths that
+            // have not yet been converted to URLs (outbound path processors
+            // and other URL handling still needs to be performed).
+            // @todo As generateFromPath() is deprecated, remove this in
+            //   https://www.drupal.org/node/2418219.
+            $destination = UrlHelper::parse($destination);
+            $path = $destination['path'];
+            $options['query'] = $destination['query'];
+            $options['fragment'] = $destination['fragment'];
+            // The 'Location' HTTP header must always be absolute.
+            $options['absolute'] = TRUE;
+            $destination = $this->urlGenerator->generateFromPath($path, $options);
+          }
+          $response->setTargetUrl($destination);
         }
         elseif (UrlHelper::externalIsLocal($destination, $this->requestContext->getCompleteBaseUrl())) {
           $response->setTargetUrl($destination);
diff --git a/core/modules/block_content/src/BlockContentListBuilder.php b/core/modules/block_content/src/BlockContentListBuilder.php
index 731f2da..793428d 100644
--- a/core/modules/block_content/src/BlockContentListBuilder.php
+++ b/core/modules/block_content/src/BlockContentListBuilder.php
@@ -39,7 +39,7 @@ public function buildRow(EntityInterface $entity) {
   public function getDefaultOperations(EntityInterface $entity) {
     $operations = parent::getDefaultOperations($entity);
     if (isset($operations['edit'])) {
-      $operations['edit']['query']['destination'] = 'admin/structure/block/block-content';
+      $operations['edit']['query']['destination'] = $entity->url('collection');
     }
     return $operations;
   }
diff --git a/core/modules/block_content/src/Plugin/Menu/LocalAction/BlockContentAddLocalAction.php b/core/modules/block_content/src/Plugin/Menu/LocalAction/BlockContentAddLocalAction.php
index 86921ec..c94f932 100644
--- a/core/modules/block_content/src/Plugin/Menu/LocalAction/BlockContentAddLocalAction.php
+++ b/core/modules/block_content/src/Plugin/Menu/LocalAction/BlockContentAddLocalAction.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Menu\LocalActionDefault;
 use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\Core\Url;
 
 /**
  * Modifies the 'Add custom block' local action.
@@ -26,7 +27,7 @@ public function getOptions(RouteMatchInterface $route_match) {
     }
     // Adds a destination on custom block listing.
     if ($route_match->getRouteName() == 'entity.block_content.collection') {
-      $options['query']['destination'] = 'admin/structure/block/block-content';
+      $options['query']['destination'] = Url::fromRouteMatch($route_match)->toString();
     }
     return $options;
   }
diff --git a/core/modules/comment/src/CommentManager.php b/core/modules/comment/src/CommentManager.php
index ef884e1..86a2238 100644
--- a/core/modules/comment/src/CommentManager.php
+++ b/core/modules/comment/src/CommentManager.php
@@ -19,6 +19,7 @@
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Core\StringTranslation\TranslationInterface;
+use Drupal\Core\Url;
 use Drupal\field\Entity\FieldStorageConfig;
 use Drupal\field\Entity\FieldConfig;
 
@@ -260,7 +261,7 @@ public function forbiddenMessage(EntityInterface $entity, $field_name) {
       // We cannot use drupal_get_destination() because these links
       // sometimes appear on /node and taxonomy listing pages.
       if ($entity->get($field_name)->getFieldDefinition()->getSetting('form_location') == CommentItemInterface::FORM_SEPARATE_PAGE) {
-        $destination = array('destination' => 'comment/reply/' . $entity->getEntityTypeId() . '/' . $entity->id() . '/' . $field_name . '#comment-form');
+        $destination = ['destination' => Url::fromRoute('comment.reply', ['entity_type' => $entity->getEntityTypeId(), 'entity' => $entity->id(), 'field_name' => $field_name], ['fragment' => 'comment-form'])->toString()];
       }
       else {
         $destination = array('destination' => $entity->url('canonical', array('fragment' => 'comment-form')));
diff --git a/core/modules/menu_ui/src/MenuForm.php b/core/modules/menu_ui/src/MenuForm.php
index 987858e..fd38c02 100644
--- a/core/modules/menu_ui/src/MenuForm.php
+++ b/core/modules/menu_ui/src/MenuForm.php
@@ -275,9 +275,11 @@ protected function buildOverviewForm(array &$form, FormStateInterface $form_stat
       ),
     );
 
-    $destination = $this->getUrlGenerator()->getPathFromRoute('entity.menu.edit_form', array('menu' => $this->entity->id()));
-    $url = $destination = $this->url('entity.menu.add_link_form', array('menu' => $this->entity->id()), array('query' => array('destination' => $destination)));
-    $form['links']['#empty'] = $this->t('There are no menu links yet. <a href="@url">Add link</a>.', array('@url' => $url));
+    $form['links']['#empty'] = $this->t('There are no menu links yet. <a href="@url">Add link</a>.', [
+      '@url' => $this->url('entity.menu.add_link_form', ['menu' => $this->entity->id()], [
+        'query' => ['destination' => $this->entity->url('edit-form')],
+      ]),
+    ]);
     $links = $this->buildOverviewTreeForm($tree, $delta);
     foreach (Element::children($links) as $id) {
       if (isset($links[$id]['#item'])) {
diff --git a/core/modules/user/src/Tests/UserAdminTest.php b/core/modules/user/src/Tests/UserAdminTest.php
index 135585d..de4749e 100644
--- a/core/modules/user/src/Tests/UserAdminTest.php
+++ b/core/modules/user/src/Tests/UserAdminTest.php
@@ -52,7 +52,7 @@ function testUserAdmin() {
     $this->assertText($admin_user->getUsername(), 'Found Admin user on admin users page');
 
     // Test for existence of edit link in table.
-    $link = $user_a->link(t('Edit'), 'edit-form', array('query' => array('destination' => 'admin/people')));
+    $link = $user_a->link(t('Edit'), 'edit-form', array('query' => array('destination' => $user_a->url('collection'))));
     $this->assertRaw($link, 'Found user A edit link on admin users page');
 
     // Test exposed filter elements.
diff --git a/core/modules/views_ui/src/ViewEditForm.php b/core/modules/views_ui/src/ViewEditForm.php
index 363474d..37fc363 100644
--- a/core/modules/views_ui/src/ViewEditForm.php
+++ b/core/modules/views_ui/src/ViewEditForm.php
@@ -727,7 +727,7 @@ public function renderDisplayTop(ViewUI $view) {
         $element['extra_actions']['#links']['revert'] = array(
           'title' => $this->t('Revert view'),
           'href' => "admin/structure/views/view/{$view->id()}/revert",
-          'query' => array('destination' => "admin/structure/views/view/{$view->id()}"),
+          'query' => array('destination' => $view->url('edit-form')),
         );
       }
       else {
