FastAPI middleware doesn't let the request go through route handler

330 Views Asked by At

I wrote a middleware in FastAPI which sends a token to the auth service to get the decoded one via gRPC. Now inside the middleware everything works nice, the request is going to the other service and the decoded token is coming back. The problem starts when it finishes its job and it doesn't pass the request to the route. Hence the request doesn't go to the controller and sending a 422.

This is my middleware:

class TokenDecoder(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):

        print("-" * 60)
        print("middleware girdi")
        print("-" * 60)
        start = time.time()

    async with aio.insecure_channel("127.0.0.1:50051") as channel:
        stub = token_pb2_grpc.TokenServiceStub(channel)

        authorization_header = request.headers.get("Authorization")
        if not authorization_header or not authorization_header.startswith("Bearer "):
            raise HTTPException(
                status_code=401, detail="Authorization token missing")

        token = authorization_header.split(" ")[1]
        grpc_request = token_pb2.UndecodedToken(token=token)

        try:
            response = await stub.GetToken(grpc_request)
            decoded_data = {
                "isValid": response.isValid,
                "userId": response.userId,
                "business": response.business,
                "company": response.company,
            }
            end = time.time()
            total_time = end - start
            print('response insde', response)
            print('request', request)
            print("\nTime Taken to Auth Service\t" + str(total_time))
            print("-" * 60)
            # Add decoded_data to the Response object
            request.state.decoded = decoded_data
            print('reste',request.state.decoded)
            result = await call_next(request)
            print('result', result)
            return result
        except grpc.aio.AioRpcError as e:
            print("Error during token validation:", e)
            # Catch the `HTTPException` and return the response from the route
            return await call_next(request)

This is one of the routes Im trying to apply middleware:

@dataprovider.get('/item-list/', tags=["data-provider"])
async def get_itemList(
    request: Request = Depends(TokenDecoder),
    type: Optional[str] = Header(None),
    config: Settings = Depends(get_setting)):
print('test', request)
# print('response', request.state)
return await itemList(company='hktm', type=type, config=config)

I dont see the result of the 'test'.

And this is the main.py where I add middleware:

app.add_middleware(TokenDecoder)
app.add_middleware(Middleware)
app.add_middleware(Logging)
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"]
)

Problem: Why can't the route handle the middleware? Why doesn't the request come through middleware?

1

There are 1 best solutions below

0
On

I changed the structure of the middleware to a helper function. To be specific I put the logic into a function.

async def token_decoder(request: Request):

    print("-" * 60)
    print("middleware")
    print("-" * 60)
    start = time.time()
    async with aio.insecure_channel("127.0.0.1:50051") as channel:
        stub = token_pb2_grpc.TokenServiceStub(channel)

        authorization_header = request.headers.get("Authorization")
        if not authorization_header or not authorization_header.startswith("Bearer "):
            raise HTTPException(
                status_code=401, detail="Authorization token missing")

        token = authorization_header.split(" ")[1]
        grpc_request = token_pb2.UndecodedToken(token=token)

        try:
           
            response = await stub.GetToken(grpc_request)
            decoded_data = {
                'isValid': response.isValid,
                "userId": response.userId,
                "business": response.business,
                "company": response.company,
            }
            # response = await call_next(request)

            end = time.time()
            total_time = end - start
            print("\nTime Taken to Auth Service\t" + str(total_time))
            print("-" * 60)
            return decoded_data
        except grpc.aio.AioRpcError as e:
            print("Error during token validation:", e)
            return None

And then called it in the route handler like this.

@dataprovider.put("/updateitem/", tags=["data-provider"])
async def put_update_rows(
    item_updates: List[ItemUpdate],
    token: dict = Depends(token_decoder),
    type: Annotated[Union[str, None], Header()] = None,
    config: Settings = Depends(get_setting)):
return await update_rows(item_updates=item_updates, 
company=token['company'], type=type, config=config)

Its working as I wanted now but would it be considered as a middleware?