mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-31 03:43:57 +08:00
update:优化http_server所在目录
This commit is contained in:
@@ -2,8 +2,7 @@ import asyncio
|
|||||||
from config.logger import setup_logging
|
from config.logger import setup_logging
|
||||||
from config.settings import load_config
|
from config.settings import load_config
|
||||||
from core.websocket_server import WebSocketServer
|
from core.websocket_server import WebSocketServer
|
||||||
from manager.http_server import ConfigServer
|
from manager.http_server import WebUI
|
||||||
from core.webui import WebUI
|
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
from core.utils.util import get_local_ip
|
from core.utils.util import get_local_ip
|
||||||
|
|
||||||
@@ -15,36 +14,28 @@ async def main():
|
|||||||
ws_server = WebSocketServer(config)
|
ws_server = WebSocketServer(config)
|
||||||
ws_task = asyncio.create_task(ws_server.start())
|
ws_task = asyncio.create_task(ws_server.start())
|
||||||
|
|
||||||
# 启动 HTTP 配置服务器
|
|
||||||
http_runner = None
|
|
||||||
if config['manager'].get('enabled', False):
|
|
||||||
config_server = ConfigServer(config)
|
|
||||||
try:
|
|
||||||
http_runner = await config_server.start()
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Failed to start HTTP server: {e}")
|
|
||||||
|
|
||||||
# 启动 WebUI 服务器
|
# 启动 WebUI 服务器
|
||||||
webui_runner = None
|
webui_runner = None
|
||||||
try:
|
if config['manager'].get('enabled', False):
|
||||||
webui = WebUI()
|
server_config = config["manager"]
|
||||||
runner = web.AppRunner(webui.app)
|
host = server_config["ip"]
|
||||||
await runner.setup()
|
port = server_config["port"]
|
||||||
site = web.TCPSite(runner, '0.0.0.0', 8002)
|
try:
|
||||||
await site.start()
|
webui = WebUI()
|
||||||
webui_runner = runner
|
runner = web.AppRunner(webui.app)
|
||||||
local_ip = get_local_ip()
|
await runner.setup()
|
||||||
print(f"WebUI server is running at http://{local_ip}:8002")
|
site = web.TCPSite(runner, host, port)
|
||||||
except Exception as e:
|
await site.start()
|
||||||
print(f"Failed to start WebUI server: {e}")
|
webui_runner = runner
|
||||||
|
local_ip = get_local_ip()
|
||||||
|
print(f"WebUI server is running at http://{local_ip}:{port}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Failed to start WebUI server: {e}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 等待 WebSocket 服务器运行
|
# 等待 WebSocket 服务器运行
|
||||||
await ws_task
|
await ws_task
|
||||||
finally:
|
finally:
|
||||||
# 清理 HTTP 服务器
|
|
||||||
if http_runner:
|
|
||||||
await http_runner.cleanup()
|
|
||||||
# 清理 WebUI 服务器
|
# 清理 WebUI 服务器
|
||||||
if webui_runner:
|
if webui_runner:
|
||||||
await webui_runner.cleanup()
|
await webui_runner.cleanup()
|
||||||
|
|||||||
+3
-3
@@ -22,11 +22,11 @@ server:
|
|||||||
#allowed_devices:
|
#allowed_devices:
|
||||||
# - "24:0A:C4:1D:3B:F0" # MAC地址列表
|
# - "24:0A:C4:1D:3B:F0" # MAC地址列表
|
||||||
manager:
|
manager:
|
||||||
|
# 是否启用管理后台
|
||||||
|
# 目前这个模块还在开发中,建议:不要修改enabled选项
|
||||||
enabled: false
|
enabled: false
|
||||||
ip: 0.0.0.0
|
ip: 0.0.0.0
|
||||||
port: 8001
|
port: 8002
|
||||||
# 请把密码设置10位数,且不能包含xiaozhi这几个字符
|
|
||||||
password: 123456
|
|
||||||
|
|
||||||
xiaozhi:
|
xiaozhi:
|
||||||
type: hello
|
type: hello
|
||||||
|
|||||||
@@ -1,90 +0,0 @@
|
|||||||
import os
|
|
||||||
import sys
|
|
||||||
import logging
|
|
||||||
from aiohttp import web
|
|
||||||
from aiohttp_cors import setup as cors_setup, ResourceOptions
|
|
||||||
from core.utils.util import get_local_ip
|
|
||||||
|
|
||||||
# 添加项目根目录到Python路径
|
|
||||||
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
root_dir = os.path.dirname(current_dir)
|
|
||||||
sys.path.append(root_dir)
|
|
||||||
|
|
||||||
from manager.api.login import LoginHandler
|
|
||||||
from manager.api.register import RegisterHandler
|
|
||||||
from manager.user_manager import UserManager
|
|
||||||
from manager.api.config import ConfigHandler
|
|
||||||
|
|
||||||
logging.basicConfig(level=logging.INFO)
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
class WebUI:
|
|
||||||
def __init__(self):
|
|
||||||
self.app = web.Application()
|
|
||||||
self.user_manager = UserManager()
|
|
||||||
|
|
||||||
# 添加静态文件路径
|
|
||||||
self.static_path = os.path.join(root_dir, 'manager', 'static', 'webui')
|
|
||||||
|
|
||||||
# 创建配置字典
|
|
||||||
self.config = {
|
|
||||||
'users': self.user_manager.get_users(),
|
|
||||||
'hash_password': self.user_manager.hash_password,
|
|
||||||
'save_user_data': self.user_manager.save_user_data,
|
|
||||||
'get_user': self.user_manager.get_user,
|
|
||||||
'update_user': self.user_manager.update_user
|
|
||||||
}
|
|
||||||
|
|
||||||
self.setup_routes()
|
|
||||||
self.setup_cors()
|
|
||||||
|
|
||||||
def setup_cors(self):
|
|
||||||
"""设置CORS"""
|
|
||||||
cors = cors_setup(self.app, defaults={
|
|
||||||
"*": ResourceOptions(
|
|
||||||
allow_credentials=True,
|
|
||||||
expose_headers="*",
|
|
||||||
allow_headers="*",
|
|
||||||
allow_methods="*"
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
for route in list(self.app.router.routes()):
|
|
||||||
cors.add(route)
|
|
||||||
|
|
||||||
def setup_routes(self):
|
|
||||||
"""设置路由"""
|
|
||||||
login_handler = LoginHandler(self.config)
|
|
||||||
register_handler = RegisterHandler(self.config)
|
|
||||||
config_handler = ConfigHandler()
|
|
||||||
|
|
||||||
# API 路由
|
|
||||||
self.app.router.add_post('/api/login', login_handler.handle_login)
|
|
||||||
self.app.router.add_post('/api/register', register_handler.handle_register)
|
|
||||||
self.app.router.add_get('/api/config/devices', config_handler.get_private_configs)
|
|
||||||
self.app.router.add_post('/api/config/device', config_handler.save_device_config)
|
|
||||||
self.app.router.add_get('/api/config/module-options', config_handler.get_module_options)
|
|
||||||
self.app.router.add_post('/api/config/save_device_config', config_handler.save_device_config)
|
|
||||||
self.app.router.add_post('/api/config/delete_device', config_handler.delete_device_config)
|
|
||||||
|
|
||||||
# 添加静态文件服务
|
|
||||||
self.app.router.add_static('/assets/', path=os.path.join(self.static_path, 'assets'))
|
|
||||||
# 所有未匹配的路由都返回 index.html
|
|
||||||
self.app.router.add_get('/{tail:.*}', self.handle_static_files)
|
|
||||||
|
|
||||||
async def handle_static_files(self, request):
|
|
||||||
"""处理静态文件请求,支持SPA前端路由"""
|
|
||||||
index_file = os.path.join(self.static_path, 'index.html')
|
|
||||||
if os.path.exists(index_file):
|
|
||||||
return web.FileResponse(index_file)
|
|
||||||
return web.Response(status=404, text='Not found')
|
|
||||||
|
|
||||||
def run(self, host='0.0.0.0', port=8002):
|
|
||||||
"""运行服务器"""
|
|
||||||
local_ip = get_local_ip()
|
|
||||||
logger.info(f"WebUI server is running at http://{local_ip}:{port}")
|
|
||||||
web.run_app(self.app, host=host, port=port)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
webui = WebUI()
|
|
||||||
webui.run()
|
|
||||||
+74
-76
@@ -1,92 +1,90 @@
|
|||||||
import logging
|
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
|
import logging
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
from core.utils.util import get_local_ip, get_project_dir, check_password
|
from aiohttp_cors import setup as cors_setup, ResourceOptions
|
||||||
from manager.api.prompt import PromptApi
|
from core.utils.util import get_local_ip
|
||||||
from manager.api.auth import AuthApi
|
|
||||||
from aiohttp.web_middlewares import middleware
|
|
||||||
|
|
||||||
|
# 添加项目根目录到Python路径
|
||||||
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
root_dir = os.path.dirname(current_dir)
|
||||||
|
sys.path.append(root_dir)
|
||||||
|
|
||||||
|
from manager.api.login import LoginHandler
|
||||||
|
from manager.api.register import RegisterHandler
|
||||||
|
from manager.user_manager import UserManager
|
||||||
|
from manager.api.config import ConfigHandler
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class WebUI:
|
||||||
|
def __init__(self):
|
||||||
|
self.app = web.Application()
|
||||||
|
self.user_manager = UserManager()
|
||||||
|
|
||||||
@middleware
|
# 添加静态文件路径
|
||||||
async def cors_middleware(request, handler):
|
self.static_path = os.path.join(root_dir, 'manager', 'static', 'webui')
|
||||||
# 预检请求处理
|
|
||||||
if request.method == 'OPTIONS':
|
|
||||||
return web.Response(
|
|
||||||
status=204,
|
|
||||||
headers={
|
|
||||||
'Access-Control-Allow-Origin': '*',
|
|
||||||
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
|
|
||||||
'Access-Control-Allow-Headers': 'Content-Type, Authorization, Token',
|
|
||||||
'Access-Control-Max-Age': '86400',
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
# 创建配置字典
|
||||||
response = await handler(request)
|
self.config = {
|
||||||
except web.HTTPException as ex:
|
'users': self.user_manager.get_users(),
|
||||||
response = ex
|
'hash_password': self.user_manager.hash_password,
|
||||||
|
'save_user_data': self.user_manager.save_user_data,
|
||||||
|
'get_user': self.user_manager.get_user,
|
||||||
|
'update_user': self.user_manager.update_user
|
||||||
|
}
|
||||||
|
|
||||||
# 添加CORS头到所有响应
|
|
||||||
cors_headers = {
|
|
||||||
'Access-Control-Allow-Origin': '*',
|
|
||||||
'Access-Control-Expose-Headers': 'Content-Type, Authorization, Token',
|
|
||||||
'Vary': 'Origin' # 避免缓存问题
|
|
||||||
}
|
|
||||||
response.headers.update(cors_headers)
|
|
||||||
|
|
||||||
return response
|
|
||||||
|
|
||||||
|
|
||||||
class ConfigServer:
|
|
||||||
def __init__(self, config: dict):
|
|
||||||
self.config = config
|
|
||||||
self.app = web.Application(middlewares=[cors_middleware]) # 注册中间件
|
|
||||||
|
|
||||||
# 初始化接口处理器
|
|
||||||
self.prompt_handler = PromptApi(config)
|
|
||||||
self.auth_handler = AuthApi(config)
|
|
||||||
self.setup_routes()
|
self.setup_routes()
|
||||||
|
self.setup_cors()
|
||||||
|
|
||||||
|
def setup_cors(self):
|
||||||
|
"""设置CORS"""
|
||||||
|
cors = cors_setup(self.app, defaults={
|
||||||
|
"*": ResourceOptions(
|
||||||
|
allow_credentials=True,
|
||||||
|
expose_headers="*",
|
||||||
|
allow_headers="*",
|
||||||
|
allow_methods="*"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
for route in list(self.app.router.routes()):
|
||||||
|
cors.add(route)
|
||||||
|
|
||||||
def setup_routes(self):
|
def setup_routes(self):
|
||||||
# 注册prompt接口
|
"""设置路由"""
|
||||||
self.app.router.add_get('/api/prompt', self.prompt_handler.get_prompt)
|
login_handler = LoginHandler(self.config)
|
||||||
self.app.router.add_post('/api/prompt', self.prompt_handler.update_prompt)
|
register_handler = RegisterHandler(self.config)
|
||||||
|
config_handler = ConfigHandler()
|
||||||
|
|
||||||
# 注册auth接口
|
# API 路由
|
||||||
self.app.router.add_post('/api/login', self.auth_handler.login)
|
self.app.router.add_post('/api/login', login_handler.handle_login)
|
||||||
|
self.app.router.add_post('/api/register', register_handler.handle_register)
|
||||||
|
self.app.router.add_get('/api/config/devices', config_handler.get_private_configs)
|
||||||
|
self.app.router.add_post('/api/config/device', config_handler.save_device_config)
|
||||||
|
self.app.router.add_get('/api/config/module-options', config_handler.get_module_options)
|
||||||
|
self.app.router.add_post('/api/config/save_device_config', config_handler.save_device_config)
|
||||||
|
self.app.router.add_post('/api/config/delete_device', config_handler.delete_device_config)
|
||||||
|
|
||||||
# 注册静态文件路由
|
# 添加静态文件服务
|
||||||
static_dir = os.path.join(get_project_dir(), 'manager/static') # 获取static目录绝对路径
|
self.app.router.add_static('/assets/', path=os.path.join(self.static_path, 'assets'))
|
||||||
self.app.router.add_static(
|
# 所有未匹配的路由都返回 index.html
|
||||||
prefix='/manager/', # 匹配前缀
|
self.app.router.add_get('/{tail:.*}', self.handle_static_files)
|
||||||
path=static_dir, # 静态文件目录
|
|
||||||
name='static'
|
|
||||||
)
|
|
||||||
self.app.router.add_get('/manager', self.redirect_to_index)
|
|
||||||
|
|
||||||
async def redirect_to_index(self, _):
|
async def handle_static_files(self, request):
|
||||||
raise web.HTTPFound('/manager/')
|
"""处理静态文件请求,支持SPA前端路由"""
|
||||||
|
index_file = os.path.join(self.static_path, 'index.html')
|
||||||
|
if os.path.exists(index_file):
|
||||||
|
return web.FileResponse(index_file)
|
||||||
|
return web.Response(status=404, text='Not found')
|
||||||
|
|
||||||
async def start(self):
|
def run(self, host='0.0.0.0', port=8002):
|
||||||
try:
|
"""运行服务器"""
|
||||||
http_config = self.config['manager']
|
local_ip = get_local_ip()
|
||||||
if not http_config.get('enabled', False):
|
logger.info(f"WebUI server is running at http://{local_ip}:{port}")
|
||||||
logger.info("HTTP server is disabled")
|
web.run_app(self.app, host=host, port=port)
|
||||||
return
|
|
||||||
token = self.config['manager']['token']
|
|
||||||
if not check_password(token):
|
|
||||||
logger.info("您设置的后台密码太弱了,启动后台管理失败!")
|
|
||||||
return
|
|
||||||
|
|
||||||
runner = web.AppRunner(self.app)
|
if __name__ == '__main__':
|
||||||
await runner.setup()
|
webui = WebUI()
|
||||||
site = web.TCPSite(runner, http_config['ip'], http_config['port'])
|
webui.run()
|
||||||
await site.start()
|
|
||||||
logger.info(
|
|
||||||
f"Config HTTP server is running at http://{get_local_ip()}:{http_config['port']}/manager/login.html")
|
|
||||||
return runner # 返回runner以便后续清理
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Failed to start HTTP server: {e}")
|
|
||||||
raise
|
|
||||||
|
|||||||
Reference in New Issue
Block a user