22from pathlib import Path
33from typing import Optional
44
5- from fastapi import FastAPI , Form , Request
5+ from fastapi import FastAPI , Form , Request , status
66from fastapi .responses import HTMLResponse , PlainTextResponse , RedirectResponse
77from fastapi .staticfiles import StaticFiles
88from fastapi .templating import Jinja2Templates
2828from app .utils .qr import generate_qr_with_logo
2929
3030
31-
3231# -----------------------------
3332# Lifespan: env + DB connect ONCE
3433# -----------------------------
@@ -103,37 +102,27 @@ async def create_short_url(
103102 original_url : str = Form ("" ),
104103 generate_qr : Optional [str ] = Form (None ),
105104 qr_type : str = Form ("short" ),
106- ):
105+ ) -> RedirectResponse :
107106 session = request .session
108107 qr_enabled = bool (generate_qr )
109108 original_url = sanitize_url (original_url )
110109
111- if not original_url :
112- session ["error" ] = "URL cannot be empty."
113- return RedirectResponse ("/" , status_code = 303 )
114-
115- if not is_valid_url (original_url ):
116- session ["error" ] = (
117- "Please enter a valid URL (must start with http:// or https://)."
118- )
119- return RedirectResponse ("/" , status_code = 303 )
110+ # Basic validation (FastAPI can also handle this via Pydantic)
111+ if not original_url or not is_valid_url (original_url ):
112+ session ["error" ] = "Please enter a valid URL."
113+ return RedirectResponse ("/" , status_code = status .HTTP_303_SEE_OTHER )
120114
121115 # 1. Try Cache First
122116 short_code : Optional [str ] = get_short_from_cache (original_url )
123117
124- if short_code :
125- session ["info_message" ] = "Already shortened before — fetched from cache."
126- else :
118+ if not short_code :
127119 # 2. Try Database
128120 existing = db_data .find_by_original_url (original_url )
129121 # Pull the value and check it in one go
130122 db_code = existing .get ("short_code" ) if existing else None
131123 if isinstance (db_code , str ):
132124 short_code = db_code
133- set_cache_pair (short_code , original_url ) # Cache it for future
134- session ["info_message" ] = (
135- "Already shortened before — fetched from database."
136- )
125+ set_cache_pair (short_code , original_url ) # Cache it for future requests
137126
138127 # 3. Generate New if still None
139128 if not short_code :
@@ -147,7 +136,7 @@ async def create_short_url(
147136 if not isinstance (short_code , str ):
148137 # This acts as a final safety net for production
149138 session ["error" ] = "Internal server error: Code generation failed."
150- return RedirectResponse ("/" , status_code = 303 )
139+ return RedirectResponse ("/" , status_code = status . HTTP_303_SEE_OTHER )
151140
152141 # Mypy now knows short_code is strictly 'str'
153142 new_short_url = build_short_url (short_code , DOMAIN )
@@ -162,7 +151,7 @@ async def create_short_url(
162151 }
163152 )
164153
165- return RedirectResponse ("/" , status_code = 303 )
154+ return RedirectResponse ("/" , status_code = status . HTTP_303_SEE_OTHER )
166155
167156
168157@app .get ("/recent" , response_class = HTMLResponse )
0 commit comments