feat(api): add virtual_path field on fs/list and fs/get responses

The existing `path` field on ObjResp/ObjLabelResp returns whatever the
storage driver writes into model.Object.Path, and that contract has
quietly diverged across drivers:

- Local sets it to the physical disk path
  (e.g. `/data/data/com.termux/files/home/storage/download/foo.tar.gz`)
- Cloud drivers (Quark / Baidu / 115 / …) leave it empty
- Some other drivers fill it with their own internal id-like path

Clients that need the canonical alist virtual path (e.g. for `share`,
`fs/copy`, navigation) cannot rely on `path` alone. The frontend has
been working around this with branchy code such as
`pathJoin(getCurrentPath(), name)` in some places and
`obj.path` in others; one such mismatch caused a share regression on
Local mounts whose root_folder_path differs from the mount path
(visible as `failed get storage: storage not found; rawPath: ...`).

Add a `virtual_path` field that is always the alist virtual path for
the object:

- `toObjsResp`  -> `FixAndCleanPath(stdpath.Join(parent, obj.Name))`
- `FsGet`       -> `FixAndCleanPath(reqPath)`

`path` is left untouched for backwards compatibility. Clients should
prefer `virtual_path` for anything that talks to other alist APIs.
This commit is contained in:
okatu-loli 2026-05-29 10:33:43 +08:00
parent f4445c56c6
commit e36c68e4db

View File

@ -35,6 +35,7 @@ type DirReq struct {
type ObjResp struct {
Id string `json:"id"`
Path string `json:"path"`
VirtualPath string `json:"virtual_path"`
Name string `json:"name"`
Size int64 `json:"size"`
IsDir bool `json:"is_dir"`
@ -65,6 +66,7 @@ type FsListResp struct {
type ObjLabelResp struct {
Id string `json:"id"`
Path string `json:"path"`
VirtualPath string `json:"virtual_path"`
Name string `json:"name"`
Size int64 `json:"size"`
IsDir bool `json:"is_dir"`
@ -318,6 +320,7 @@ func toObjsResp(objs []model.Obj, parent string, encrypt bool) []ObjLabelResp {
resp = append(resp, ObjLabelResp{
Id: obj.GetID(),
Path: obj.GetPath(),
VirtualPath: utils.FixAndCleanPath(stdpath.Join(parent, obj.GetName())),
Name: obj.GetName(),
Size: obj.GetSize(),
IsDir: obj.IsDir(),
@ -452,6 +455,7 @@ func FsGet(c *gin.Context) {
ObjResp: ObjResp{
Id: obj.GetID(),
Path: obj.GetPath(),
VirtualPath: utils.FixAndCleanPath(reqPath),
Name: obj.GetName(),
Size: obj.GetSize(),
IsDir: obj.IsDir(),