support subpath

pull/357/head
zanllp 2024-03-15 04:13:18 +08:00
parent 4455ca9148
commit e543c58ffb
5 changed files with 70 additions and 57 deletions

10
app.py
View File

@ -44,7 +44,7 @@ def paths_check(paths):
if os.path.isabs(path):
abs_path = path
else:
abs_path = os.path.join(os.getcwd(), path)
abs_path = os.path.normpath(os.path.join(os.getcwd(), path))
if not os.path.exists(abs_path):
print(f"{tag} The path '{abs_path}' will be ignored (value: {path}).")
@ -75,7 +75,7 @@ class AppUtils:
allow_cors=False,
enable_shutdown=False,
sd_webui_dir: Optional[str] = None,
base="",
base: Optional[str]=None,
export_fe_fn=False,
):
"""
@ -88,6 +88,8 @@ class AppUtils:
self.allow_cors = allow_cors
self.enable_shutdown = enable_shutdown
self.sd_webui_dir = sd_webui_dir
if base and not base.startswith('/'):
base = '/' + base
self.base = base
self.export_fe_fn = export_fe_fn
if sd_webui_dir:
@ -138,7 +140,7 @@ class AppUtils:
allow_cors=self.allow_cors,
enable_shutdown=self.enable_shutdown,
launch_mode="server",
base=self.base,
base= self.base,
export_fe_fn=self.export_fe_fn,
)
@ -151,7 +153,7 @@ class AppUtils:
# 用于在首页显示
@app.get("/")
def index():
if self.base and self.base != DEFAULT_BASE:
if isinstance(self.base, str):
with open(index_html_path, "r", encoding="utf-8") as file:
content = file.read().replace(DEFAULT_BASE, self.base)
return Response(content=content, media_type="text/html")

View File

@ -23,7 +23,7 @@ Promise.resolve().then(async () => {
</body>
</html>
`
`.replace(/\/infinite_image_browsing/g, (window.location.pathname + '/infinite_image_browsing').replace(/\/\//g, '/'))
let containerSelector = '#infinite_image_browsing_container_wrapper'
let shouldMaximize = true

View File

@ -96,8 +96,9 @@ async def verify_secret(request: Request):
DEFAULT_BASE = "/infinite_image_browsing"
def infinite_image_browsing_api(app: FastAPI, **kwargs):
pre = "/infinite_image_browsing"
api_base = kwargs.get("base") if isinstance(kwargs.get("base"), str) else DEFAULT_BASE
fe_public_path = kwargs.get("fe_public_path") if isinstance(kwargs.get("fe_public_path"), str) else api_base
# print(f"IIB api_base:{api_base} fe_public_path:{fe_public_path}")
if IIB_DEBUG:
@app.exception_handler(Exception)
async def exception_handler(request: Request, exc: Exception):
@ -133,7 +134,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
f"An exception occurred while processing {request.method} {request.url}: {exc}"
)
pre = kwargs.get("base") or DEFAULT_BASE
if kwargs.get("allow_cors"):
app.add_middleware(
CORSMiddleware,
@ -237,22 +238,13 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
def filter_allowed_files(files: List[FileInfoDict]):
return [x for x in files if is_path_trusted(x["fullpath"])]
static_dir = f"{cwd}/vue/dist"
@app.get(pre + "/fe-static/{file_path:path}")
async def serve_static_file(file_path: str):
file_full_path = f"{static_dir}/{file_path}"
if file_path.endswith(".js"):
with open(file_full_path, "r", encoding="utf-8") as file:
content = file.read().replace(DEFAULT_BASE, pre)
return Response(content=content, media_type="text/javascript")
else:
return FileResponse(file_full_path)
@app.get(f"{pre}/hello")
@app.get(f"{api_base}/hello")
async def greeting():
return "hello"
@app.get(f"{pre}/global_setting", dependencies=[Depends(verify_secret)])
@app.get(f"{api_base}/global_setting", dependencies=[Depends(verify_secret)])
async def global_setting():
all_custom_tags = []
@ -284,7 +276,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
file_paths: List[str]
@app.post(
pre + "/delete_files",
api_base + "/delete_files",
dependencies=[Depends(verify_secret), Depends(write_permission_required)],
)
async def delete_files(req: DeleteFilesReq):
@ -325,7 +317,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
dest_folder: str
@app.post(
pre + "/mkdirs",
api_base + "/mkdirs",
dependencies=[Depends(verify_secret), Depends(write_permission_required)],
)
async def create_folders(req: CreateFoldersReq):
@ -340,7 +332,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
create_dest_folder: Optional[bool] = False
@app.post(
pre + "/copy_files",
api_base + "/copy_files",
dependencies=[Depends(verify_secret), Depends(write_permission_required)],
)
async def copy_files(req: MoveFilesReq):
@ -360,7 +352,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
raise HTTPException(400, detail=error_msg)
@app.post(
pre + "/move_files",
api_base + "/move_files",
dependencies=[Depends(verify_secret), Depends(write_permission_required)],
)
async def move_files(req: MoveFilesReq):
@ -394,7 +386,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
)
raise HTTPException(400, detail=error_msg)
@app.get(pre + "/files", dependencies=[Depends(verify_secret)])
@app.get(api_base + "/files", dependencies=[Depends(verify_secret)])
async def get_target_folder_files(folder_path: str):
files: List[FileInfoDict] = []
try:
@ -450,7 +442,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
return {"files": filter_allowed_files(files)}
@app.get(pre + "/image-thumbnail", dependencies=[Depends(verify_secret)])
@app.get(api_base + "/image-thumbnail", dependencies=[Depends(verify_secret)])
async def thumbnail(path: str, t: str, size: str = "256x256"):
check_path_trust(path)
if not temp_path:
@ -483,7 +475,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
headers={"Cache-Control": "max-age=31536000", "ETag": hash},
)
@app.get(pre + "/file", dependencies=[Depends(verify_secret)])
@app.get(api_base + "/file", dependencies=[Depends(verify_secret)])
async def get_file(path: str, t: str, disposition: Optional[str] = None):
filename = path
import mimetypes
@ -516,12 +508,12 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
headers=headers,
)
@app.post(pre + "/send_img_path", dependencies=[Depends(verify_secret)])
@app.post(api_base + "/send_img_path", dependencies=[Depends(verify_secret)])
async def api_set_send_img_path(path: str):
send_img_path["value"] = path
# 等待图片信息生成完成
@app.get(pre + "/gen_info_completed", dependencies=[Depends(verify_secret)])
@app.get(api_base + "/gen_info_completed", dependencies=[Depends(verify_secret)])
async def api_set_send_img_path():
for _ in range(30): # timeout 3s
if send_img_path["value"] == "": # 等待setup里面生成完成
@ -531,7 +523,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
await asyncio.sleep(0.1)
return send_img_path["value"] == ""
@app.get(pre + "/image_geninfo", dependencies=[Depends(verify_secret)])
@app.get(api_base + "/image_geninfo", dependencies=[Depends(verify_secret)])
async def image_geninfo(path: str):
with Image.open(path) as img:
if is_img_created_by_comfyui(img):
@ -551,7 +543,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
class GeninfoBatchReq(BaseModel):
paths: List[str]
@app.post(pre + "/image_geninfo_batch", dependencies=[Depends(verify_secret)])
@app.post(api_base + "/image_geninfo_batch", dependencies=[Depends(verify_secret)])
async def image_geninfo_batch(req: GeninfoBatchReq):
res = {}
for path in req.paths:
@ -562,7 +554,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
class CheckPathExistsReq(BaseModel):
paths: List[str]
@app.post(pre + "/check_path_exists", dependencies=[Depends(verify_secret)])
@app.post(api_base + "/check_path_exists", dependencies=[Depends(verify_secret)])
async def check_path_exists(req: CheckPathExistsReq):
update_all_scanned_paths()
res = {}
@ -570,13 +562,24 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
res[path] = os.path.exists(path) and is_path_trusted(path)
return res
@app.get(pre)
@app.get(api_base)
def index_bd():
if pre != DEFAULT_BASE:
if fe_public_path:
with open(index_html_path, "r", encoding="utf-8") as file:
content = file.read().replace(DEFAULT_BASE, pre)
content = file.read().replace(DEFAULT_BASE, fe_public_path)
return Response(content=content, media_type="text/html")
return FileResponse(index_html_path)
static_dir = f"{cwd}/vue/dist"
@app.get(api_base + "/fe-static/{file_path:path}")
async def serve_static_file(file_path: str):
file_full_path = f"{static_dir}/{file_path}"
if file_path.endswith(".js"):
with open(file_full_path, "r", encoding="utf-8") as file:
content = file.read().replace(DEFAULT_BASE, fe_public_path)
return Response(content=content, media_type="text/javascript")
else:
return FileResponse(file_full_path)
class PathsReq(BaseModel):
paths: List[str]
@ -585,7 +588,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
path: str
@app.post(
pre + "/open_folder",
api_base + "/open_folder",
dependencies=[Depends(verify_secret), Depends(write_permission_required)],
)
def open_folder_using_explore(req: OpenFolderReq):
@ -593,7 +596,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
raise HTTPException(status_code=403)
open_folder(*os.path.split(req.path))
@app.post(pre + "/shutdown")
@app.post(api_base + "/shutdown")
async def shutdown_app():
# This API endpoint is mainly used as a sidecar in Tauri applications to shut down the application
if not kwargs.get("enable_shutdown"):
@ -602,7 +605,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
return {"message": "Application is shutting down."}
@app.post(
pre + "/zip",
api_base + "/zip",
dependencies=[Depends(verify_secret), Depends(write_permission_required)],
)
def zip_files(req: PathsReq):
@ -614,9 +617,9 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
create_zip_file(req.paths, file_path)
return FileResponse(file_path, media_type="application/zip")
db_pre = pre + "/db"
db_api_base = api_base + "/db"
@app.get(db_pre + "/basic_info", dependencies=[Depends(verify_secret)])
@app.get(db_api_base + "/basic_info", dependencies=[Depends(verify_secret)])
async def get_db_basic_info():
conn = DataBase.get_conn()
img_count = DbImg.count(conn)
@ -629,7 +632,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
"expired_dirs": expired_dirs,
}
@app.get(db_pre + "/expired_dirs", dependencies=[Depends(verify_secret)])
@app.get(db_api_base + "/expired_dirs", dependencies=[Depends(verify_secret)])
async def get_db_expired():
conn = DataBase.get_conn()
expired_dirs = Folder.get_expired_dirs(conn)
@ -639,7 +642,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
}
@app.post(
db_pre + "/update_image_data",
db_api_base + "/update_image_data",
dependencies=[Depends(verify_secret)],
)
async def update_image_db_data():
@ -665,7 +668,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
folder_paths: List[str] = None
size: Optional[int] = 200
@app.post(db_pre + "/search_by_substr", dependencies=[Depends(verify_secret)])
@app.post(db_api_base + "/search_by_substr", dependencies=[Depends(verify_secret)])
async def search_by_substr(req: SearchBySubstrReq):
if IIB_DEBUG:
logger.info(req)
@ -694,7 +697,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
folder_paths: List[str] = None
size: Optional[int] = 200
@app.post(db_pre + "/match_images_by_tags", dependencies=[Depends(verify_secret)])
@app.post(db_api_base + "/match_images_by_tags", dependencies=[Depends(verify_secret)])
async def match_image_by_tags(req: MatchImagesByTagsReq):
if IIB_DEBUG:
logger.info(req)
@ -714,7 +717,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
"cursor": next_cursor
}
@app.get(db_pre + "/img_selected_custom_tag", dependencies=[Depends(verify_secret)])
@app.get(db_api_base + "/img_selected_custom_tag", dependencies=[Depends(verify_secret)])
async def get_img_selected_custom_tag(path: str):
path = os.path.normpath(path)
if not is_valid_image_path(path):
@ -733,7 +736,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
# tags = Tag.get_all_custom_tag()
return ImageTag.get_tags_for_image(conn, img.id, type="custom")
@app.post(db_pre + "/get_image_tags", dependencies=[Depends(verify_secret)])
@app.post(db_api_base + "/get_image_tags", dependencies=[Depends(verify_secret)])
async def get_img_tags(req: PathsReq):
conn = DataBase.get_conn()
return ImageTag.batch_get_tags_by_path(conn, req.paths)
@ -743,7 +746,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
tag_id: int
@app.post(
db_pre + "/toggle_custom_tag_to_img",
db_api_base + "/toggle_custom_tag_to_img",
dependencies=[Depends(verify_secret), Depends(write_permission_required)],
)
async def toggle_custom_tag_to_img(req: ToggleCustomTagToImgReq):
@ -786,7 +789,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
tag_id: int
@app.post(
db_pre + "/batch_update_image_tag",
db_api_base + "/batch_update_image_tag",
dependencies=[Depends(verify_secret), Depends(write_permission_required)],
)
async def batch_update_image_tag(req: BatchUpdateImageReq):
@ -828,7 +831,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
tag_name: str
@app.post(
db_pre + "/add_custom_tag",
db_api_base + "/add_custom_tag",
dependencies=[Depends(verify_secret), Depends(write_permission_required)],
)
async def add_custom_tag(req: AddCustomTagReq):
@ -841,7 +844,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
tag_id: str
@app.post(
db_pre + "/remove_custom_tag",
db_api_base + "/remove_custom_tag",
dependencies=[Depends(verify_secret), Depends(write_permission_required)],
)
async def remove_custom_tag(req: RemoveCustomTagReq):
@ -854,7 +857,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
tag_id: str
@app.post(
db_pre + "/remove_custom_tag_from_img",
db_api_base + "/remove_custom_tag_from_img",
dependencies=[Depends(verify_secret), Depends(write_permission_required)],
)
async def remove_custom_tag_from_img(req: RemoveCustomTagFromReq):
@ -869,7 +872,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
type: Optional[ExtraPathType]
@app.post(
f"{db_pre}/extra_paths",
f"{db_api_base}/extra_paths",
dependencies=[Depends(verify_secret), Depends(write_permission_required)],
)
async def create_extra_path(extra_path: ExtraPathModel):
@ -884,7 +887,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
conn.commit()
@app.get(
f"{db_pre}/extra_paths",
f"{db_api_base}/extra_paths",
dependencies=[Depends(verify_secret)],
)
async def read_extra_paths():
@ -892,7 +895,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
return ExtraPath.get_extra_paths(conn)
@app.delete(
f"{db_pre}/extra_paths",
f"{db_api_base}/extra_paths",
dependencies=[Depends(verify_secret), Depends(write_permission_required)],
)
async def delete_extra_path(extra_path: ExtraPathModel):
@ -902,7 +905,7 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
@app.post(
f"{db_pre}/rebuild_index",
f"{db_api_base}/rebuild_index",
dependencies=[Depends(verify_secret), Depends(write_permission_required)],
)
async def rebuild_index():

View File

@ -7,6 +7,7 @@ from scripts.iib.logger import logger
from fastapi import FastAPI
import gradio as gr
from modules.shared import cmd_opts
"""
api函数声明和启动分离方便另外一边被外部调用
@ -71,7 +72,14 @@ def on_ui_tabs():
def on_app_started(_: gr.Blocks, app: FastAPI) -> None:
# 第一个参数是SD-WebUI传进来的gr.Blocks但是不需要使用
infinite_image_browsing_api(app)
DEFAULT_BASE = "/infinite_image_browsing"
fe_public_path = None
subpath = vars(cmd_opts).get("subpath")
if subpath:
base = "/" + subpath + "/" + DEFAULT_BASE
fe_public_path = base.replace('//', '/')
infinite_image_browsing_api(app, fe_public_path = fe_public_path)
script_callbacks.on_ui_tabs(on_ui_tabs)

View File

@ -3,7 +3,7 @@ Promise.resolve().then(async () => {
* This is a file generated using `yarn build`.
* If you want to make changes, please modify `index.tpl.js` and run the command to generate it again.
*/
const html = `__built_html__`
const html = `__built_html__`.replace(/\/infinite_image_browsing/g, (window.location.pathname + '/infinite_image_browsing').replace(/\/\//g, '/'))
let containerSelector = '#infinite_image_browsing_container_wrapper'
let shouldMaximize = true