Skip to content

Commit

Permalink
Merge pull request #21 from yihong1120/feature/separation-of-front-an…
Browse files Browse the repository at this point in the history
…d-back-ends

Feature/separation of front and back ends
  • Loading branch information
yihong1120 authored Nov 21, 2024
2 parents c73eae7 + 2da9e73 commit 5f98c56
Show file tree
Hide file tree
Showing 29 changed files with 396 additions and 524 deletions.
88 changes: 0 additions & 88 deletions config/nginx_config_example.conf

This file was deleted.

51 changes: 51 additions & 0 deletions config/streaming_web_frontend.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
server {
# Listen on port 80 (HTTP)
listen 80;
server_name changdar-server.mooo.com;

# Set the root directory for the website, pointing to the dist folder of the frontend build
root /var/www/html;

# Specify the default homepage file
index index.html;

# Handle static file requests
location / {
# Check if the requested file exists, otherwise fallback to index.html (for SPA)
try_files $uri /index.html;
}

# Proxy /api requests to the backend service
location /api/ {
proxy_pass http://127.0.0.1:8800; # Backend service address
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

# Necessary configuration to support WebSocket upgrades
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}

# Configure caching for static assets
location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg|mp4)$ {
expires 6M;
access_log off;
add_header Cache-Control "public";
}

# Configure the 404 error page
error_page 404 /index.html;

