Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • 15:37
    falkben commented #2892
  • 14:22
    Kludex commented #2907
  • 14:09
    hesummerzh commented #2907
  • 13:51
    snow6oy commented #911
  • 13:10
    Suyoung789 edited #2908
  • 13:09
    github-actions[bot] commented #2908
  • 13:08
    codecov[bot] commented #2908
  • 13:08
    codecov[bot] commented #2908
  • 13:06
    codecov[bot] commented #2908
  • 13:06
    codecov[bot] commented #2908
  • 13:06
    Suyoung789 synchronize #2908
  • 10:03
    github-actions[bot] commented #2908
  • 10:01
    codecov[bot] commented #2908
  • 10:01
    codecov[bot] commented #2908
  • 10:00
    codecov[bot] commented #2908
  • 10:00
    codecov[bot] commented #2908
  • 10:00
    codecov[bot] commented #2908
  • 10:00
    codecov[bot] commented #2908
  • 10:00
    Suyoung789 synchronize #2908
  • 09:58
    codecov[bot] commented #2908
euri10
@euri10
Brand new table yes I haven't used it much indeed. In other projects I rarely have that deep relationships so really can't comment on whether or not sqlalchemy core would be a pain in the a**
On a particular project I'm making deep use of ordinality and unnest and managed a way to write the query in core,honestly I doubt it's feasible with orm, and the raw query is just more readable
gargleblaster
@gargleblaster

Hi, I'm very new to FastAPI. Thanks for your work! I am trying to handle a 302 to allow the user to complete an OAuth authorization. I have tried returning the response from the Python requests library, which is indeed a 302, directly to the browser, but I get an exception. It seems that FastAPI is trying to look inside of the response, rather than just passing it along. How can I resolve this?

DEBUG:main:login response: <Response [302]>
INFO:uvicorn:('67.191.210.63', 58131) - "GET /login HTTP/1.1" 500
ERROR:uvicorn:Exception in ASGI application
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/uvicorn/protocols/http/httptools_impl.py", line 368, in run_asgi
result = await app(self.scope, self.receive, self.send)
File "/usr/local/lib/python3.7/site-packages/engineio/async_drivers/asgi.py", line 53, in call
await self.other_asgi_app(scope, receive, send)
File "/usr/local/lib/python3.7/site-packages/starlette/applications.py", line 133, in call
await self.error_middleware(scope, receive, send)
File "/usr/local/lib/python3.7/site-packages/starlette/middleware/errors.py", line 122, in call
raise exc from None
File "/usr/local/lib/python3.7/site-packages/starlette/middleware/errors.py", line 100, in call
await self.app(scope, receive, _send)
File "/usr/local/lib/python3.7/site-packages/starlette/exceptions.py", line 73, in call
raise exc from None
File "/usr/local/lib/python3.7/site-packages/starlette/exceptions.py", line 62, in call
await self.app(scope, receive, sender)
File "/usr/local/lib/python3.7/site-packages/starlette/routing.py", line 585, in call
await route(scope, receive, send)
File "/usr/local/lib/python3.7/site-packages/starlette/routing.py", line 207, in call
await self.app(scope, receive, send)
File "/usr/local/lib/python3.7/site-packages/starlette/routing.py", line 40, in app
response = await func(request)
File "/usr/local/lib/python3.7/site-packages/fastapi/routing.py", line 122, in app
skip_defaults=response_model_skip_defaults,
File "/usr/local/lib/python3.7/site-packages/fastapi/routing.py", line 63, in serialize_response
return jsonable_encoder(response)
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 110, in jsonable_encoder
sqlalchemy_safe=sqlalchemy_safe,
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 66, in jsonable_encoder
sqlalchemy_safe=sqlalchemy_safe,
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 110, in jsonable_encoder
sqlalchemy_safe=sqlalchemy_safe,
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 66, in jsonable_encoder
sqlalchemy_safe=sqlalchemy_safe,
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 110, in jsonable_encoder
sqlalchemy_safe=sqlalchemy_safe,
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 66, in jsonable_encoder
sqlalchemy_safe=sqlalchemy_safe,
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 110, in jsonable_encoder
sqlalchemy_safe=sqlalchemy_safe,
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 66, in jsonable_encoder
sqlalchemy_safe=sqlalchemy_safe,
File "/usr/local/lib/python3.7/site-packages/fastapi/encoders.py", line 103, in jsonable_encoder
raise ValueError(errors)
ValueError: [KeyError(<class 'object'>), TypeError("'object' object is not iterable"), TypeError('vars() argument must have dict attribute')]

