Files
SMANAGE/gvsds/apps/core/views.py
T
2026-06-16 11:55:14 +08:00

174 lines
6.5 KiB
Python

import os
import mimetypes
from pathlib import Path
from django.http import HttpResponse, Http404, JsonResponse, HttpResponseRedirect
from django.views import View
from django.conf import settings
from gvsds.template_engine import render_template
TEMPLATE_DIR = Path(settings.BASE_DIR) / "TempLate"
MIME_TYPES = {
'.js': 'application/javascript',
'.mjs': 'application/javascript',
'.css': 'text/css',
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.gif': 'image/gif',
'.svg': 'image/svg+xml',
'.ico': 'image/x-icon',
'.woff': 'font/woff',
'.woff2': 'font/woff2',
'.ttf': 'font/ttf',
'.eot': 'application/vnd.ms-fontobject',
'.json': 'application/json',
'.xml': 'application/xml',
'.html': 'text/html',
'.htm': 'text/html',
'.txt': 'text/plain',
'.pdf': 'application/pdf',
'.zip': 'application/zip',
'.mp4': 'video/mp4',
'.webp': 'image/webp',
'.map': 'application/json',
}
SUBDOMAIN_CONFIG = {
'www': {'dir': '', 'root_is_index': True, 'use_base': True},
'gerp': {'dir': 'GERP', 'root_is_index': True, 'base': 'GERP/_Base'},
'ugm': {'dir': '', 'root_is_index': True},
'api': {'dir': None, 'root_is_index': False},
'mc': {'dir': 'MC', 'root_is_index': True},
'3crb': {'dir': 'CCCRB', 'root_is_index': True},
'ccgo': {'dir': 'CCGO', 'root_is_index': True},
'invite': {'dir': 'Invite', 'root_is_index': True, 'use_base': True},
'doc': {'dir': 'Document', 'root_is_index': True},
't4': {'dir': None, 'root_is_index': False},
'verify': {'dir': 'Verify', 'root_is_index': True},
'verifox': {'dir': 'Verifox', 'root_is_index': True},
'nav': {'dir': 'nav', 'root_is_index': True},
'history': {'dir': 'history', 'root_is_index': True},
'cdn': {'dir': 'cdn', 'root_is_index': False, 'root_text': 'GVSDS CDN'},
'yc8z': {'dir': 'yc8z', 'root_is_index': True},
'omc': {'dir': 'omc', 'root_is_index': True},
'tailwind': {'dir': 'Tailwindcss', 'root_is_index': False, 'root_redirect': '/3.4.17'},
'nanjingmassacre': {'dir': 'NanjingMassacre', 'root_is_index': True},
'3c': {'dir': None, 'root_is_index': False},
'vu': {'dir': None, 'root_is_index': False},
'links': {'dir': None, 'root_is_index': False},
'unclear': {'dir': 'Unclear', 'root_is_index': True},
}
def _get_subdomain(request):
return getattr(request, 'subdomain', 'www') or 'www'
def _get_subdomain_dir(subdomain):
config = SUBDOMAIN_CONFIG.get(subdomain, {})
return config.get('dir', '')
def _resolve_file(subdomain, file_path):
if '..' in file_path.split('/') or '..' in file_path.split(os.sep):
return None
subdomain_dir = _get_subdomain_dir(subdomain)
if subdomain_dir is None:
return None
if subdomain_dir:
candidate = TEMPLATE_DIR / subdomain_dir / file_path
try:
candidate.resolve().relative_to(TEMPLATE_DIR.resolve())
except ValueError:
return None
if candidate.is_file():
return candidate
candidate = TEMPLATE_DIR / file_path
try:
candidate.resolve().relative_to(TEMPLATE_DIR.resolve())
except ValueError:
return None
if candidate.is_file():
return candidate
return None
def _serve_file(full_path, subdomain=None):
ext = full_path.suffix.lower()
content_type = MIME_TYPES.get(ext, mimetypes.guess_type(str(full_path))[0] or 'application/octet-stream')
if ext in ('.html', '.htm'):
rel_path = full_path.relative_to(TEMPLATE_DIR)
template_name = str(rel_path).replace('\\', '/')
base = None
use_base = False
if subdomain:
config = SUBDOMAIN_CONFIG.get(subdomain, {})
base = config.get('base')
use_base = config.get('use_base', False)
if base:
return render_template(request=None, template_name=template_name, UseBase='false', SubBase=base)
if not use_base:
return render_template(request=None, template_name=template_name, UseBase='false')
return render_template(request=None, template_name=template_name, UseBase='true')
with open(full_path, 'rb') as f:
response = HttpResponse(f.read(), content_type=content_type)
if ext in ('.css', '.js', '.mjs', '.json', '.xml', '.txt', '.svg'):
response['Cache-Control'] = 'public, max-age=3600'
elif ext in ('.png', '.jpg', '.jpeg', '.gif', '.webp', '.ico', '.woff', '.woff2', '.ttf', '.eot', '.mp4'):
response['Cache-Control'] = 'public, max-age=86400'
return response
class SubdomainView(View):
def get(self, request, file_path=''):
subdomain = _get_subdomain(request)
config = SUBDOMAIN_CONFIG.get(subdomain, {})
if config.get('dir') is None:
raise Http404
# ugm 子域:未登录则跳转登录页,已登录则跳转 gerp
if subdomain == 'ugm':
elt_token = request.COOKIES.get('ELToken')
if not elt_token:
# 未登录 → 跳转登录页
if file_path and file_path not in ('/', 'login.html', 'register.html'):
from django.urls import reverse
login_url = f"https://ugm.gvsds.com/login.html?redirect=https://gerp.gvsds.com/"
return HttpResponseRedirect(login_url)
if not file_path or file_path == '/':
return HttpResponseRedirect('https://ugm.gvsds.com/login.html')
else:
# 已登录 → 跳转 gerp
if not file_path or file_path == '/' or file_path == 'index.html':
return HttpResponseRedirect('https://gerp.gvsds.com/')
if not file_path or file_path == '/':
if config.get('root_redirect'):
return HttpResponseRedirect(config['root_redirect'])
if config.get('root_text') is not None:
return HttpResponse(config['root_text'])
if config.get('root_is_index'):
file_path = 'index.html'
else:
raise Http404
if file_path.endswith('/'):
file_path += 'index.html'
if subdomain == 'tailwind' and not file_path.endswith('.js') and not file_path.endswith('.json'):
js_path = _resolve_file(subdomain, file_path + '.js')
if js_path:
return _serve_file(js_path, subdomain)
resolved = _resolve_file(subdomain, file_path)
if resolved:
return _serve_file(resolved, subdomain)
raise Http404