Replies: 18 comments 2 replies
-
|
Where do you use the |
Beta Was this translation helpful? Give feedback.
-
|
@Dustyposa I've expanded the "ping" endpoint above to call httpbin.org/headers. Adding a hardwired token there works (without manipulating the middleware request), but trying to access the flask header gives a 500. The client code is simple: import requests
import myserver # the code above
token = "foo"
myserver.start_server(port=8899, token=token) # testing middleware
requests.get("http://localhost:8899/ping", headers={"token": token}) # testing explicitly |
Beta Was this translation helpful? Give feedback.
-
|
@deeplook Got it. import fastapi
import requests
import uvicorn
from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
from starlette.requests import Request
from starlette.responses import Response
from starlette.types import Scope, Receive, Send
app = fastapi.FastAPI()
token = "token"
@app.get("/ping")
async def ping(request: Request) -> fastapi.Response:
"""
GET httpbin.org/headers with added token in header.
Return text body with token copied from result.
"""
j = requests.get(
"https://httpbin.org/headers",
headers={
# "token": "some_token", # works
"token": request.headers.get('token') # -> 500
}
).json()
return fastapi.Response(
content="pong",
media_type="text/plain",
headers={
"access-control-allow-origin": "*",
"x-token": j["headers"]["Token"]
}
)
class CustomHttpMiddleware(BaseHTTPMiddleware):
async def __call__(self, scope: Scope, receive: Receive, send: Send):
if scope["type"] != "http":
await self.app(scope, receive, send)
return
self._add_custom_headers(scope=scope)
request = Request(scope, receive=receive)
response = await self.dispatch_func(request, self.call_next)
await response(scope, receive, send)
async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) -> Response:
return await call_next(request)
@classmethod
def _add_custom_headers(cls, scope: Scope):
scope["headers"].append((b"token", b"my_token"))
if __name__ == '__main__':
app.add_middleware(CustomHttpMiddleware)
uvicorn.run(app)But I think this is not a good way to do. You changed the |
Beta Was this translation helpful? Give feedback.
-
|
I agree it looks like a wrong thing to do. I would also expect/hope for this to be easier. And my token is dynamic and I have to create it and pass it to the server at startup time. |
Beta Was this translation helpful? Give feedback.
-
How about to the server at startup to |
Beta Was this translation helpful? Give feedback.
-
|
Redis is not really a better option, as this is intended to be a more or less short-lived server started from a Jupyter notebook. It has to be hidden from the user and not bother him with starting something from the command-line, or knowing a "standard port" which is why I'm running it in a different process with a free port found at runtime. All this was "minimized" away from the above description. |
Beta Was this translation helpful? Give feedback.
-
|
Essentially, the goal is to have a proxy for an HTTP GET, but with a token added to the headers. It sounds like there should be some existing FastAPI proxy middleware for this already. |
Beta Was this translation helpful? Give feedback.
-
|
I see, but the key is |
Beta Was this translation helpful? Give feedback.
-
Yes, there has a list |
Beta Was this translation helpful? Give feedback.
-
|
The BaseHTTPMiddleware section on https://www.starlette.io/middleware passes a |
Beta Was this translation helpful? Give feedback.
-
|
But it also adds to the response header, not the request header, so it would not be an improvement. |
Beta Was this translation helpful? Give feedback.
-
|
Yes, need to rewrite the |
Beta Was this translation helpful? Give feedback.
-
|
@deeplook Hi, do you have to rewrite the request header? Or can you think to another type of solution? I was thinking you can use the starlette request 'state' property to store your token and passed it through the application stack. That's the starlette doc: https://www.starlette.io/requests/#other-state |
Beta Was this translation helpful? Give feedback.
-
|
This seems to be what I'm looking for, specifically to add the JWT token as the Authorization header to make it work with the jinja html templates. |
Beta Was this translation helpful? Give feedback.
-
|
@deeplook did you ever get this figured out? Seems much harder than it should be to add a header via middleware. |
Beta Was this translation helpful? Give feedback.
-
|
Nope. |
Beta Was this translation helpful? Give feedback.
-
|
@deeplook I found this which allowed me to grab the token from the cookies by adding a middleware. Seems to have worked but I'm still testing it. |
Beta Was this translation helpful? Give feedback.
-
|
one possible solution is: async def some_middleware(request: Request, call_next):
mutable_headers = request.headers.mutablecopy()
# Do something with it
mutable_headers["lady"] = "gaga"
request._headers = mutable_headers
return await call_next(request) |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I'm still very new to FastAPI, but I start with a tricky issue. I start a FastAPI server programmatically in a separate process and want to add a token value in the request header in some middleware. I have found various snippets that show how to add a field to the response header of a middlewhere, but I need it in the request header because in the route there will be another request made using
requests.get()using that token in the header. I see that the request headers are immutable so I've tried to create a replacement request object, but I keep getting 500 when running this. Any help would be greatly appreciated.Example
Environment
Beta Was this translation helpful? Give feedback.
All reactions