feat: 优化后台网络设置,同时支持ipv4和ipv6

This commit is contained in:
涵曦 2024-07-14 07:24:04 +00:00
parent 514bf9b8b2
commit 6d7d90d642
2 changed files with 57 additions and 30 deletions

View File

@ -77,7 +77,7 @@ def main():
xiaomusic = XiaoMusic(config) xiaomusic = XiaoMusic(config)
HttpInit(xiaomusic) HttpInit(xiaomusic)
uvicorn.run(HttpApp, host="0.0.0.0", port=config.port) uvicorn.run(HttpApp, host=["::", "0.0.0.0"], port=config.port)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,8 +1,10 @@
import asyncio import asyncio
import json import json
import os import os
import secrets
from contextlib import asynccontextmanager from contextlib import asynccontextmanager
from dataclasses import asdict from dataclasses import asdict
from typing import Annotated
from fastapi import Depends, FastAPI, HTTPException, Request, status from fastapi import Depends, FastAPI, HTTPException, Request, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials from fastapi.security import HTTPBasic, HTTPBasicCredentials
@ -29,10 +31,49 @@ async def app_lifespan(app):
task.cancel() task.cancel()
app = FastAPI(lifespan=app_lifespan)
security = HTTPBasic() security = HTTPBasic()
def verification(
credentials: Annotated[HTTPBasicCredentials, Depends(security)],
):
current_username_bytes = credentials.username.encode("utf8")
correct_username_bytes = config.httpauth_username.encode("utf8")
is_correct_username = secrets.compare_digest(
current_username_bytes, correct_username_bytes
)
current_password_bytes = credentials.password.encode("utf8")
correct_password_bytes = config.httpauth_password.encode("utf8")
is_correct_password = secrets.compare_digest(
current_password_bytes, correct_password_bytes
)
if not (is_correct_username and is_correct_password):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
headers={"WWW-Authenticate": "Basic"},
)
return True
def no_verification():
return True
app = FastAPI(
lifespan=app_lifespan,
version=__version__,
dependencies=[Depends(verification)],
)
def reset_dependency():
if not config.disable_httpauth:
app.dependency_overrides[verification] = no_verification
else:
app.dependency_overrides = {}
def HttpInit(_xiaomusic): def HttpInit(_xiaomusic):
global xiaomusic, config, log global xiaomusic, config, log
xiaomusic = _xiaomusic xiaomusic = _xiaomusic
@ -41,22 +82,7 @@ def HttpInit(_xiaomusic):
app.mount("/static", StaticFiles(directory="xiaomusic/static"), name="static") app.mount("/static", StaticFiles(directory="xiaomusic/static"), name="static")
app.mount("/music", StaticFiles(directory=config.music_path), name="music") app.mount("/music", StaticFiles(directory=config.music_path), name="music")
reset_dependency()
def verification(creds: HTTPBasicCredentials = Depends(security)):
username = creds.username
password = creds.password
if config.disable_httpauth:
return True
if config.httpauth_username == username and config.httpauth_password == password:
return True
else:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect email or password",
headers={"WWW-Authenticate": "Basic"},
)
@app.get("/") @app.get("/")
@ -71,7 +97,7 @@ def getversion():
@app.get("/getvolume") @app.get("/getvolume")
async def getvolume(did: str = "", Verifcation=Depends(verification)): async def getvolume(did: str = ""):
if not xiaomusic.did_exist(did): if not xiaomusic.did_exist(did):
return {"volume": 0} return {"volume": 0}
@ -85,7 +111,7 @@ class DidVolume(BaseModel):
@app.post("/setvolume") @app.post("/setvolume")
async def setvolume(data: DidVolume, Verifcation=Depends(verification)): async def setvolume(data: DidVolume):
did = data.did did = data.did
volume = data.volume volume = data.volume
if not xiaomusic.did_exist(did): if not xiaomusic.did_exist(did):
@ -97,12 +123,12 @@ async def setvolume(data: DidVolume, Verifcation=Depends(verification)):
@app.get("/searchmusic") @app.get("/searchmusic")
def searchmusic(name: str = "", Verifcation=Depends(verification)): def searchmusic(name: str = ""):
return xiaomusic.searchmusic(name) return xiaomusic.searchmusic(name)
@app.get("/playingmusic") @app.get("/playingmusic")
def playingmusic(did: str = "", Verifcation=Depends(verification)): def playingmusic(did: str = ""):
if not xiaomusic.did_exist(did): if not xiaomusic.did_exist(did):
return {"ret": "Did not exist"} return {"ret": "Did not exist"}
@ -121,7 +147,7 @@ class DidCmd(BaseModel):
@app.post("/cmd") @app.post("/cmd")
async def do_cmd(data: DidCmd, Verifcation=Depends(verification)): async def do_cmd(data: DidCmd):
did = data.did did = data.did
cmd = data.cmd cmd = data.cmd
log.info(f"docmd. did:{did} cmd:{cmd}") log.info(f"docmd. did:{did} cmd:{cmd}")
@ -135,7 +161,7 @@ async def do_cmd(data: DidCmd, Verifcation=Depends(verification)):
@app.get("/getsetting") @app.get("/getsetting")
async def getsetting(need_device_list: bool = False, Verifcation=Depends(verification)): async def getsetting(need_device_list: bool = False):
config = xiaomusic.getconfig() config = xiaomusic.getconfig()
data = asdict(config) data = asdict(config)
if need_device_list: if need_device_list:
@ -146,13 +172,14 @@ async def getsetting(need_device_list: bool = False, Verifcation=Depends(verific
@app.post("/savesetting") @app.post("/savesetting")
async def savesetting(request: Request, Verifcation=Depends(verification)): async def savesetting(request: Request):
try: try:
data_json = await request.body() data_json = await request.body()
data = json.loads(data_json.decode("utf-8")) data = json.loads(data_json.decode("utf-8"))
debug_data = deepcopy_data_no_sensitive_info(data) debug_data = deepcopy_data_no_sensitive_info(data)
log.info(f"saveconfig: {debug_data}") log.info(f"saveconfig: {debug_data}")
await xiaomusic.saveconfig(data) await xiaomusic.saveconfig(data)
reset_dependency()
return "save success" return "save success"
except json.JSONDecodeError as err: except json.JSONDecodeError as err:
raise HTTPException(status_code=400, detail="Invalid JSON") from err raise HTTPException(status_code=400, detail="Invalid JSON") from err
@ -164,7 +191,7 @@ async def musiclist(Verifcation=Depends(verification)):
@app.get("/curplaylist") @app.get("/curplaylist")
async def curplaylist(did: str = "", Verifcation=Depends(verification)): async def curplaylist(did: str = ""):
if not xiaomusic.did_exist(did): if not xiaomusic.did_exist(did):
return "" return ""
return xiaomusic.get_cur_play_list(did) return xiaomusic.get_cur_play_list(did)
@ -175,7 +202,7 @@ class MusicItem(BaseModel):
@app.post("/delmusic") @app.post("/delmusic")
def delmusic(data: MusicItem, Verifcation=Depends(verification)): def delmusic(data: MusicItem):
log.info(data) log.info(data)
xiaomusic.del_music(data.name) xiaomusic.del_music(data.name)
return "success" return "success"
@ -186,7 +213,7 @@ class UrlInfo(BaseModel):
@app.post("/downloadjson") @app.post("/downloadjson")
async def downloadjson(data: UrlInfo, Verifcation=Depends(verification)): async def downloadjson(data: UrlInfo):
log.info(data) log.info(data)
url = data.url url = data.url
content = "" content = ""
@ -212,7 +239,7 @@ def downloadlog(Verifcation=Depends(verification)):
@app.get("/playurl") @app.get("/playurl")
async def playurl(did: str, url: str, Verifcation=Depends(verification)): async def playurl(did: str, url: str):
if not xiaomusic.did_exist(did): if not xiaomusic.did_exist(did):
return {"ret": "Did not exist"} return {"ret": "Did not exist"}
@ -223,7 +250,7 @@ async def playurl(did: str, url: str, Verifcation=Depends(verification)):
@app.post("/debug_play_by_music_url") @app.post("/debug_play_by_music_url")
async def debug_play_by_music_url(request: Request, Verifcation=Depends(verification)): async def debug_play_by_music_url(request: Request):
try: try:
data = await request.body() data = await request.body()
data_dict = json.loads(data.decode("utf-8")) data_dict = json.loads(data.decode("utf-8"))