1

So relatively new to FastAPI, and I have a small project I am trying to perform. Been through the examples at https://fastapi.tiangolo.com/. and did get some of what I am posting but not all.

My Post is a JSON body, with a single header, but uses basic auth. If I use the FastAPI Basic Auth example, I can get the user/pass easily. If I use Request, It gets the Header and Body easily, but accessing the user data coughs

    ), "AuthenticationMiddleware must be installed to access request.user"
AssertionError: AuthenticationMiddleware must be installed to access request.user

So I can see it's there, but can't read it.

from typing import Union
from fastapi import Depends, FastAPI, Header, Request, Body
from fastapi.security import HTTPBasic, HTTPBasicCredentials
security = HTTPBasic()
app = FastAPI()
@app.post("/posttest")
async def root(request: Request):
        my_header = request.headers.get('client_id')
        return{"Client-Id": my_header, "Body": await request.json(), "User": request.user}

I am not sure how one collects all 3 bits so I can use my own python request code to do a proper O-Auth2 call with this data to return the answer the original post needed (The App cannot do O-Auth, so I am making a wedge)

This block instead will get the username and password, but I am unable to pull my Header or Body. I am sure I am missing something silly, but this is my first crack at this.

async def root(credentials: HTTPBasicCredentials = Depends(security)):
        return {"username": credentials.username, "password": credentials.password}
  • You're not using the FastAPI dependency from the example, which is what would provide the user data if you're basing your code on FastAPI documentation (see the `Depends` definition here: https://fastapi.tiangolo.com/advanced/security/http-basic-auth/) - just creating a `security` variable does nothing in itself). If you want to use `request.user`, that functionality is provided by Starlette: https://www.starlette.io/authentication/ – MatsLindh Aug 10 '22 at 19:17
  • I am not sure what you mean. I do see that this snippet doesn't use the security bit, but if I switch over to root(credentials: HTTPBasicCredentials = Depends(security)), the Auth part works, but not the Headers or Body. I do not care how I get the username and password, if that helps, I just saw that it was there when I did a dir(request) so I went poking. – Nick Ellson Aug 11 '22 at 03:03
  • I edited my post to show the block I use that does get the credentials, but does not seem to let me get at the Headers or Body. I have actually tried Starlette directly as well. I have an app that doe sget credentials/headers/and body, but it only access GET not POST.. equally confusing as I don't see where I specified either... – Nick Ellson Aug 11 '22 at 03:19
  • Here is what I did in Starlette that works only for the GET method, and I needed POST. https://stackoverflow.com/questions/73314925/this-starlette-code-works-but-only-with-get-and-i-need-post – Nick Ellson Aug 11 '22 at 03:28
  • 1
    Usually you don't use the raw request body directly in FastAPI, you use a pydantic model that represents the expected json body, and this gets automagically converted to a object of that model. To retrieve a header you can use `x_required_foo: str = Header(...)` to required an HTTP-header named `X-Required-Foo` for example: https://fastapi.tiangolo.com/tutorial/header-params/ - In most cases you define your controllers like this instead of accessing the `request` object directly, and FastAPI does the magic stuff for you. – MatsLindh Aug 11 '22 at 09:17
  • So I am looking for a method that uses the BaseModel construct AND Basic Auth, yes? The examples have not showed one yet. I'll keep looking. – Nick Ellson Aug 11 '22 at 22:16
  • OK, great! that go me my Header and Basic Auth.. now to get the body it appears that I need a data class that gets the whole json block? (where the ???? is async def read_items(credentials: HTTPBasicCredentials = Depends(security), client_id: Union[str, None] = Header(default=None, convert_underscores=False), ?????): return {"username": credentials.username, "password": credentials.password, "Client-ID": client_id} – Nick Ellson Aug 11 '22 at 22:43
  • I win!!! async def read_items(credentials: HTTPBasicCredentials = Depends(security), client_id: Union[str, None] = Header(default=None, convert_underscores=False), item: str = Body(imbed=True)): return {"username": credentials.username, "password": credentials.password, "Client-ID": client_id, "Body": item} That got everything, thanks for the ideas!!! – Nick Ellson Aug 11 '22 at 23:20

1 Answers1

0

Learned my solution by learning how to build on the attributes in my app's funtion. Thanks everyone!

def read_items(credentials: HTTPBasicCredentials = Depends(security), client_id: Union[str, None] = Header(default=None, convert_underscores=False), item: str = Body(embed=True)):
Chris
  • 18,724
  • 6
  • 46
  • 80