blivechat/api/main.py
2024-11-12 20:09:42 +08:00

121 lines
3.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
import asyncio
import hashlib
import logging
import os
import tornado.web
import api.base
import config
import update
logger = logging.getLogger(__name__)
EMOTICON_UPLOAD_PATH = os.path.join(config.DATA_PATH, 'emoticons')
EMOTICON_BASE_URL = '/emoticons'
CUSTOM_PUBLIC_PATH = os.path.join(config.DATA_PATH, 'custom_public')
class StaticHandler(tornado.web.StaticFileHandler):
"""为了使用Vue Router的history模式把不存在的文件请求转发到index.html"""
async def get(self, path, include_body=True):
if path == '':
await self._get_index(include_body)
return
try:
await super().get(path, include_body)
except tornado.web.HTTPError as e:
if e.status_code != 404:
raise
# 不存在的文件请求转发到index.html交给前端路由
await self._get_index(include_body)
async def _get_index(self, include_body=True):
# index.html不缓存防止更新后前端还是旧版
self.set_header('Cache-Control', 'no-cache')
await super().get('index.html', include_body)
class ServerInfoHandler(api.base.ApiHandler):
async def get(self):
cfg = config.get_config()
self.write({
'version': update.VERSION,
'config': {
'enableTranslate': cfg.enable_translate,
'enableUploadFile': cfg.enable_upload_file,
'loaderUrl': cfg.loader_url,
'enableAdminPlugins': cfg.enable_admin_plugins,
}
})
class ServiceDiscoveryHandler(api.base.ApiHandler):
async def get(self):
cfg = config.get_config()
self.write({
'endpoints': cfg.registered_endpoints,
})
class PingHandler(api.base.ApiHandler):
async def get(self):
self.set_status(204)
class UploadEmoticonHandler(api.base.ApiHandler):
async def post(self):
cfg = config.get_config()
if not cfg.enable_upload_file:
raise tornado.web.HTTPError(403)
try:
file = self.request.files['file'][0]
except LookupError:
raise tornado.web.MissingArgumentError('file')
if len(file.body) > 1024 * 1024:
raise tornado.web.HTTPError(413, 'file is too large, size=%d', len(file.body))
if not file.content_type.lower().startswith('image/'):
raise tornado.web.HTTPError(415)
url = await asyncio.get_running_loop().run_in_executor(
None, self._save_file, file.body, self.request.remote_ip
)
self.write({'url': url})
@staticmethod
def _save_file(body, client):
md5 = hashlib.md5(body).hexdigest()
filename = md5 + '.png'
path = os.path.join(EMOTICON_UPLOAD_PATH, filename)
logger.info('client=%s uploaded file, path=%s, size=%d', client, path, len(body))
tmp_path = path + '.tmp'
with open(tmp_path, 'wb') as f:
f.write(body)
os.replace(tmp_path, path)
return f'{EMOTICON_BASE_URL}/{filename}'
class NoCacheStaticFileHandler(tornado.web.StaticFileHandler):
def set_extra_headers(self, path):
self.set_header('Cache-Control', 'no-cache')
ROUTES = [
(r'/api/server_info', ServerInfoHandler),
(r'/api/endpoints', ServiceDiscoveryHandler),
(r'/api/ping', PingHandler),
(r'/api/emoticon', UploadEmoticonHandler),
]
# 通配的放在最后
LAST_ROUTES = [
(rf'{EMOTICON_BASE_URL}/(.*)', tornado.web.StaticFileHandler, {'path': EMOTICON_UPLOAD_PATH}),
# 这个目录不保证文件内容不会变,还是不用缓存了
(r'/custom_public/(.*)', NoCacheStaticFileHandler, {'path': CUSTOM_PUBLIC_PATH}),
(r'/(.*)', StaticHandler, {'path': config.WEB_ROOT}),
]