Skip to content

Instantly share code, notes, and snippets.

@mayankchoubey
Last active October 18, 2023 04:21
Show Gist options
  • Save mayankchoubey/cae0b968e496c4ea4a763968bf132a63 to your computer and use it in GitHub Desktop.
Save mayankchoubey/cae0b968e496c4ea4a763968bf132a63 to your computer and use it in GitHub Desktop.
Python - FastAPI URL shortener service in PostgreSQL
from service import shorten
from fastapi import FastAPI, Response, Request, HTTPException
from fastapi.responses import JSONResponse
async def handleRequest(reqBody: any):
if not reqBody.srcUrl:
raise HTTPException(status_code=400, detail="Parameter 'srcUrl' is missing")
srcUrl = reqBody.srcUrl
if len(srcUrl) > 250:
raise HTTPException(status_code=400, detail="Parameter 'srcUrl' must not be more than 250 characters")
if not srcUrl.startswith(('http://', 'https://')):
raise HTTPException(status_code=400, detail="Parameter 'srcUrl' must start with http:// or https://")
shortenedUrl = await shorten(srcUrl)
if len(shortenedUrl) == 0:
raise HTTPException(status_code=500, detail="Failed to shorten")
return JSONResponse({'srcUrl':srcUrl, 'shortenedUrl':shortenedUrl });
from sqlalchemy import Column, String, DateTime
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy.ext.asyncio import async_sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from datetime import datetime
import os
engine = create_async_engine(
f'postgresql+psycopg://{os.getenv("dbUser")}:{os.getenv("dbUserPass")}@localhost/{os.getenv("dbName")}',
pool_size=10,
future=True
)
AsyncSessionFactory = async_sessionmaker(bind=engine)
Base = declarative_base()
class ShortenedUrl(Base):
__tablename__ = 'shortenedurls'
id = Column(String, primary_key=True)
srcurl = Column(String)
created = Column(DateTime, default=datetime.now)
lastaccessed = Column(DateTime, default=datetime.now)
async def save(urlId: str, srcUrl: str):
shortenedUrl = ShortenedUrl(id=urlId, srcurl=srcUrl)
async with AsyncSessionFactory() as session:
session.add(shortenedUrl)
await session.commit()
return True
from fastapi import FastAPI, Response, Request, HTTPException
from fastapi.responses import JSONResponse
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel
from controller import handleRequest
app = FastAPI()
class ShortenRequest(BaseModel):
srcUrl: str
@app.post("/shorten")
async def requestHandler(reqBody: ShortenRequest):
return await handleRequest(reqBody)
from db import save
from nanoid import generate
baseUrl = "http://test.short/"
async def shorten(srcUrl: str):
if not srcUrl:
return ""
urlId = generate(size=10)
shortenedUrl = baseUrl + urlId
dbStatus = await save(urlId, srcUrl)
if dbStatus == False:
return ""
return shortenedUrl
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment