"""雜項 Routes Blueprint。從 app.py 抽離(Phase 3e)。 收納尚未歸類的小型 routes: - POST /api/test_url:測試外部網址連通性 - GET /brand_assets:品牌資產庫頁面 """ import requests from flask import Blueprint, jsonify, render_template, request from urllib.parse import urljoin from auth import login_required from services.logger_manager import SystemLogger from utils.security import validate_public_http_url misc_bp = Blueprint('misc', __name__) sys_log = SystemLogger('MiscRoutes').get_logger() @misc_bp.route('/api/test_url', methods=['POST']) @login_required def test_url(): """API: 測試網址是否有效""" try: data = request.get_json() url = data.get('url') if not url: return jsonify({"status": "error", "message": "網址不能為空"}), 400 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" } current_url = validate_public_http_url(url) response = None for _ in range(4): response = requests.get( current_url, headers=headers, timeout=(3.05, 10), allow_redirects=False, stream=True, ) if response.status_code not in {301, 302, 303, 307, 308}: break location = response.headers.get('Location') response.close() if not location: break current_url = validate_public_http_url(urljoin(current_url, location)) if response is None: raise ValueError('無法取得網址回應') status_code = response.status_code response.close() if status_code == 200: return jsonify({"status": "success", "message": f"✅ 連結有效 (Status: 200)"}) else: return jsonify({"status": "warning", "message": f"⚠️ 連結回應異常 (Status: {status_code})"}) except ValueError as exc: return jsonify({"status": "error", "message": str(exc)}), 400 except Exception as exc: sys_log.warning(f"[Misc] [URL_CHECK] 連線失敗 | Error: {exc}") return jsonify({"status": "error", "message": "連線失敗,請確認網址後再試。"}), 502 @misc_bp.route('/brand_assets') def brand_assets(): """顯示品牌資產庫""" return render_template('brand_assets.html', active_page='brand_assets')