57 lines
1.7 KiB
Python
57 lines
1.7 KiB
Python
import time
|
|
from urllib.parse import urljoin
|
|
|
|
from fastapi import FastAPI, status, HTTPException
|
|
from fastapi.responses import RedirectResponse
|
|
import redis
|
|
|
|
from app.config import settings
|
|
from app.dao import URLsDAO
|
|
from app.migrations.shemas import SURL, SNewUrl, SGetStats
|
|
|
|
app = FastAPI(
|
|
title="Сокращатель ссылок",
|
|
)
|
|
|
|
r = redis.Redis(host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=settings.REDIS_DB)
|
|
|
|
|
|
@app.post("/zip_url", response_model=SNewUrl)
|
|
async def zip_url(url: SURL):
|
|
url = str(url.url)
|
|
|
|
url_hash = await URLsDAO.add_new_url(original_url=url)
|
|
|
|
new_url_path = urljoin(settings.SHORTENER_HOST, str(url_hash))
|
|
|
|
return {"new_url_path": new_url_path}
|
|
|
|
|
|
@app.get("/{url_hash}", response_class=RedirectResponse, status_code=status.HTTP_307_TEMPORARY_REDIRECT)
|
|
async def redirect(url_hash: int):
|
|
if r.exists(str(url_hash)):
|
|
url_bytes = r.get(str(url_hash))
|
|
url = url_bytes.decode('utf-8')
|
|
else:
|
|
urls = await URLsDAO.find_by_hash(url_hash)
|
|
if not urls:
|
|
raise HTTPException(status_code=404, detail="Этой ссылки ещё не существует")
|
|
url = urls.original_url
|
|
r.set(str(url_hash), url)
|
|
r.expire(str(url_hash), 60)
|
|
|
|
list_key = f"visit_times:{url_hash}"
|
|
timestamp = int(time.time())
|
|
r.lpush(list_key, timestamp)
|
|
|
|
return RedirectResponse(url=url)
|
|
|
|
|
|
@app.get("/stats/{url_hash}", response_model=SGetStats)
|
|
async def get_stats(url_hash: int):
|
|
list_key = f"visit_times:{url_hash}"
|
|
if r.exists(list_key):
|
|
timestamps = r.lrange(list_key, 0, -1)
|
|
visit_times = len(timestamps)
|
|
return {"visit_times": visit_times, "timestamps": timestamps}
|
|
return {"visit_times": 0, "timestamps": []}
|