Try every endpoint. The right panel shows which server function ran and what SQL/JWT happened behind the scenes.
Swagger docs: docs ยท Source repo: blog-api/app/
Every request lands on FastAPI in app/main.py, which routes it to a function based on the URL prefix:
app/routes/auth.pyapp/routes/users.pyapp/routes/posts.pyapp/routes/comments.py
1. Pydantic validates JSON โ UserCreate (schemas/user.py)
2. SQLAlchemy checks if username exists in `users` table
3. On register: password hashed with bcrypt (core/security.hash_password)
4. On login: verify_password(plain, hash) โ bcrypt compare
5. jwt_handler.create_access_token({"sub": username}) signs a JWT
using SECRET_KEY + HS256 (config.py). Expires in 30 min.
6. Returns { access_token, token_type: "bearer" }
1. FastAPI dependency get_current_user() runs before the route.
2. It reads "Authorization: Bearer <token>" header.
3. decode_jwt() verifies signature + expiry.
4. Looks up User row by `sub` claim.
5. Injects the User object into the route function as
`current_user: User = Depends(get_current_user)`.
6. Route can now enforce ownership:
if post.author_id != current_user.id: raise 403
routes/posts.py โ create_post() โโ get_current_user() โ validates JWT โโ Post(**data, author_id=current_user.id) โโ db.add() + db.commit() โ SQLAlchemy INSERT โโ returns Post โ serialized by PostOut schema (from_attributes=True)
routes/comments.py โ create_comment() โโ get_current_user() โโ Comment(post_id, content, author_id=current_user.id) โโ INSERT into `comments` (FK โ posts.id, users.id) โโ Response serialized by CommentOut
SQLite file โ blog.db (see config.DATABASE_URL) Tables auto-created on startup by: Base.metadata.create_all(bind=engine) in app/main.py Delete blog.db to reset everything.