Skip to content

Commit f454733

Browse files
fwerkorcodex
andauthored
fix(drivers/webdav): normalize missing path error (#2611)
Normalize WebDAV 404 responses from `Stat` to `errs.ObjectNotFound`. This fixes the mkdir pre-check path: when the target folder does not exist, `op.MakeDir` can now treat the lookup as a normal missing object and continue to issue `MKCOL` through the WebDAV driver. Co-authored-by: ChatGPT <noreply@openai.com>
1 parent dcfefce commit f454733

2 files changed

Lines changed: 93 additions & 0 deletions

File tree

drivers/webdav/driver.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
"github.com/OpenListTeam/OpenList/v4/drivers/base"
1212
"github.com/OpenListTeam/OpenList/v4/internal/driver"
13+
"github.com/OpenListTeam/OpenList/v4/internal/errs"
1314
"github.com/OpenListTeam/OpenList/v4/internal/model"
1415
"github.com/OpenListTeam/OpenList/v4/pkg/cron"
1516
"github.com/OpenListTeam/OpenList/v4/pkg/gowebdav"
@@ -130,6 +131,9 @@ func (d *WebDav) Get(ctx context.Context, _path string) (model.Obj, error) {
130131
_path = path.Join(d.GetRootPath(), _path)
131132
info, err := d.client.Stat(_path)
132133
if err != nil {
134+
if gowebdav.IsErrNotFound(err) {
135+
return nil, errs.ObjectNotFound
136+
}
133137
return nil, err
134138
}
135139

drivers/webdav/driver_test.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package webdav
2+
3+
import (
4+
"context"
5+
"net/http"
6+
"net/http/httptest"
7+
"sync/atomic"
8+
"testing"
9+
10+
"github.com/OpenListTeam/OpenList/v4/internal/driver"
11+
"github.com/OpenListTeam/OpenList/v4/internal/errs"
12+
"github.com/OpenListTeam/OpenList/v4/internal/op"
13+
)
14+
15+
func TestGetMapsMissingPathToObjectNotFound(t *testing.T) {
16+
d, cleanup := newTestDriver(t, nil)
17+
defer cleanup()
18+
19+
_, err := d.Get(context.Background(), "/missing")
20+
if !errs.IsObjectNotFound(err) {
21+
t.Fatalf("expected object not found, got %v", err)
22+
}
23+
}
24+
25+
func TestMakeDirAfterMissingWebDAVStat(t *testing.T) {
26+
var mkcolCount int32
27+
d, cleanup := newTestDriver(t, func(w http.ResponseWriter, r *http.Request) bool {
28+
if r.Method == "MKCOL" && (r.URL.Path == "/new" || r.URL.Path == "/new/") {
29+
atomic.AddInt32(&mkcolCount, 1)
30+
w.WriteHeader(http.StatusCreated)
31+
return true
32+
}
33+
return false
34+
})
35+
defer cleanup()
36+
37+
if err := op.MakeDir(context.Background(), d, "/new"); err != nil {
38+
t.Fatalf("MakeDir failed: %v", err)
39+
}
40+
if got := atomic.LoadInt32(&mkcolCount); got != 1 {
41+
t.Fatalf("expected one MKCOL request, got %d", got)
42+
}
43+
}
44+
45+
func newTestDriver(t *testing.T, extra func(http.ResponseWriter, *http.Request) bool) (*WebDav, func()) {
46+
t.Helper()
47+
48+
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
49+
if extra != nil && extra(w, r) {
50+
return
51+
}
52+
switch r.Method {
53+
case "PROPFIND":
54+
if r.URL.Path == "/" {
55+
w.Header().Set("Content-Type", "application/xml; charset=utf-8")
56+
w.WriteHeader(http.StatusMultiStatus)
57+
_, _ = w.Write([]byte(`<?xml version="1.0" encoding="utf-8"?>
58+
<d:multistatus xmlns:d="DAV:">
59+
<d:response>
60+
<d:href>/</d:href>
61+
<d:propstat>
62+
<d:prop>
63+
<d:displayname>/</d:displayname>
64+
<d:resourcetype><d:collection/></d:resourcetype>
65+
</d:prop>
66+
<d:status>HTTP/1.1 200 OK</d:status>
67+
</d:propstat>
68+
</d:response>
69+
</d:multistatus>`))
70+
return
71+
}
72+
http.NotFound(w, r)
73+
case "MKCOL":
74+
w.WriteHeader(http.StatusConflict)
75+
default:
76+
w.WriteHeader(http.StatusMethodNotAllowed)
77+
}
78+
}))
79+
80+
d := &WebDav{Addition: Addition{Address: srv.URL, RootPath: driver.RootPath{RootFolderPath: "/"}}}
81+
if err := d.Init(context.Background()); err != nil {
82+
srv.Close()
83+
t.Fatalf("init driver: %v", err)
84+
}
85+
return d, func() {
86+
_ = d.Drop(context.Background())
87+
srv.Close()
88+
}
89+
}

0 commit comments

Comments
 (0)