diff --git a/src/applications/auth/provider/PhabricatorAuthProvider.php b/src/applications/auth/provider/PhabricatorAuthProvider.php
--- a/src/applications/auth/provider/PhabricatorAuthProvider.php
+++ b/src/applications/auth/provider/PhabricatorAuthProvider.php
@@ -438,12 +438,13 @@
 
     $uri = $attributes['uri'];
     $uri = new PhutilURI($uri);
-    $params = $uri->getQueryParams();
+    $params = $uri->getQueryParamsAsPairList();
     $uri->setQueryParams(array());
 
     $content = array($button);
 
-    foreach ($params as $key => $value) {
+    foreach ($params as $pair) {
+      list($key, $value) = $pair;
       $content[] = phutil_tag(
         'input',
         array(
diff --git a/src/applications/differential/controller/DifferentialRevisionViewController.php b/src/applications/differential/controller/DifferentialRevisionViewController.php
--- a/src/applications/differential/controller/DifferentialRevisionViewController.php
+++ b/src/applications/differential/controller/DifferentialRevisionViewController.php
@@ -1098,7 +1098,8 @@
     //   D123.vs123.id123.whitespaceignore-all.diff
     // lame but nice to include these options
     $file_name = ltrim($request_uri->getPath(), '/').'.';
-    foreach ($request_uri->getQueryParams() as $key => $value) {
+    foreach ($request_uri->getQueryParamsAsPairList() as $pair) {
+      list($key, $value) = $pair;
       if ($key == 'download') {
         continue;
       }
diff --git a/src/applications/differential/view/DifferentialChangesetListView.php b/src/applications/differential/view/DifferentialChangesetListView.php
--- a/src/applications/differential/view/DifferentialChangesetListView.php
+++ b/src/applications/differential/view/DifferentialChangesetListView.php
@@ -358,7 +358,7 @@
 
     if ($this->standaloneURI) {
       $uri = new PhutilURI($this->standaloneURI);
-      $uri->setQueryParams($uri->getQueryParams() + $qparams);
+      $uri = $this->appendDefaultQueryParams($uri, $qparams);
       $meta['standaloneURI'] = (string)$uri;
     }
 
@@ -381,7 +381,7 @@
     if ($this->leftRawFileURI) {
       if ($change != DifferentialChangeType::TYPE_ADD) {
         $uri = new PhutilURI($this->leftRawFileURI);
-        $uri->setQueryParams($uri->getQueryParams() + $qparams);
+        $uri = $this->appendDefaultQueryParams($uri, $qparams);
         $meta['leftURI'] = (string)$uri;
       }
     }
@@ -390,7 +390,7 @@
       if ($change != DifferentialChangeType::TYPE_DELETE &&
           $change != DifferentialChangeType::TYPE_MULTICOPY) {
         $uri = new PhutilURI($this->rightRawFileURI);
-        $uri->setQueryParams($uri->getQueryParams() + $qparams);
+        $uri = $this->appendDefaultQueryParams($uri, $qparams);
         $meta['rightURI'] = (string)$uri;
       }
     }
@@ -421,4 +421,23 @@
 
   }
 
+  private function appendDefaultQueryParams(PhutilURI $uri, array $params) {
+    // Add these default query parameters to the query string if they do not
+    // already exist.
+
+    $have = array();
+    foreach ($uri->getQueryParamsAsPairList() as $pair) {
+      list($key, $value) = $pair;
+      $have[$key] = true;
+    }
+
+    foreach ($params as $key => $value) {
+      if (!isset($have[$key])) {
+        $uri->appendQueryParam($key, $value);
+      }
+    }
+
+    return $uri;
+  }
+
 }
diff --git a/src/applications/diffusion/controller/DiffusionBrowseController.php b/src/applications/diffusion/controller/DiffusionBrowseController.php
--- a/src/applications/diffusion/controller/DiffusionBrowseController.php
+++ b/src/applications/diffusion/controller/DiffusionBrowseController.php
@@ -709,8 +709,6 @@
         'path'      => $path,
       ));
 
-    $before_uri->setQueryParams($request->getRequestURI()->getQueryParams());
-    $before_uri = $before_uri->alter('before', null);
     $before_uri = $before_uri->alter('renamed', $renamed);
     $before_uri = $before_uri->alter('follow', $follow);
 
diff --git a/src/applications/oauthserver/PhabricatorOAuthServer.php b/src/applications/oauthserver/PhabricatorOAuthServer.php
--- a/src/applications/oauthserver/PhabricatorOAuthServer.php
+++ b/src/applications/oauthserver/PhabricatorOAuthServer.php
@@ -256,8 +256,8 @@
 
     // Any query parameters present in the first URI must be exactly present
     // in the second URI.
-    $need_params = $primary_uri->getQueryParams();
-    $have_params = $secondary_uri->getQueryParams();
+    $need_params = $primary_uri->getQueryParamsAsMap();
+    $have_params = $secondary_uri->getQueryParamsAsMap();
 
     foreach ($need_params as $key => $value) {
       if (!array_key_exists($key, $have_params)) {
diff --git a/src/infrastructure/markup/rule/PhabricatorYoutubeRemarkupRule.php b/src/infrastructure/markup/rule/PhabricatorYoutubeRemarkupRule.php
--- a/src/infrastructure/markup/rule/PhabricatorYoutubeRemarkupRule.php
+++ b/src/infrastructure/markup/rule/PhabricatorYoutubeRemarkupRule.php
@@ -18,12 +18,22 @@
       return $text;
     }
 
-    $params = $uri->getQueryParams();
-    $v_param = idx($params, 'v');
-    if (!strlen($v_param)) {
+    $v_params = array();
+
+    $params = $uri->getQueryParamsAsPairList();
+    foreach ($params as $pair) {
+      list($k, $v) = $pair;
+      if ($k === 'v') {
+        $v_params[] = $v;
+      }
+    }
+
+    if (count($v_params) !== 1) {
       return $text;
     }
 
+    $v_param = head($v_params);
+
     $text_mode = $this->getEngine()->isTextMode();
     $mail_mode = $this->getEngine()->isHTMLMailMode();