cleanup
This commit is contained in:
@@ -1,149 +0,0 @@
|
||||
# --- Global UTF-8 logging setup (fix UnicodeEncodeError) ---
|
||||
import sys
|
||||
import logging
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
# Add the parent directory to sys.path to import our modules
|
||||
# This must be done before any local imports
|
||||
current_dir = os.path.dirname(__file__)
|
||||
parent_dir = os.path.join(current_dir, '..')
|
||||
sys.path.insert(0, os.path.abspath(parent_dir))
|
||||
|
||||
from flask import Flask, render_template, request, jsonify, redirect, url_for
|
||||
import logging
|
||||
import atexit
|
||||
# Import config
|
||||
try:
|
||||
from config import config
|
||||
except ImportError:
|
||||
# Fallback config
|
||||
class Config:
|
||||
anime_directory = "./downloads"
|
||||
log_level = "INFO"
|
||||
config = Config()
|
||||
|
||||
# Simple auth decorators as fallbacks
|
||||
def require_auth(f):
|
||||
from functools import wraps
|
||||
@wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
return f(*args, **kwargs)
|
||||
return decorated_function
|
||||
|
||||
def optional_auth(f):
|
||||
return f
|
||||
|
||||
|
||||
# Placeholder for missing services
|
||||
class MockScheduler:
|
||||
def start_scheduler(self): pass
|
||||
def stop_scheduler(self): pass
|
||||
|
||||
def init_scheduler(config, socketio=None, app=None):
|
||||
return MockScheduler()
|
||||
|
||||
def init_series_app(verbose=False):
|
||||
if verbose:
|
||||
logging.info("Series app initialized (mock)")
|
||||
|
||||
|
||||
app = Flask(__name__,
|
||||
template_folder='web/templates/base',
|
||||
static_folder='web/static')
|
||||
app.config['SECRET_KEY'] = os.urandom(24)
|
||||
app.config['PERMANENT_SESSION_LIFETIME'] = 86400 # 24 hours
|
||||
|
||||
# Error handler for API routes to return JSON instead of HTML
|
||||
@app.errorhandler(404)
|
||||
def handle_api_not_found(error):
|
||||
"""Handle 404 errors for API routes by returning JSON instead of HTML."""
|
||||
if request.path.startswith('/api/'):
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': 'API endpoint not found',
|
||||
'path': request.path
|
||||
}), 404
|
||||
# For non-API routes, let Flask handle it normally
|
||||
return error
|
||||
|
||||
# Global error handler to log any unhandled exceptions
|
||||
@app.errorhandler(Exception)
|
||||
def handle_exception(e):
|
||||
logging.error("Unhandled exception occurred: %s", e, exc_info=True)
|
||||
if request.path.startswith('/api/'):
|
||||
return jsonify({'success': False, 'error': 'Internal Server Error'}), 500
|
||||
return "Internal Server Error", 500
|
||||
|
||||
# Register cleanup functions
|
||||
@atexit.register
|
||||
def cleanup_on_exit():
|
||||
"""Clean up resources on application exit."""
|
||||
try:
|
||||
# Additional cleanup functions will be added when features are implemented
|
||||
logging.info("Application cleanup completed")
|
||||
except Exception as e:
|
||||
logging.error(f"Error during cleanup: {e}")
|
||||
|
||||
# Basic routes since blueprints are missing
|
||||
@app.route('/')
|
||||
def index():
|
||||
return jsonify({
|
||||
'message': 'AniWorld Flask Server',
|
||||
'version': '1.0.0',
|
||||
'status': 'running'
|
||||
})
|
||||
|
||||
@app.route('/health')
|
||||
def health():
|
||||
return jsonify({
|
||||
'status': 'healthy',
|
||||
'timestamp': datetime.now().isoformat(),
|
||||
'services': {
|
||||
'flask': 'online',
|
||||
'config': 'loaded'
|
||||
}
|
||||
})
|
||||
|
||||
@app.route('/api/auth/login', methods=['POST'])
|
||||
def login():
|
||||
# Simple login endpoint
|
||||
data = request.get_json()
|
||||
if data and data.get('password') == 'admin123':
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'message': 'Login successful',
|
||||
'token': 'mock-jwt-token'
|
||||
})
|
||||
return jsonify({'success': False, 'error': 'Invalid password'}), 401
|
||||
|
||||
# Initialize scheduler
|
||||
scheduler = init_scheduler(config)
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Configure basic logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.info("Basic logging system initialized")
|
||||
|
||||
# Only run startup messages and scheduler in the parent process
|
||||
if os.environ.get('WERKZEUG_RUN_MAIN') != 'true':
|
||||
logger.info("Starting Aniworld Flask server...")
|
||||
logger.info(f"Anime directory: {config.anime_directory}")
|
||||
logger.info(f"Log level: {config.log_level}")
|
||||
|
||||
scheduler.start_scheduler()
|
||||
init_series_app(verbose=True)
|
||||
logger.info("Server will be available at http://localhost:5000")
|
||||
|
||||
try:
|
||||
# Run Flask app
|
||||
app.run(debug=True, host='0.0.0.0', port=5000)
|
||||
finally:
|
||||
# Clean shutdown
|
||||
if 'scheduler' in locals() and scheduler:
|
||||
scheduler.stop_scheduler()
|
||||
logger.info("Scheduler stopped")
|
||||
@@ -347,6 +347,22 @@ async def health_check() -> HealthResponse:
|
||||
}
|
||||
)
|
||||
|
||||
# Common browser requests that might cause "Invalid HTTP request received" warnings
|
||||
@app.get("/favicon.ico")
|
||||
async def favicon():
|
||||
"""Handle favicon requests from browsers."""
|
||||
return JSONResponse(status_code=404, content={"detail": "Favicon not found"})
|
||||
|
||||
@app.get("/robots.txt")
|
||||
async def robots():
|
||||
"""Handle robots.txt requests."""
|
||||
return JSONResponse(status_code=404, content={"detail": "Robots.txt not found"})
|
||||
|
||||
@app.get("/")
|
||||
async def root():
|
||||
"""Root endpoint redirect to docs."""
|
||||
return {"message": "AniWorld API", "documentation": "/docs", "health": "/health"}
|
||||
|
||||
# Anime endpoints (protected)
|
||||
@app.get("/api/anime/search", response_model=List[AnimeResponse], tags=["Anime"])
|
||||
async def search_anime(
|
||||
@@ -487,35 +503,46 @@ async def get_system_config(current_user: Dict = Depends(get_current_user)) -> D
|
||||
"version": "1.0.0"
|
||||
}
|
||||
|
||||
# Root endpoint
|
||||
@app.get("/", tags=["System"])
|
||||
async def root():
|
||||
"""
|
||||
Root endpoint with basic API information.
|
||||
"""
|
||||
return {
|
||||
"message": "AniWorld FastAPI Server",
|
||||
"version": "1.0.0",
|
||||
"docs": "/docs",
|
||||
"health": "/health"
|
||||
}
|
||||
|
||||
if __name__ == "__main__":
|
||||
import socket
|
||||
|
||||
# Configure enhanced logging
|
||||
log_level = getattr(logging, settings.log_level.upper(), logging.INFO)
|
||||
logging.getLogger().setLevel(log_level)
|
||||
|
||||
# Check if port is available
|
||||
def is_port_available(host: str, port: int) -> bool:
|
||||
"""Check if a port is available on the given host."""
|
||||
try:
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
||||
sock.bind((host, port))
|
||||
return True
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
host = "127.0.0.1"
|
||||
port = 8000
|
||||
|
||||
if not is_port_available(host, port):
|
||||
logger.error(f"Port {port} is already in use on {host}. Please stop other services or choose a different port.")
|
||||
logger.info("You can check which process is using the port with: netstat -ano | findstr :8000")
|
||||
sys.exit(1)
|
||||
|
||||
logger.info("Starting AniWorld FastAPI server with uvicorn...")
|
||||
logger.info(f"Anime directory: {settings.anime_directory}")
|
||||
logger.info(f"Log level: {settings.log_level}")
|
||||
logger.info("Server will be available at http://127.0.0.1:8000")
|
||||
logger.info("API documentation at http://127.0.0.1:8000/docs")
|
||||
logger.info(f"Server will be available at http://{host}:{port}")
|
||||
logger.info(f"API documentation at http://{host}:{port}/docs")
|
||||
|
||||
# Run the application
|
||||
uvicorn.run(
|
||||
"fastapi_app:app",
|
||||
host="127.0.0.1",
|
||||
port=8000,
|
||||
reload=False, # Disable reload to prevent constant restarting
|
||||
log_level=settings.log_level.lower()
|
||||
)
|
||||
try:
|
||||
# Run the application
|
||||
uvicorn.run(
|
||||
"fastapi_app:app",
|
||||
host=host,
|
||||
port=port,
|
||||
reload=False, # Disable reload to prevent constant restarting
|
||||
log_level=settings.log_level.lower()
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to start server: {e}")
|
||||
sys.exit(1)
|
||||
@@ -1,20 +0,0 @@
|
||||
@echo off
|
||||
REM Start the FastAPI server and run a simple test
|
||||
|
||||
echo Starting AniWorld FastAPI Server...
|
||||
cd /d "D:\repo\Aniworld\src\server"
|
||||
|
||||
REM Start server in background
|
||||
start "AniWorld Server" cmd /k "C:\Users\lukas\anaconda3\envs\AniWorld\python.exe fastapi_app.py"
|
||||
|
||||
REM Wait a moment for server to start
|
||||
timeout /t 5
|
||||
|
||||
REM Test the server
|
||||
echo Testing the server...
|
||||
C:\Users\lukas\anaconda3\envs\AniWorld\python.exe test_fastapi.py
|
||||
|
||||
echo.
|
||||
echo FastAPI server should be running in the other window.
|
||||
echo Visit http://localhost:8000/docs to see the API documentation.
|
||||
pause
|
||||
@@ -1,33 +0,0 @@
|
||||
@echo off
|
||||
REM AniWorld FastAPI Server Startup Script for Windows
|
||||
REM This script activates the conda environment and starts the FastAPI server
|
||||
|
||||
echo Starting AniWorld FastAPI Server...
|
||||
|
||||
REM Activate conda environment
|
||||
echo Activating AniWorld conda environment...
|
||||
call conda activate AniWorld
|
||||
|
||||
REM Change to server directory
|
||||
cd /d "%~dp0"
|
||||
|
||||
REM Set environment variables for development
|
||||
set PYTHONPATH=%PYTHONPATH%;%CD%\..\..
|
||||
|
||||
REM Check if .env file exists
|
||||
if not exist ".env" (
|
||||
echo Warning: .env file not found. Using default configuration.
|
||||
)
|
||||
|
||||
REM Install/update FastAPI dependencies if needed
|
||||
echo Checking FastAPI dependencies...
|
||||
pip install -r requirements_fastapi.txt
|
||||
|
||||
REM Start the FastAPI server with uvicorn
|
||||
echo Starting FastAPI server on http://localhost:8000
|
||||
echo API documentation available at http://localhost:8000/docs
|
||||
echo Press Ctrl+C to stop the server
|
||||
|
||||
python fastapi_app.py
|
||||
|
||||
pause
|
||||
@@ -1,32 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# AniWorld FastAPI Server Startup Script
|
||||
# This script activates the conda environment and starts the FastAPI server
|
||||
|
||||
echo "Starting AniWorld FastAPI Server..."
|
||||
|
||||
# Activate conda environment
|
||||
echo "Activating AniWorld conda environment..."
|
||||
source activate AniWorld
|
||||
|
||||
# Change to server directory
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
# Set environment variables for development
|
||||
export PYTHONPATH="${PYTHONPATH}:$(pwd)/../.."
|
||||
|
||||
# Check if .env file exists
|
||||
if [ ! -f ".env" ]; then
|
||||
echo "Warning: .env file not found. Using default configuration."
|
||||
fi
|
||||
|
||||
# Install/update FastAPI dependencies if needed
|
||||
echo "Checking FastAPI dependencies..."
|
||||
pip install -r requirements_fastapi.txt
|
||||
|
||||
# Start the FastAPI server with uvicorn
|
||||
echo "Starting FastAPI server on http://localhost:8000"
|
||||
echo "API documentation available at http://localhost:8000/docs"
|
||||
echo "Press Ctrl+C to stop the server"
|
||||
|
||||
python fastapi_app.py
|
||||
@@ -1,22 +0,0 @@
|
||||
@echo off
|
||||
echo Starting AniWorld Web Manager...
|
||||
echo.
|
||||
|
||||
REM Check if environment variable is set
|
||||
if "%ANIME_DIRECTORY%"=="" (
|
||||
echo WARNING: ANIME_DIRECTORY environment variable not set!
|
||||
echo Using default directory: \\sshfs.r\ubuntu@192.168.178.43\media\serien\Serien
|
||||
echo.
|
||||
echo To set your own directory, run:
|
||||
echo set ANIME_DIRECTORY="\\sshfs.r\ubuntu@192.168.178.43\media\serien\Serien"
|
||||
echo.
|
||||
pause
|
||||
)
|
||||
|
||||
REM Change to server directory
|
||||
cd /d "%~dp0"
|
||||
|
||||
REM Start the Flask application
|
||||
python app.py
|
||||
|
||||
pause
|
||||
@@ -1,21 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "Starting AniWorld Web Manager..."
|
||||
echo
|
||||
|
||||
# Check if environment variable is set
|
||||
if [ -z "$ANIME_DIRECTORY" ]; then
|
||||
echo "WARNING: ANIME_DIRECTORY environment variable not set!"
|
||||
echo "Using default directory: \\\\sshfs.r\\ubuntu@192.168.178.43\\media\\serien\\Serien"
|
||||
echo
|
||||
echo "To set your own directory, run:"
|
||||
echo "export ANIME_DIRECTORY=\"/path/to/your/anime/directory\""
|
||||
echo
|
||||
read -p "Press Enter to continue..."
|
||||
fi
|
||||
|
||||
# Change to server directory
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
# Start the Flask application
|
||||
python app.py
|
||||
@@ -1,109 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Simple test script for the AniWorld FastAPI server.
|
||||
"""
|
||||
|
||||
import requests
|
||||
import json
|
||||
|
||||
BASE_URL = "http://localhost:8000"
|
||||
|
||||
def test_health():
|
||||
"""Test the health endpoint."""
|
||||
print("Testing /health endpoint...")
|
||||
try:
|
||||
response = requests.get(f"{BASE_URL}/health")
|
||||
print(f"Status: {response.status_code}")
|
||||
print(f"Response: {json.dumps(response.json(), indent=2)}")
|
||||
return response.status_code == 200
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
return False
|
||||
|
||||
def test_root():
|
||||
"""Test the root endpoint."""
|
||||
print("\nTesting / endpoint...")
|
||||
try:
|
||||
response = requests.get(f"{BASE_URL}/")
|
||||
print(f"Status: {response.status_code}")
|
||||
print(f"Response: {json.dumps(response.json(), indent=2)}")
|
||||
return response.status_code == 200
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
return False
|
||||
|
||||
def test_login():
|
||||
"""Test the login endpoint."""
|
||||
print("\nTesting /auth/login endpoint...")
|
||||
try:
|
||||
# Test with correct password
|
||||
data = {"password": "admin123"}
|
||||
response = requests.post(f"{BASE_URL}/auth/login", json=data)
|
||||
print(f"Status: {response.status_code}")
|
||||
response_data = response.json()
|
||||
print(f"Response: {json.dumps(response_data, indent=2, default=str)}")
|
||||
|
||||
if response.status_code == 200:
|
||||
return response_data.get("token")
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
return None
|
||||
|
||||
def test_protected_endpoint(token):
|
||||
"""Test a protected endpoint with the token."""
|
||||
print("\nTesting /auth/verify endpoint (protected)...")
|
||||
try:
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
response = requests.get(f"{BASE_URL}/auth/verify", headers=headers)
|
||||
print(f"Status: {response.status_code}")
|
||||
print(f"Response: {json.dumps(response.json(), indent=2, default=str)}")
|
||||
return response.status_code == 200
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
return False
|
||||
|
||||
def test_anime_search(token):
|
||||
"""Test the anime search endpoint."""
|
||||
print("\nTesting /api/anime/search endpoint (protected)...")
|
||||
try:
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
params = {"query": "naruto", "limit": 5}
|
||||
response = requests.get(f"{BASE_URL}/api/anime/search", headers=headers, params=params)
|
||||
print(f"Status: {response.status_code}")
|
||||
print(f"Response: {json.dumps(response.json(), indent=2)}")
|
||||
return response.status_code == 200
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("AniWorld FastAPI Server Test")
|
||||
print("=" * 40)
|
||||
|
||||
# Test public endpoints
|
||||
health_ok = test_health()
|
||||
root_ok = test_root()
|
||||
|
||||
# Test authentication
|
||||
token = test_login()
|
||||
|
||||
if token:
|
||||
# Test protected endpoints
|
||||
verify_ok = test_protected_endpoint(token)
|
||||
search_ok = test_anime_search(token)
|
||||
|
||||
print("\n" + "=" * 40)
|
||||
print("Test Results:")
|
||||
print(f"Health endpoint: {'✓' if health_ok else '✗'}")
|
||||
print(f"Root endpoint: {'✓' if root_ok else '✗'}")
|
||||
print(f"Login endpoint: {'✓' if token else '✗'}")
|
||||
print(f"Token verification: {'✓' if verify_ok else '✗'}")
|
||||
print(f"Anime search: {'✓' if search_ok else '✗'}")
|
||||
|
||||
if all([health_ok, root_ok, token, verify_ok, search_ok]):
|
||||
print("\n🎉 All tests passed! The FastAPI server is working correctly.")
|
||||
else:
|
||||
print("\n❌ Some tests failed. Check the output above for details.")
|
||||
else:
|
||||
print("\n❌ Authentication failed. Cannot test protected endpoints.")
|
||||
Reference in New Issue
Block a user