Repository: readthedocs/readthedocs.org

Issue:
How to enable query parameters in redirects?
I don't really understand how any of this works under the covers, but since  #5081 has been merged this should be supported, right?

For example, I have set the default version of my project to `0.6.0`, so it correctly redirects https://nbsphinx.readthedocs.io/ to https://nbsphinx.readthedocs.io/en/0.6.0/.

However, when I use the search URL with a query parameter, the parameter is somehow lost in redirection:

## Expected Result

https://nbsphinx.readthedocs.io/search.html?q=readthedocs should get redirected to https://nbsphinx.readthedocs.io/en/0.6.0/search.html?q=readthedocs

## Actual Result

https://nbsphinx.readthedocs.io/search.html?q=readthedocs gets redirected to https://nbsphinx.readthedocs.io/en/0.6.0/search.html


Discussion:
This looks like a regression from our new proxy server
@mgeier What is the redirect that you have configured on your project for this case? 

Resolving patch:
diff --git a/readthedocs/proxito/views/mixins.py b/readthedocs/proxito/views/mixins.py
--- a/readthedocs/proxito/views/mixins.py
+++ b/readthedocs/proxito/views/mixins.py
@@ -205,6 +205,8 @@ def get_redirect_response(self, request, redirect_path, proxito_path, http_statu
         """
 
         schema, netloc, path, params, query, fragments = urlparse(proxito_path)
+        # `proxito_path` doesn't include query params.
+        query = urlparse(request.get_full_path()).query
         new_path = urlunparse((schema, netloc, redirect_path, params, query, fragments))
 
         # Re-use the domain and protocol used in the current request.
diff --git a/readthedocs/proxito/views/serve.py b/readthedocs/proxito/views/serve.py
--- a/readthedocs/proxito/views/serve.py
+++ b/readthedocs/proxito/views/serve.py
@@ -235,7 +235,13 @@ def get(self, request, proxito_path, template_name='404.html'):
                     new_path = parts.path.rstrip('/') + f'/{tryfile}'
                 else:
                     new_path = parts.path.rstrip('/') + '/'
-                new_parts = parts._replace(path=new_path)
+
+                # `proxito_path` doesn't include query params.`
+                query = urlparse(request.get_full_path()).query
+                new_parts = parts._replace(
+                    path=new_path,
+                    query=query,
+                )
                 redirect_url = new_parts.geturl()
 
                 # TODO: decide if we need to check for infinite redirect here


Test patch:
diff --git a/readthedocs/proxito/tests/handler_404_urls.py b/readthedocs/proxito/tests/handler_404_urls.py
--- a/readthedocs/proxito/tests/handler_404_urls.py
+++ b/readthedocs/proxito/tests/handler_404_urls.py
@@ -25,7 +25,7 @@ def inner_view(request, exception, *args, **kwargs):
         return view_func(
             request,
             *args,
-            proxito_path=request.get_full_path(),
+            proxito_path=request.path,
             **kwargs,
         )
     return inner_view
diff --git a/readthedocs/proxito/tests/test_full.py b/readthedocs/proxito/tests/test_full.py
--- a/readthedocs/proxito/tests/test_full.py
+++ b/readthedocs/proxito/tests/test_full.py
@@ -333,8 +333,7 @@ def test_directory_indexes_get_args(self):
         self.project.versions.update(active=True, built=True)
         # Confirm we've serving from storage for the `index-exists/index.html` file
         response = self.client.get(
-            reverse('proxito_404_handler', kwargs={
-                    'proxito_path': '/en/latest/index-exists?foo=bar'}),
+            reverse('proxito_404_handler', kwargs={'proxito_path': '/en/latest/index-exists'}) + '?foo=bar',
             HTTP_HOST='project.readthedocs.io',
         )
         self.assertEqual(