Files
workspacewanderers/api/app.py
2025-02-15 16:20:54 +01:00

115 lines
4.2 KiB
Python

from flask import Flask, request, jsonify, make_response
import requests
import json
from urllib.parse import urlparse
import logging
# Configure basic logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Initialize Flask app
MyApp = Flask(__name__)
MyApp.config['SECRET_KEY'] = 'your-secret-key-here'
class ResourceRouter:
def __init__(self):
self.resource_mappings = {
'login': {'backend_url': 'http://linepe.de:5004/login', 'methods': ['POST']},
'logout': {'backend_url': 'http://linepe.de:5004/logout', 'methods': ['POST']},
'register': {'backend_url': 'http://linepe.de:5004/register', 'methods': ['POST']},
'listing': {'backend_url': 'http://linepe.de:5005/listing', 'methods': ['GET', 'POST', 'PUT', 'DELETE']},
'listings': {'backend_url': 'http://linepe.de:5005/listings', 'methods': ['GET', 'POST', 'PUT', 'DELETE']}
}
def get_backend_info(self, resource_path):
"""Get backend URL and allowed methods based on the resource path"""
return self.resource_mappings.get(resource_path)
def is_valid_request(self, resource_path, method):
"""Check if the request path and method are valid"""
backend_info = self.get_backend_info(resource_path)
if not backend_info:
return False
return method in backend_info['methods']
resource_router = ResourceRouter()
def handle_backend_response(response):
"""Helper function to handle backend responses"""
if not response.ok:
logger.error(f"Backend request failed with status code {response.status_code}")
# Check if the response has a valid Content-Type header for JSON
if response.headers.get('Content-Type', '').startswith('application/json'):
try:
logger.error(f"Errormessage {response.json()}")
except ValueError as e:
logger.error(f"Failed to parse JSON response: {e}")
else:
# If the response isn't JSON, log the raw response content
logger.error(f"Non-JSON response received: {response.text}")
if not response.json():
return jsonify({"error": f"Failed to process request"}), 500
else:
return response.json(), response.status_code
try:
data = response.json()
return jsonify(data), response.status_code
except json.JSONDecodeError:
logger.error("Failed to decode backend response")
return jsonify({"error": "Invalid response format"}), 500
@MyApp.route('/')
def home():
"""Health check endpoint"""
return jsonify({'status': 'ok', 'message': 'API gateway is running'})
@MyApp.route('/<path:path>', methods=['GET', 'POST', 'PUT', 'DELETE'])
def generic_proxy(path):
"""Generic route handler for all API resources"""
if "/" in path:
route_parts = path.split('/')
resource = route_parts[0]
listing_id = route_parts[1]
elif "?" in path:
route_parts = path.split('?')
resource = route_parts[0]
else:
resource = path
if not resource_router.is_valid_request(resource, request.method):
return jsonify({"error": "Invalid path or method"}), 405
backend_info = resource_router.get_backend_info(resource)
backend_url = backend_info['backend_url']
# Extract all query parameters
query_params = dict(request.args)
try:
data = {}
if request.is_json and request.json:
data.update(request.json)
# Append listing_id to the URL if present in query parameters
if "/" in path:
backend_url += f"/{listing_id}"
# Make the request to the backend service
response = requests.request(
method=request.method,
url=backend_url,
json=data,
params=query_params, # Send all remaining query parameters as part of the request
headers=request.headers
)
return handle_backend_response(response)
except Exception as e:
logger.error(f"Error proxying request: {str(e)}")
return jsonify({"error": str(e)}), 500
if __name__ == '__main__':
MyApp.run(debug=True, port=5000)