gargleblaster
@gargleblaster
Here is the working code:
def login(response: Response):
    resp = getAuthCode()
    response.status_code = 302
    response.headers['Location'] = resp.headers['Location']
    logger.debug(f'login response: {response}')
    return response
Sebastián Ramírez
@tiangolo
@gargleblaster I think you might nave an old version of FastAPI. It's better to create an issue in GitHub, that way I (or someone else) can check it.
gargleblaster
@gargleblaster
@tiangolo Thanks for your reply. I am running 0.31.0, which doesn't seem very old. Are you saying that my code above should have been unnecessary, and that the 302 response should have been passed through? (Understood about creating an issue in GitHub, but I assumed this was not a bug but operator error. :-)
gargleblaster
@gargleblaster
@tiangolo Sorry, I am actually using your docker image: tiangolo/uvicorn-gunicorn-fastapi:python3.7, so that turns out to be 0.30.1.
chbndrhnns
@chbndrhnns
Hey, I would like some inspiration on how I could implement role-based access with fastAPI. I know for Flask, there is flask-rbac, for example.
William Hayes
@wshayes
Are you getting your roles from the JWT token? a db user query? Did you want to do it as a decorator? You’ll need to add role access control logic to each endpoint you want to protect.
skaaptjop
@skaaptjop
auth-auth is always a fun topic.
I like the fact that certain frameworks remain lightweight. Allows us to choose the pattern that fits the use-case best. It is certainly quite straightforward to "port" any flask lib to a fastapi implementation because the basic principle of request/response/middleware/endpoint is the same foreverything
chbndrhnns
@chbndrhnns

Are you getting your roles from the JWT token? a db user query? Did you want to do it as a decorator? You’ll need to add role access control logic to each endpoint you want to protect.

A db query, probably. I was hoping for an existing solution in the starlette world, to be honest.

Francesco Bartoli
@francbartoli

Are you getting your roles from the JWT token? a db user query? Did you want to do it as a decorator? You’ll need to add role access control logic to each endpoint you want to protect.

Hi @wshayes getting roles/claims from a JWT token is a super interesting topic for me but I’m curious what is your suggestion

Neil Shapiro
@nrshapiro
So in my api I'm returning a pydantic model, and fastAPI is converting it to json. If I test or demonstrate a endpoint directly via the browser (rather than through docs), is there a way to get FastAPI to prettyprint (indent) the json?
Neil Shapiro
@nrshapiro
Also, and more importantly, how do I make the pydantic fields in a model return only what's not defaulted to "None" in the model? If I don't set a default to None, then the model produces an error because the field is "required". If I default them to None, they all show up in the response to the client--in the API I'm replacing, those fields should remain absent, reducing the data return and also showing up in the client as undefined (and the client actually tests for that).
James Vogel
@voglster
so i have me head wrapped around authentication and creating a jwt. I also added a graphql endpoint on my app to query some objects. What I would like to do is add authentication to the GraphQLApp. can you use the depends syntax current_user: User = Depends(get_current_active_user)) when using app.add_route for graphql?
James Vogel
@voglster
either that or how can i make the graphql endpoint require a jwt?
euri10
@euri10

So in my api I'm returning a pydantic model, and fastAPI is converting it to json. If I test or demonstrate a endpoint directly via the browser (rather than through docs), is there a way to get FastAPI to prettyprint (indent) the json?

it's already the case @nrshapiro the returned json is indented, see this screen for instance:

Imgur

as for the defaults you may try dict(skip_defaults=True)
William Hayes
@wshayes
@nrshapiro https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_skip_defaults-parameter may work - it works if you are creating the Pydantic model directly - if you are setting the defaults any way other than that (e.g. the defaults are set by code other than Pydantic model creation) it won’t clean them out. I have a recursive function that will clean out anything null’ish for responses.
@francbartoli It’s pretty straightforward to add claims/roles to JWT’s and then use them (after authentication) to determine what a user has access to - it cuts down on DB queries. The only problem with it is you cannot expire the token early (e.g. your user has a new role added to them and their token is still good for X minutes). Until their token expires or you have someway to force a token update - they won’t see the benefit of the new role. If you are using websockets, you could use that to trigger a token update.
William Hayes
@wshayes
You can add any fields you want to a JWT payload. I’ve seen tokens that have several dozen fields and are around 4kb in size - I think that’s a bit overdoing it :) It’s not a problem from the JWT spec/browsers/servers - just adds more IO to each request.
euri10
@euri10
my googling skills are failing short : is there a way on a running app, to get gunicorn config params ? I know I can run with gunicorn -c config but I've got a machine where I setup some params and I'm not positive they have been loaded
Omri Har-Shemesh
@omrihar
Hello everyone! We've been hit with a weird issue and I'm wondering if anyone has experienced this before: we deployed the fastapi fullstack app to AWS cloudfront using traefik and for some reason we don't manage to get query parameters to pass to our API endpoints. We get None instead if there is not default value set. What is weird is that the API docs work and also the api works when no query parameters are needed. Any suggestions as to where the culprit could lie?
William Hayes
@wshayes
You have your application assets on Cloudfront? but not Traefik or FastAPI right?
Omri Har-Shemesh
@omrihar
Just as I posted this we managed to solve it - we didn't define cloudfront to forward query parameters!
So once we did this and waited the long time it takes to update it works.
Thanks!
euri10
@euri10
:bug: :)
William Hayes
@wshayes
Cool - thanks for sharing!
Omri Har-Shemesh
@omrihar
It was a sneaky one thou because we mostly had defaults that work and we didn't notice that the parameters don't change - until there was a default that didn't work in a specific setting
Francesco Bartoli
@francbartoli

