-
-
Notifications
You must be signed in to change notification settings - Fork 6.8k
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to do case-insensitive URLs? #826
Comments
The easiest way I can think of would be to update the path regexs for the routes. For example: import re
from starlette.routing import Route
from starlette.testclient import TestClient
from fastapi import FastAPI
app = FastAPI()
@app.get("/endpoint")
async def endpoint() -> str:
return "success"
for route in app.router.routes:
if isinstance(route, Route):
route.path_regex = re.compile(route.path_regex.pattern, re.IGNORECASE)
print(TestClient(app).get("/endpoint").json())
# success
print(TestClient(app).get("/ENDPOINT").json())
# success Let us know if that doesn't work for you. |
@dmontagu Thanks. But it only changes the path part. The query string is still case-sensitive. How can we achieved this for entire URL except scheme and domain part. |
Hmm, that might be more challenging. Currently I don't think FastAPI exposes (or even has) any functionality related to transforming the query parameter keys prior to injection. You can always add I think it might be possible to achieve this by using a custom In general, I would recommend trying not to rely on case insensitivity of the query string if possible. I'd be interested if anyone else has a better solution here. |
Well, the problem is that it comes in an immutable dict called |
I think the most convenient solution to your problem is the middleware, which will be convert path and params to lower case. This example works with
from fastapi import FastAPI
from starlette.requests import Request
app = FastAPI()
DECODE_FORMAT = "latin-1"
@app.get("/test")
async def test(request: Request):
print(request.query_params)
return request.query_params
@app.middleware("http")
async def case_sens_middleware(request: Request, call_next):
raw_query_str = request.scope["query_string"].decode(DECODE_FORMAT).lower()
request.scope["query_string"] = raw_query_str.encode(DECODE_FORMAT)
path = request.scope["path"].lower()
request.scope["path"] = path
response = await call_next(request)
return response UPD: See also regex validation for Path and Query |
Thanks @SlyFoxy. I think that this will work for me. |
Thanks for the help here everyone! Clever trick @SlyFoxy 🦊 🚀 I think that should solve your use case, right @shivshankardayal ? If so, you can close the issue. |
For posterity, here's how to import a middleware from another module:
from starlette.requests import Request
class LowerCaseMiddleware:
def __init__(self) -> None:
self.DECODE_FORMAT = "latin-1"
async def __call__(self, request: Request, call_next):
raw = request.scope["query_string"].decode(self.DECODE_FORMAT).lower()
request.scope["query_string"] = raw.encode(self.DECODE_FORMAT)
path = request.scope["path"].lower()
request.scope["path"] = path
response = await call_next(request)
return response
...
from lower_case_middleware import LowerCaseMiddleware
app = FastAPI()
my_middleware = LowerCaseMiddleware()
app.middleware("http")(my_middleware) |
any idea on how we could only change the keys of the this would do the job but a bit hacky: query_string = ""
for k in request.query_params:
query_string += k.lower() + '=' + request.query_params[k] + "&"
query_string = query_string[:-1]
request.scope["query_string"] = query_string.encode(self.DECODE_FORMAT) |
real query_params case insensitive~
path case insensitive~
|
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
How can I do case-insensitive URLs in FastAPI?
The text was updated successfully, but these errors were encountered: