mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2025-12-14 10:10:29 +08:00
添加网页根目录、网站地址和端口的配置选项
This commit is contained in:
parent
d5a0b1a8b3
commit
9a29dc6c2e
@ -353,6 +353,9 @@ def _get_config_scheme() -> dict:
|
||||
"heartbeat": Option(15.0, type=valid_float_f01),
|
||||
"access_log_format": Option("[%P / %{X-Real-IP}i] '%r' => %s; size=%b ---"
|
||||
" referer='%{Referer}i'; user_agent='%{User-Agent}i'"),
|
||||
"web_path": Option("/usr/share/kvmd/web", type=valid_abs_path),
|
||||
"host": Option("127.0.0.1", type=valid_ip_or_host),
|
||||
"port": Option(8080, type=valid_port),
|
||||
},
|
||||
|
||||
"auth": {
|
||||
|
||||
@ -103,6 +103,9 @@ def main(argv: (list[str] | None)=None) -> None:
|
||||
),
|
||||
|
||||
keymap_path=config.hid.keymap,
|
||||
web_path=config.server.web_path,
|
||||
host=config.server.host,
|
||||
port=config.server.port,
|
||||
|
||||
stream_forever=config.streamer.forever,
|
||||
).run(**config.server._unpack())
|
||||
|
||||
@ -19,19 +19,8 @@
|
||||
# #
|
||||
# ========================================================================== #
|
||||
|
||||
|
||||
import os
|
||||
from aiohttp import ClientConnectionError, ClientSession
|
||||
from aiohttp import UnixConnector
|
||||
from aiohttp.web import Request
|
||||
from aiohttp.web import Response
|
||||
from aiohttp.web import HTTPForbidden
|
||||
from aiohttp.web import HTTPNotFound
|
||||
from aiohttp.web import FileResponse
|
||||
from aiohttp.web import HTTPInternalServerError
|
||||
|
||||
from aiohttp.web import StreamResponse
|
||||
from urllib.parse import urlparse, urlunparse, parse_qs, urlencode
|
||||
|
||||
from ....htserver import exposed_http
|
||||
from ....htserver import make_json_response
|
||||
@ -45,12 +34,9 @@ from ..info import InfoManager
|
||||
class InfoApi:
|
||||
def __init__(self, info_manager: InfoManager) -> None:
|
||||
self.__info_manager = info_manager
|
||||
self.static_dir = 'kvmd_data/usr/share/kvmd/web'
|
||||
self.target_stream_server = 'http://127.0.0.1:8081'
|
||||
|
||||
# =====
|
||||
|
||||
|
||||
@exposed_http("GET", "/api/info")
|
||||
async def __common_state_handler(self, req: Request) -> Response:
|
||||
fields = self.__valid_info_fields(req)
|
||||
@ -62,52 +48,3 @@ class InfoApi:
|
||||
arg=req.query.get("fields", ",".join(available)),
|
||||
variants=available,
|
||||
) or available)
|
||||
|
||||
@exposed_http("GET", "/streamer/stream")
|
||||
async def proxy_stream_handler(self, request):
|
||||
socket_path = '/home/mofeng/One-KVM/kvmd_data/run/kvmd/ustreamer.sock'
|
||||
query_string = urlencode(request.query)
|
||||
headers = request.headers.copy()
|
||||
try:
|
||||
async with ClientSession(connector=UnixConnector(path=socket_path)) as session:
|
||||
backend_url = f'http://localhost/stream?{query_string}' if query_string else 'http://localhost/stream'
|
||||
async with session.get(backend_url, headers=headers) as resp:
|
||||
response = StreamResponse(status=resp.status, reason=resp.reason, headers=resp.headers)
|
||||
await response.prepare(request)
|
||||
while True:
|
||||
chunk = await resp.content.read(512000)
|
||||
if not chunk:
|
||||
break
|
||||
await response.write(chunk)
|
||||
return response
|
||||
except ClientConnectionError:
|
||||
return Response(status=500, text="Client connection was closed")
|
||||
|
||||
|
||||
@exposed_http("GET", "/{path:.*}", auth_required=False)
|
||||
async def __html_file_handler(self, req: Request) -> Response:
|
||||
path = req.match_info['path']
|
||||
full_path = os.path.normpath(os.path.join(self.static_dir, path))
|
||||
print("---------------")
|
||||
print(full_path)
|
||||
|
||||
# 安全检查:确保请求的文件在允许的基础目录内
|
||||
if not full_path.startswith(self.static_dir):
|
||||
raise HTTPForbidden(text="Access denied.")
|
||||
|
||||
if os.path.isdir(full_path):
|
||||
index_path = os.path.join(full_path, 'index.html')
|
||||
if os.path.isfile(index_path):
|
||||
full_path = index_path
|
||||
else:
|
||||
raise HTTPNotFound(text="Directory does not contain an index.html file.")
|
||||
|
||||
# 检查调整后的路径是否为现有文件
|
||||
if not (os.path.exists(full_path) and os.path.isfile(full_path)):
|
||||
raise HTTPNotFound(text="File not found.")
|
||||
|
||||
try:
|
||||
return FileResponse(full_path)
|
||||
except IOError as e:
|
||||
raise HTTPInternalServerError(text=str(e))
|
||||
|
||||
@ -30,6 +30,18 @@ from typing import Any
|
||||
from aiohttp.web import Request
|
||||
from aiohttp.web import Response
|
||||
from aiohttp.web import WebSocketResponse
|
||||
from aiohttp.web import HTTPForbidden
|
||||
from aiohttp.web import HTTPNotFound
|
||||
from aiohttp.web import FileResponse
|
||||
from aiohttp.web import HTTPInternalServerError
|
||||
from aiohttp.web import StreamResponse
|
||||
|
||||
import os
|
||||
from aiohttp import ClientConnectionError
|
||||
from aiohttp import ClientSession
|
||||
from aiohttp import UnixConnector
|
||||
from urllib.parse import urlencode
|
||||
|
||||
|
||||
from ... import __version__
|
||||
|
||||
@ -153,7 +165,9 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
|
||||
snapshoter: Snapshoter,
|
||||
|
||||
keymap_path: str,
|
||||
|
||||
web_path: str,
|
||||
host: str,
|
||||
port: int,
|
||||
stream_forever: bool,
|
||||
) -> None:
|
||||
|
||||
@ -194,6 +208,9 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
|
||||
self.__streamer_notifier = aiotools.AioNotifier()
|
||||
self.__reset_streamer = False
|
||||
self.__new_streamer_params: dict = {}
|
||||
self.__web_path = web_path
|
||||
self.__host = host
|
||||
self.__port = port
|
||||
|
||||
# ===== STREAMER CONTROLLER
|
||||
|
||||
@ -306,6 +323,53 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
|
||||
self._get_wss(),
|
||||
)))
|
||||
|
||||
# ===== WEB TASKS
|
||||
@exposed_http("GET", "/streamer/stream")
|
||||
async def proxy_stream_handler(self, request):
|
||||
socket_path = self.__streamer.get_path()
|
||||
query_string = urlencode(request.query)
|
||||
headers = request.headers.copy()
|
||||
try:
|
||||
async with ClientSession(connector=UnixConnector(path=socket_path)) as session:
|
||||
backend_url = f'http://localhost/stream?{query_string}' if query_string else 'http://localhost/stream'
|
||||
async with session.get(backend_url, headers=headers) as resp:
|
||||
response = StreamResponse(status=resp.status, reason=resp.reason, headers=resp.headers)
|
||||
await response.prepare(request)
|
||||
while True:
|
||||
chunk = await resp.content.read(512000)
|
||||
if not chunk:
|
||||
break
|
||||
await response.write(chunk)
|
||||
return response
|
||||
except ClientConnectionError:
|
||||
return Response(status=500, text="Client connection was closed")
|
||||
|
||||
|
||||
@exposed_http("GET", "/{path:.*}", auth_required=False)
|
||||
async def __html_file_handler(self, req: Request) -> Response:
|
||||
path = req.match_info['path']
|
||||
if not os.path.exists(self.__web_path):
|
||||
raise HTTPNotFound(text="Web root directory not found.")
|
||||
full_path = os.path.normpath(os.path.join(self.__web_path, path))
|
||||
|
||||
if not full_path.startswith(self.__web_path):
|
||||
raise HTTPForbidden(text="Access denied.")
|
||||
|
||||
if os.path.isdir(full_path):
|
||||
index_path = os.path.join(full_path, 'index.html')
|
||||
if os.path.isfile(index_path):
|
||||
full_path = index_path
|
||||
else:
|
||||
raise HTTPNotFound(text="404 Not Found")
|
||||
|
||||
if not (os.path.exists(full_path) and os.path.isfile(full_path)):
|
||||
raise HTTPNotFound(text="404 Not Found")
|
||||
|
||||
try:
|
||||
return FileResponse(full_path)
|
||||
except IOError as e:
|
||||
raise HTTPInternalServerError(text=str(e))
|
||||
|
||||
# ===== SYSTEM TASKS
|
||||
|
||||
async def __stream_controller(self) -> None:
|
||||
|
||||
@ -272,6 +272,8 @@ class Streamer: # pylint: disable=too-many-instance-attributes
|
||||
def get_params(self) -> dict:
|
||||
return self.__params.get_params()
|
||||
|
||||
def get_path(self) -> str:
|
||||
return self.__unix_path
|
||||
# =====
|
||||
|
||||
async def get_state(self) -> dict:
|
||||
|
||||
@ -288,12 +288,12 @@ class HttpServer:
|
||||
unix_mode: int,
|
||||
heartbeat: float,
|
||||
access_log_format: str,
|
||||
web_path: str,
|
||||
host: str,
|
||||
port: int,
|
||||
) -> None:
|
||||
|
||||
self.__ws_heartbeat = heartbeat
|
||||
# 默认绑定到所有地址
|
||||
host = '0.0.0.0'
|
||||
port = 8080
|
||||
#if unix_rm and os.path.exists(unix_path):
|
||||
#os.remove(unix_path)
|
||||
#server_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
|
||||
@ -17,8 +17,9 @@ kvmd:
|
||||
|
||||
server:
|
||||
unix: kvmd_data/run/kvmd/kvmd.sock
|
||||
#unix_mode: 432
|
||||
#unix_rm: true
|
||||
web_path: kvmd_data/usr/share/kvmd/web
|
||||
host: 0.0.0.0
|
||||
port: 8080
|
||||
|
||||
atx:
|
||||
type: disabled
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user