nsidnev / fastapi-realworld-example-app Goto Github PK
View Code? Open in Web Editor NEWBackend logic implementation for https://github.com/gothinkster/realworld with awesome FastAPI
License: MIT License
Backend logic implementation for https://github.com/gothinkster/realworld with awesome FastAPI
License: MIT License
Now:
DB_CONNECTION=postgres://postgres:postgres@localhost/postgres
Expected:
DB_CONNECTION=postgres://postgres:postgres@db/postgres
The hostname for connection is the same as a service name, so this information is considered permanent.
Hi there.
I start using fastAPI before a few weeks and I love it!
And I read a lot about poetry, and I get the idea, but I still not managed to deploy this app to Google app engine engine, because the requirements file is missing.
I try to digging into it, but I fill that I missed something, especially in gae, but also in other services and tools that require requirements.txt
Thanks for any help!
fastapi being fast and scalable, but it seems this example won't handle readworld benchmark. To repro, run this and benchmark with wrk -t1 -c100 -d10s --latency http://localhost:8000/api/articles
, and any api accessing db is stuck :(
Maybe we could increase the default MAX_CONNECTIONS_COUNT to a higher value.
May i know the reason why you used FakeAsyncPGPool for testing?
HI!
I found ways to fix the typing in several places where now is "type: ignore". Can I suggest my PR that solves this? How can I do this?
This is less an issue and more a gotcha that I ran into when load testing, but I thought it would be worth noting since it took me a good bit of time to figure out, and I'm curious what people's thoughts on this might be.
If you're acquiring pool connections in Depends
arguments, you can run into a connection leak that deadlocks your application if you exhaust the pool. This is a result of how dependencies are fulfilled in FastAPI, but following a pattern used in this example app can cause the behavior:
The get_repository
dependency (here) returns an async generator, which gets you a Repository
and handles the acquiring and release of the associated connection via the async with
deal. The problem arises if you have multiple dependencies that acquire connections from the pool and you exhaust the pool. Because the dependencies are executed in an AsyncExitStack
, connections are released into the pool in the reverse order that they acquired.
For instance, the update_current_user
route
async def update_current_user(
user_update: UserInUpdate = Body(..., embed=True, alias="user"),
current_user: User = Depends(get_current_user_authorizer()),
users_repo: UsersRepository = Depends(get_repository(UsersRepository)),
)
depends on get_repository(UsersRepository)
and get_current_user_authorizer
, which transitively depends on a get_repository(UsersRepository)
as well. When a request comes in, ideally you'll
UsersRepository
needed for get_current_user_authorizer
UsersRepository
needed for users_repo
But if you have a max_size of 1 on your connection pool, you'll
You'd probably never be so reckless as to have such a measly connection pool as that, but if you're under high load, what would have been brief pool exhaustion causing slight delays in acquiring connections quickly escalates into deadlock forever. Even if you add timeouts for acquiring connections and for query execution, you still suffer a pretty horrible performance hit this way, getting lots of timeout errors you wouldn't be getting otherwise, and holding connections open for a lot longer than you need to. It seems to me like the easiest way around this would be to have the Repository
classes be long lived and take a Pool
init arg rather than Connection
so that they can handle the connection lifecycles themselves, but I'm curious if there are better ways, since FastAPI
and a lot of this async
business are pretty new to me.
I should note that this repo has been a tremendous resource, and I'm very grateful for its existence.
This repository has shown me a very interesting way of organsing the db logic and I'm interested in the reasons behind your decisions. Thank you! (It's really amazing work and really helpful.)
currently locked uvicorn version is ancient.
I created a local database that can be approached with ident authentication.
Then in .env specified:
DB_CONNECTION=postgresql+psycopg2:///real_world_application
In an ipython shell I verified that I can use this string to the database.
Still $ USE_LOCAL_DB_FOR_TEST=True pytest
results in:
During handling of the above exception, another exception occurred:
../../../.cache/pypoetry/virtualenvs/fastapi-realworld-example-app-qr8Xy3u9-py3.8/lib/python3.8/site-packages/docker/api/client.py:214: in _retrieve_server_version
return self.version(api_version=False)["ApiVersion"]
../../../.cache/pypoetry/virtualenvs/fastapi-realworld-example-app-qr8Xy3u9-py3.8/lib/python3.8/site-packages/docker/api/daemon.py:181: in version
return self._result(self._get(url), json=True)
../../../.cache/pypoetry/virtualenvs/fastapi-realworld-example-app-qr8Xy3u9-py3.8/lib/python3.8/site-packages/docker/utils/decorators.py:46: in inner
return f(self, *args, **kwargs)
../../../.cache/pypoetry/virtualenvs/fastapi-realworld-example-app-qr8Xy3u9-py3.8/lib/python3.8/site-packages/docker/api/client.py:237: in _get
return self.get(url, **self._set_request_timeout(kwargs))
../../../.cache/pypoetry/virtualenvs/fastapi-realworld-example-app-qr8Xy3u9-py3.8/lib/python3.8/site-packages/requests/sessions.py:555: in get
return self.request('GET', url, **kwargs)
../../../.cache/pypoetry/virtualenvs/fastapi-realworld-example-app-qr8Xy3u9-py3.8/lib/python3.8/site-packages/requests/sessions.py:542: in request
resp = self.send(prep, **send_kwargs)
../../../.cache/pypoetry/virtualenvs/fastapi-realworld-example-app-qr8Xy3u9-py3.8/lib/python3.8/site-packages/requests/sessions.py:655: in send
r = adapter.send(request, **kwargs)
../../../.cache/pypoetry/virtualenvs/fastapi-realworld-example-app-qr8Xy3u9-py3.8/lib/python3.8/site-packages/requests/adapters.py:498: in send
raise ConnectionError(err, request=request)
E requests.exceptions.ConnectionError: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory'))
(Lots of the above...)
Dear nsidnev,
I'm a fan of your architecture in this application. Unfortunately, I cannot figure out the error from the registration side:
"asyncpg.exceptions.UndefinedTableError: relation "users" does not exist"
I attached an image on how it looks like. I hope we could figure this out.
Cheers and stay healthy.
How to add the authorised button next to the endpoint in swagger?
Best regards
The readme assumes that you're on Linux (can't use EXPORT
in Windows)
I'm attempting to create a new table entity, and writing a repository to query the database.
env.py
to support auto-generation with alembic, but wasn't sure where the "base metadata" lives, or how to specify it exactly. Do I need a file that imports all the models in app/models/domain
?queries.py
references queries.pyi
. The readme doesn't specify how to use aiosql, so I'm not sure what to do with it exactly. Is it required for doing queries?FastAPI recommends using BaseSettings for confiugration. It would be nice for this example to follow that recommendation. See https://fastapi.tiangolo.com/advanced/settings/
Hi,
I found this repo amazing and very useful.
There is a small issue i noticed in the status code when the app raise an exception; it's sending 200 status code.
I did solve it by adding the exc status code in this line:
Thank you for this project!
Testing with zap-api-scan.py I have discovered various 500 status codes in the API. For example:
curl -X GET "http://localhost:8000/api/articles?tag=%00&author=author&favorited=favorited&limit=20&offset=0" -H "accept: application/json"
The complete report look like this:
Generated on Thu, 25 Feb 2021 15:54:01
Risk Level | Number of Alerts |
---|---|
High | 0 |
Medium | 0 |
Low | 3 |
Informational | 1 |
Name | Risk Level | Number of Instances |
---|---|---|
A Server Error response code was returned by the server | Low | 3 |
Unexpected Content-Type was returned | Low | 3 |
X-Content-Type-Options Header Missing | Low | 3 |
A Client Error response code was returned by the server | Informational | 435 |
A response code of 500 was returned by the server.
This may indicate that the application is failing to handle unexpected input correctly.
Raised by the 'Alert on HTTP Response Code Error' script
URL: http://localhost:8000/api/articles?tag=tag&author=author&favorited=%00&limit=20&offset=0
Method: GET
Evidence: HTTP/1.1 500
URL: http://localhost:8000/api/articles?tag=tag&author=%00&favorited=favorited&limit=20&offset=0
Method: GET
Evidence: HTTP/1.1 500
URL: http://localhost:8000/api/articles?tag=%00&author=author&favorited=favorited&limit=20&offset=0
Method: GET
Evidence: HTTP/1.1 500
Instances: 3
A Content-Type of text/plain was returned by the server.
This is not one of the types expected to be returned by an API.
Raised by the 'Alert on Unexpected Content Types' script
URL: http://localhost:8000/api/articles?tag=tag&author=author&favorited=%00&limit=20&offset=0
Method: GET
Evidence: text/plain
URL: http://localhost:8000/api/articles?tag=tag&author=%00&favorited=favorited&limit=20&offset=0
Method: GET
Evidence: text/plain
URL: http://localhost:8000/api/articles?tag=%00&author=author&favorited=favorited&limit=20&offset=0
Method: GET
Evidence: text/plain
Instances: 3
The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.
URL: http://localhost:8000/api/articles?tag=tag&author=author&favorited=favorited&limit=20&offset=0
Method: GET
Parameter: X-Content-Type-Options
URL: http://localhost:8000/api/tags
Method: GET
Parameter: X-Content-Type-Options
URL: http://localhost:8000/openapi.json
Method: GET
Parameter: X-Content-Type-Options
Instances: 3
Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.
If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.
This issue still applies to error type pages (401, 403, 500, etc.) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.
At "High" threshold this scan rule will not alert on client or server error responses.
A response code of 404 was returned by the server.
This may indicate that the application is failing to handle unexpected input correctly.
Raised by the 'Alert on HTTP Response Code Error' script
URL: http://localhost:8000/api/articles/658428727677602872
Method: GET
Evidence: HTTP/1.1 404
Method: GET
Evidence: HTTP/1.1 422
Method: GET
Evidence: HTTP/1.1 422
URL: http://localhost:8000/api/articles/feed?limit=20&offset=0%27%29+UNION+ALL+select+NULL+--+
Method: GET
Evidence: HTTP/1.1 403
Method: GET
Evidence: HTTP/1.1 403
Method: GET
Evidence: HTTP/1.1 422
URL: http://localhost:8000/api/articles/feed?limit=www.google.com%3A80%2F&offset=0
Method: GET
Evidence: HTTP/1.1 403
URL: http://localhost:8000/api/articles/feed?limit=20&offset=0%3B
Method: GET
Evidence: HTTP/1.1 403
Method: GET
Evidence: HTTP/1.1 422
URL: http://localhost:8000/api/articles/feed?limit=%27&offset=0
Method: GET
Evidence: HTTP/1.1 403
Method: GET
Evidence: HTTP/1.1 403
Method: GET
Evidence: HTTP/1.1 422
URL: http://localhost:8000/api/articles/feed?limit=HtTp%3A%2F%2F776609502133833358.owasp.org&offset=0
Method: GET
Evidence: HTTP/1.1 403
URL: http://localhost:8000/api/articles/feed?limit=20%27%7Ctype+%25SYSTEMROOT%25%5Cwin.ini&offset=0
Method: GET
Evidence: HTTP/1.1 403
Method: GET
Evidence: HTTP/1.1 422
Method: GET
Evidence: HTTP/1.1 422
Method: GET
Evidence: HTTP/1.1 422
Method: GET
Evidence: HTTP/1.1 422
Method: GET
Evidence: HTTP/1.1 422
URL: http://localhost:8000/api/articles/feed?limit=20&offset=0%27%3Bsleep+15%3B%27
Method: GET
Evidence: HTTP/1.1 403
Instances: 435
After install environment with poetry and setup dot env file, i run command alembic upgrade head
and receive the follow error
Traceback (most recent call last):
File "pydantic/env_settings.py", line 225, in pydantic.env_settings.read_env_file
ModuleNotFoundError: No module named 'dotenv'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/thuvh/.cache/pypoetry/virtualenvs/fastapi-realworld-example-app-2RFB7GKt-py3.8/bin/alembic", line 8, in <module>
sys.exit(main())
File "/home/thuvh/.cache/pypoetry/virtualenvs/fastapi-realworld-example-app-2RFB7GKt-py3.8/lib/python3.8/site-packages/alembic/config.py", line 588, in main
CommandLine(prog=prog).main(argv=argv)
File "/home/thuvh/.cache/pypoetry/virtualenvs/fastapi-realworld-example-app-2RFB7GKt-py3.8/lib/python3.8/site-packages/alembic/config.py", line 582, in main
self.run_cmd(cfg, options)
File "/home/thuvh/.cache/pypoetry/virtualenvs/fastapi-realworld-example-app-2RFB7GKt-py3.8/lib/python3.8/site-packages/alembic/config.py", line 559, in run_cmd
fn(
File "/home/thuvh/.cache/pypoetry/virtualenvs/fastapi-realworld-example-app-2RFB7GKt-py3.8/lib/python3.8/site-packages/alembic/command.py", line 320, in upgrade
script.run_env()
File "/home/thuvh/.cache/pypoetry/virtualenvs/fastapi-realworld-example-app-2RFB7GKt-py3.8/lib/python3.8/site-packages/alembic/script/base.py", line 563, in run_env
util.load_python_file(self.dir, "env.py")
File "/home/thuvh/.cache/pypoetry/virtualenvs/fastapi-realworld-example-app-2RFB7GKt-py3.8/lib/python3.8/site-packages/alembic/util/pyfiles.py", line 92, in load_python_file
module = load_module_py(module_id, path)
File "/home/thuvh/.cache/pypoetry/virtualenvs/fastapi-realworld-example-app-2RFB7GKt-py3.8/lib/python3.8/site-packages/alembic/util/pyfiles.py", line 108, in load_module_py
spec.loader.exec_module(module) # type: ignore
File "<frozen importlib._bootstrap_external>", line 783, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "./app/db/migrations/env.py", line 12, in <module>
SETTINGS = get_app_settings()
File "/home/thuvh/workspaces/aopt/app/core/config.py", line 19, in get_app_settings
app_env = BaseAppSettings().app_env
File "pydantic/env_settings.py", line 37, in pydantic.env_settings.BaseSettings.__init__
File "pydantic/env_settings.py", line 63, in pydantic.env_settings.BaseSettings._build_values
File "pydantic/env_settings.py", line 154, in pydantic.env_settings.EnvSettingsSource.__call__
File "pydantic/env_settings.py", line 227, in pydantic.env_settings.read_env_file
ImportError: python-dotenv is not installed, run `pip install pydantic[dotenv]`
I'm total beginner with fastapi and i have a lot of problem.
The uvicorn server start ok and coonection with db is okey but at localhost(or 127.0.0.1) or at localhost:8000
i have :
{"errors":["Not Found"]}.
Instead with docker-compose i have
"file not found"
on docker-logs app
Any help it's appreciate. Thanks
Is alembic configured correctly? When I change the model, and run alembic revision
, it generates an empty migration. It does not seem to pick up the changes made in models files.
https://github.com/gothinkster/react-redux-realworld-example-app
seems they use a wrong api to connect?
INFO: ('127.0.0.1', 64608) - "OPTIONS /api/users HTTP/1.1" 400
INFO: ('127.0.0.1', 64712) - "OPTIONS /api/users/login HTTP/1.1" 400
I was reading your code, but I don't understand where this method receives Request argument:
Because:
Note: If you want to label this issue as question
For example in one API.
I am calling a lot of methods from repositories and updating a lot of tables. So if there will be exceptions how can I roll back changes?
by the way thanks for such a great project!!! 🥇
It will be great to have a detailed documentation that covers directory structure, app functionalities. This will really help new users to be able to grasp your work easily.
Hi,
Thank you for creating this project.
Can you please let me know how I can authenticate in the Swagger UI?
Here's what I am doing right now:
/api/users/login
which returns a TOKEN
.Token TOKEN
.But, when I try out any of the endpoints, it gives me unsupported authorization type
error.
Thank you
I‘m used to virtualenv, and use "pip install -r xxx", why can't provide it, hhh, just think it's easy to quickly start.
I think this need some guideline to how to run unit test under the test
dir for some beginners
It will be very helpful, so much thanks
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.