Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ MODE=local
MONGO_URI=mongodb://<username>:<password>@127.0.0.1:27017/?authSource=admin&retryWrites=true&w=majority
DOMAIN=https://localhost:8001
PORT=8001
API_VERSION=""
APP_NAMe="LOCAL"
API_VERSION="/api/v1"
APP_NAME="LOCAL"
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,6 @@ poetry.lock
*.tmp
*.temp
*.bak


assets/images/qr/*
34 changes: 26 additions & 8 deletions app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@
from contextlib import asynccontextmanager
from pathlib import Path
import logging
import traceback
import asyncio

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

# from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles
from starlette.middleware.sessions import SessionMiddleware

# from fastapi.exceptions import RequestValidationError
# from starlette.exceptions import HTTPException as StarletteHTTPException
from fastapi.templating import Jinja2Templates

from app.routes import ui_router
from app.utils import db
from app.utils.cache import cleanup_expired
Expand Down Expand Up @@ -90,22 +94,36 @@ async def lifespan(app: FastAPI):

app = FastAPI(title="TinyURL", lifespan=lifespan)
app.add_middleware(SessionMiddleware, secret_key=SESSION_SECRET)
templates = Jinja2Templates(directory="app/templates")

BASE_DIR = Path(__file__).resolve().parent
STATIC_DIR = BASE_DIR / "static"

app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")

# QR codes are now served from /qr, which maps to assets/images/qr in the project root
PROJECT_ROOT = BASE_DIR.parent
QR_DIR = PROJECT_ROOT / "assets" / "images" / "qr"
app.mount("/qr", StaticFiles(directory=QR_DIR), name="qr")

# -----------------------------
# Global error handler
# -----------------------------
@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
traceback.print_exc()
return JSONResponse(
status_code=500,
content={"success": False, "error": "INTERNAL_SERVER_ERROR"},
# app.exception_handler(Exception)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reason to comment these code?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I commented these becoz it overridding the response of 404 error of ui routes and cache route ...but now i fixed and updated both

# sync def global_exception_handler(request: Request, exc: Exception):
# traceback.print_exc()
# return JSONResponse(
# status_code=500,
# content={"success": False, "error": "INTERNAL_SERVER_ERROR"},
# )


@app.exception_handler(404)
async def custom_404_handler(request: Request, exc):
return templates.TemplateResponse(
"404.html",
{"request": request},
status_code=404,
)


Expand Down
10 changes: 7 additions & 3 deletions app/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from fastapi.templating import Jinja2Templates
from pydantic import BaseModel, Field


from app import __version__
from app.utils import db
from app.utils.cache import (
Expand Down Expand Up @@ -67,10 +68,11 @@ async def index(request: Request):
if qr_enabled and new_short_url and short_code:
qr_data = new_short_url
qr_filename = f"{short_code}.png"
qr_dir = BASE_DIR / "static" / "qr"
PROJECT_ROOT = BASE_DIR.parent # go from app/ → project root
qr_dir = PROJECT_ROOT / "assets" / "images" / "qr"
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

create QR_DIR constant and use

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

qr_dir.mkdir(parents=True, exist_ok=True)
generate_qr_with_logo(qr_data, str(qr_dir / qr_filename))
qr_image = f"/static/qr/{qr_filename}"
qr_image = f"/qr/{qr_filename}"

recent_urls = db.get_recent_urls(MAX_RECENT_URLS) or get_recent_from_cache(
MAX_RECENT_URLS
Expand Down Expand Up @@ -138,6 +140,7 @@ async def create_short_url(


@ui_router.get("/recent", response_class=HTMLResponse)
@ui_router.get("/history", response_class=HTMLResponse)
async def recent_urls(request: Request):
recent_urls_list = db.get_recent_urls(MAX_RECENT_URLS) or get_recent_from_cache(
MAX_RECENT_URLS
Expand Down Expand Up @@ -222,7 +225,8 @@ def redirect_short_ui(short_code: str, background_tasks: BackgroundTasks):
set_cache_pair(short_code, original_url)
return RedirectResponse(original_url)

return PlainTextResponse("Invalid short URL", status_code=404)
# return PlainTextResponse("Invalid short URL", status_code=404)
raise HTTPException(status_code=404, detail="Page not found")


@ui_router.delete("/recent/{short_code}")
Expand Down
Loading