To retrieve query parameters from a request object, one could use request.query_params, which returns a starlette.datastructures.QueryParams object that is actually an ImmutableMultiDict with the query parameters. Another way is to use request.url.query, which returns the raw query string, as shown in this answer. Both approaches should also return keys with blank values in the query string.
Example
@app.get("/")
def main(request: Request):
return request.query_params
Test URL
http://localhost:8000/?x=foo&y=bar&z=
Result
{"x":"foo","y":"bar","z":""}
One could retrieve values for specific keys the same way as in a standard dict:
x = request.query_params["x"]
As noted earlier, request.query_params would return an immutable multidict—one could confirm that by using print(type(request.query_params))—and thus, if one would like to convert the result into a standard dictionary, they could do that using the dict() function:
params = dict(request.query_params)
Note
In a scenario where you expect a list of values for a specific key, and may appear multiple times in the URL, using request.query_params or dict(request.query_params) to get a dictionary of every key-value pair in the query string wouldn't work as expected. For instance, /?foo=2&foo=10&bar=7 would return {"foo":"10","bar":"7"} instead of {"foo":["2","10"],"bar":"7"}. In that case, you may consider following an approach similar to this answer, using urllib.parse.parse_qs. In order to have keys with blank values included as well, you should set the keep_blank_values flag to True, as described in the documentation:
The optional argument keep_blank_values is a flag indicating whether
blank values in percent-encoded queries should be treated as blank
strings. A true value indicates that blanks should be retained as
blank strings. The default false value indicates that blank values
are to be ignored and treated as if they were not included.
Example
from fastapi import FastAPI, Request
from urllib.parse import parse_qs
app = FastAPI()
@app.get("/")
def main(request: Request):
q_params = parse_qs(request.url.query, keep_blank_values=True)
d = dict((k, v if len(v)>1 else v[0])
for k, v in q_params.items())
return d
Test URL
http://localhost:8000/?foo=2&foo=10&bar=7&z=
Result
{"foo":["2","10"],"bar":"7","z":""}
On a side note, if the query parameters are known beforehand (not arbitrary) but not required, one could always declare them as Optional parameters in an endpoint (see Query Parameters documentation). Related answers on how to define query parameters in a FastAPI endpoint can be found here and here, as well as here and here.