# Handle WebSocket live streaming on a specific route (if required)
location /ws/ {
proxy_pass http://127.0.0.1:8800; # Backend WebSocket service address
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
或是

```sh
uvicorn examples.streaming_web.app:sio_app --host 127.0.0.1 --port 8000
uvicorn examples.streaming_web.backend.app:sio_app --host 127.0.0.1 --port 8000
```

2. **打開您的網頁瀏覽器並導航至:**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ This section provides an example implementation of a Streaming Web application,
or

```sh
uvicorn examples.streaming_web.app:sio_app --host 127.0.0.1 --port 8000
uvicorn examples.streaming_web.backend.app:sio_app --host 127.0.0.1 --port 8000
```

2. **Open your web browser and navigate to:**
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ async def lifespan(app: FastAPI) -> AsyncGenerator[None]:
# Mount the static files directory to serve static assets
app.mount(
'/static',
StaticFiles(directory='examples/streaming_web/static'),
StaticFiles(directory='examples/streaming_web/backend/static'),
name='static',
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@
from fastapi import WebSocket
from fastapi import WebSocketDisconnect
from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles
from fastapi_limiter.depends import RateLimiter
from starlette.responses import Response
from starlette.templating import Jinja2Templates

from .utils import RedisManager
from .utils import Utils
Expand All @@ -23,9 +20,6 @@

# Create an API router for defining routes
router = APIRouter()
templates = Jinja2Templates(
directory='examples/streaming_web/templates',
)


def register_routes(app: Any) -> None:
Expand All @@ -37,96 +31,62 @@ def register_routes(app: Any) -> None:
"""
app.include_router(router)

# Mount the static files directory to serve static assets
app.mount(
'/static',
StaticFiles(directory='examples/streaming_web/static'),
name='static',
)


# Create rate limiters for the API routes
rate_limiter_index = RateLimiter(times=60, seconds=60)
rate_limiter_label = RateLimiter(times=6000, seconds=6000)


@router.get('/', dependencies=[Depends(rate_limiter_index)])
async def index(request: Request) -> Response:
"""
Renders the index page with available labels from Redis.
Args:
request (Request): The HTTP request object.
Returns:
Response: The rendered HTML template for the index page,
containing available labels.
"""
try:
# Retrieve available labels from Redis
labels = await redis_manager.get_labels()
except Exception as e:
# Raise HTTP 500 error if labels cannot be fetched
raise HTTPException(
status_code=500, detail=f"Failed to fetch labels: {str(e)}",
)
# Render and return the index template with the fetched labels
return templates.TemplateResponse(
request,
'index.html',
{
'labels': labels,
},
)


@router.get('/label/{label}', dependencies=[Depends(rate_limiter_label)])
async def label_page(
request: Request,
label: str,
) -> Response:
@router.get('/api/labels', dependencies=[Depends(rate_limiter_index)])
async def get_labels() -> JSONResponse:
"""
Renders the page for a specific label with available labels from Redis.
Args:
request (Request): The HTTP request object.
label (str): The label identifier to display on the page.
None
Returns:
Response: The rendered HTML template for the label page
with available labels.
JSONResponse: A JSON response containing the labels.
"""
try:
# Retrieve available labels from Redis
labels = await redis_manager.get_labels()

# Check if the requested label is present in the available labels
if label not in labels:
# Raise HTTP 404 error if the label is not found
raise HTTPException(
status_code=404, detail=f"Label '{label}' not found",
)
except HTTPException as e:
# Re-raise HTTP exceptions
raise e
except ValueError as ve:
print(f"ValueError while fetching labels: {str(ve)}")
raise HTTPException(
status_code=400,
detail=f"Invalid data encountered: {str(ve)}",
)
except KeyError as ke:
print(f"KeyError while fetching labels: {str(ke)}")
raise HTTPException(
status_code=404,
detail=f"Missing key encountered: {str(ke)}",
)
except ConnectionError as ce:
print(f"ConnectionError while fetching labels: {str(ce)}")
raise HTTPException(
status_code=503,
detail=f"Failed to connect to the database: {str(ce)}",
)
except TimeoutError as te:
print(f"TimeoutError while fetching labels: {str(te)}")
raise HTTPException(
status_code=504,
detail=f"Request timed out: {str(te)}",
)
except Exception as e:
# Log unexpected errors and raise HTTP 500 error
print(f"Unexpected error while fetching labels: {str(e)}")
raise HTTPException(
status_code=500, detail=f"Failed to fetch labels: {str(e)}",
status_code=500,
detail=f"Failed to fetch labels: {str(e)}",
)

# Render and return the label template with the fetched labels
return templates.TemplateResponse(
request,
'label.html',
{
'label': label,
'labels': labels,
},
)
return JSONResponse(content={'labels': labels})


@router.websocket('/ws/label/{label}')
@router.websocket('/api/ws/labels/{label}')
async def websocket_label_stream(websocket: WebSocket, label: str) -> None:
"""
Establishes a WebSocket connection to stream updated frames
Expand Down Expand Up @@ -168,7 +128,7 @@ async def websocket_label_stream(websocket: WebSocket, label: str) -> None:
print('WebSocket connection closed')


@router.post('/webhook')
@router.post('/api/webhook')
async def webhook(request: Request) -> JSONResponse:
"""
Processes incoming webhook requests by logging the request body.
Expand All @@ -188,7 +148,7 @@ async def webhook(request: Request) -> JSONResponse:
# Uncomment and use the following endpoint for file uploads if needed


@router.post('/upload')
@router.post('/api/upload')
async def upload_file(file: UploadFile) -> JSONResponse:
"""
Saves an uploaded file to the designated upload folder
Expand All @@ -200,10 +160,10 @@ async def upload_file(file: UploadFile) -> JSONResponse:
Returns:
JSONResponse: A JSON response containing the URL of the uploaded file.
"""
UPLOAD_FOLDER = Path('static/uploads')
UPLOAD_FOLDER = Path('uploads')
UPLOAD_FOLDER.mkdir(parents=True, exist_ok=True)

# 检查 filename 是否为 None
# Check if the file has a filename
if not file.filename:
raise HTTPException(status_code=400, detail='Filename is missing')

Expand All @@ -216,5 +176,5 @@ async def upload_file(file: UploadFile) -> JSONResponse:
status_code=500, detail=f"Failed to save file: {str(e)}",
)

url = f"https://yihong-server.mooo.com/static/uploads/{file.filename}"
url = f"/uploads/{file.filename}"
return JSONResponse(content={'url': url})
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def __init__(
redis_password (str): The Redis password for authentication.
"""
self.redis_host: str = os.getenv('REDIS_HOST') or redis_host
self.redis_port: int = int(os.getenv('REDIS_PORT')) or redis_port
self.redis_port: int = int(os.getenv('REDIS_PORT') or redis_port)
self.redis_password: str = os.getenv(
'REDIS_PASSWORD',
) or redis_password
Expand Down Expand Up @@ -74,11 +74,16 @@ async def get_labels(self) -> list[str]:
match = re.match(
r'stream_frame:([\w\x80-\xFF]+)_([\w\x80-\xFF]+)', key,
)
if match:
label, stream_name = match.groups()
if not match:
continue

label, stream_name = match.groups()

if 'test' in label:
continue

labels.add(label)

if label and 'test' not in label:
labels.add(f"{label}")

if cursor == 0: # Exit loop if scan cursor has reached the end
break
Expand Down
Loading

0 comments on commit 5f98c56

Please sign in to comment.