from fastapi import APIRouter, HTTPException from fastapi.responses import RedirectResponse from sqlalchemy.exc import IntegrityError from app.db import database from app.models import Url from app.schemas import UrlPayload from app.services import encoder router = APIRouter() @router.get("/{shortcode}") async def redirect_to_original_url(shortcode: str): if not encoder.is_valid(shortcode): raise HTTPException(status_code=400, detail="Shortcode is not valid") query = Url.__table__.select().where(Url.shortcode == shortcode) url_result = await database.fetch_one(query) if url_result: return RedirectResponse(url=url_result.url, status_code=302) else: raise HTTPException(status_code=404, detail="Shortcode not found") @router.post("/shorten") async def create_url_shortcode(url_payload: UrlPayload): original_url = str(url_payload.url) query = "SELECT nextval('urls_id_seq')" next_id = await database.fetch_val(query) shortcode = encoder.encode(next_id) try: query = Url.__table__.insert().values({ "id": next_id, "url": original_url, "shortcode": shortcode }) await database.execute(query) return {"shortcode": shortcode, "original_url": original_url} except IntegrityError as e: if 'shortcode' in str(e): raise HTTPException(status_code=409, detail="Shortcode already in use") else: raise HTTPException(status_code=500, detail="Internal Server Error")