You can add any fields you want to a JWT payload. I’ve seen tokens that have several dozen fields and are around 4kb in size - I think that’s a bit overdoing it :) It’s not a problem from the JWT spec/browsers/servers - just adds more IO to each request.

Thanks @wshayes, my first thought is to find a viable solution to receive authorization claims/roles from an external authentication system and spend it over a microservices architecture based on FastAPI

William Hayes
@wshayes
AWS Cognito, Auth0 and others allow you to add roles/claims and other user metadata as user attributes to the token. Note that the new Auth0 javascript library makes it much more difficult to get a JWT (instead they share a simple access token unless you slap it hard upside the head). I’ve not used Cognito yet, but I’ve been eyeing it as Auth0 seems to make hard things harder rather than slightly easier.
Neil Shapiro
@nrshapiro

@euri10, that's only the case in Docs as I mentioned. But others may show it in Google Chrome or elsewhere, where it looks like this:

image.png

euri10
@euri10
skaaptjop
@skaaptjop
@francbartoli another lighter weight solution is Google's firebase. Extremely straightforward to handle auth.
Francesco Bartoli
@francbartoli
Yep @skaaptjop, I played a bit with Firebase Auth but did not manag claims/roles at that time
skaaptjop
@skaaptjop
claims in FB are very lightweight (max 1000b I believe) so they do kinda expect any role based or other scheme to be implemented around it (with firestore for example)
David Montague
@dmontagu
@nrshapiro You can modify how the serialization happens by changing the response_class argument on your endpoint
the default response class (starlette.responses.JSONResponse) looks like this:
class JSONResponse(Response):
    media_type = "application/json"

    def render(self, content: typing.Any) -> bytes:
        return json.dumps(
            content,
            ensure_ascii=False,
            allow_nan=False,
            indent=None,
            separators=(",", ":"),
        ).encode("utf-8")
if you subclass and modify the render method to set indent=4 and separators=(", ", ": ") in json.dumps I think it will render closer to the "pretty" way
something like this:
import json
import typing

from starlette.responses import Response

class PrettyJSONResponse(Response):
    media_type = "application/json"

    def render(self, content: typing.Any) -> bytes:
        return json.dumps(
            content,
            ensure_ascii=False,
            allow_nan=False,
            indent=4,
            separators=(", ", ": "),
        ).encode("utf-8")
then using it would look like
    @app.get("/", response_class=PrettyJSONResponse)
    async def get_some_json():
        ...
David Montague
@dmontagu
This might be useful for debugging. If you wanted it on all endpoints during development (and off in production), this could be done by dynamically setting the response_class to a variable depending on the environment. But I think you'd be better served just making use of dev tools that will parse and display the json more neatly for you (e.g., the swagger docs, chrome extensions, etc.), and just occasionally making temporary use of the PrettyJSONResponse in situations where it is temporarily useful to have it pretty-printed
@nrshapiro As @wshayes said, there is a built-in way to skip default values as long as you don't explicitly set them to the default value when instantianting the model (pydantic must have skipped setting the values). So if the default value is None, and you don't pass it to the constructor, it will be skipped during serialization. (It was designed this way, rather than just skipping nulls, because otherwise, if you want it to include None for some reason, (e.g., because you updated a non-null value to become null, and want to signal that in your response), you wouldn't be able to.)
William Hayes
@wshayes
@dmontagu Thanks for that example - I added it to my gists for future reference!
euri10
@euri10
added flower and celery to my base, flower is super nicely made
William Hayes
@wshayes
do you use rabbitmq or redis with celery?