Repository: encode/starlette

Issue:
Use "308 Permanent Redirect" for redirect slashes behavior.
Hi,
I stumbled upon a quirk in starlette that is not properly documented. It seems like all of my HTTP request to a route without trailing slash are being redirected to route with trailing slashes. Say I am hitting `http://hostname/mountpoint/api` it will be redirected (302) to `http://hostname/mountpoint/api/`. This messed up your api calls; if you call POST to `http://hostname/mountpoint/api` it will be redirected to GET `http://hostname/mountpoint/api/`.

I dig on the source and see this redirect_slashes flag and setting it to False fix this. I feel this behavior (the auto redirection) should be documented.

Comments:

Patch:
diff --git a/starlette/middleware/httpsredirect.py b/starlette/middleware/httpsredirect.py
index 13f3a70..7f646ed 100644
--- a/starlette/middleware/httpsredirect.py
+++ b/starlette/middleware/httpsredirect.py
@@ -13,7 +13,7 @@ class HTTPSRedirectMiddleware:
             redirect_scheme = {"http": "https", "ws": "wss"}[url.scheme]
             netloc = url.hostname if url.port in (80, 443) else url.netloc
             url = url.replace(scheme=redirect_scheme, netloc=netloc)
-            response = RedirectResponse(url, status_code=301)
+            response = RedirectResponse(url, status_code=308)
             await response(scope, receive, send)
         else:
             await self.app(scope, receive, send)
diff --git a/starlette/responses.py b/starlette/responses.py
index 13982db..a755d24 100644
--- a/starlette/responses.py
+++ b/starlette/responses.py
@@ -161,7 +161,7 @@ class UJSONResponse(JSONResponse):
 
 class RedirectResponse(Response):
     def __init__(
-        self, url: typing.Union[str, URL], status_code: int = 302, headers: dict = None
+        self, url: typing.Union[str, URL], status_code: int = 307, headers: dict = None
     ) -> None:
         super().__init__(content=b"", status_code=status_code, headers=headers)
         self.headers["location"] = quote_plus(str(url), safe=":/%#?&=@[]!$&'()*+,;")


Test patch:
diff --git a/tests/middleware/test_https_redirect.py b/tests/middleware/test_https_redirect.py
index 15f1e3f..6a81ed3 100644
--- a/tests/middleware/test_https_redirect.py
+++ b/tests/middleware/test_https_redirect.py
@@ -19,20 +19,20 @@ def test_https_redirect_middleware():
 
     client = TestClient(app)
     response = client.get("/", allow_redirects=False)
-    assert response.status_code == 301
+    assert response.status_code == 308
     assert response.headers["location"] == "https://testserver/"
 
     client = TestClient(app, base_url="http://testserver:80")
     response = client.get("/", allow_redirects=False)
-    assert response.status_code == 301
+    assert response.status_code == 308
     assert response.headers["location"] == "https://testserver/"
 
     client = TestClient(app, base_url="http://testserver:443")
     response = client.get("/", allow_redirects=False)
-    assert response.status_code == 301
+    assert response.status_code == 308
     assert response.headers["location"] == "https://testserver/"
 
     client = TestClient(app, base_url="http://testserver:123")
     response = client.get("/", allow_redirects=False)
-    assert response.status_code == 301
+    assert response.status_code == 308
     assert response.headers["location"] == "https://testserver:123/"