serve webdav: fix webdav with --baseurl under Windows

Windows webdav does an OPTIONS request on the root even when given a
path and if we return 404 here then Windows refuses to use the path.

This patch allows OPTIONS requests only on the root to fix this.

This affects all the HTTP servers.
This commit is contained in:
Nick Craig-Wood 2024-03-27 12:23:35 +00:00
parent a67688dcc7
commit 72425b1218
2 changed files with 59 additions and 5 deletions

View File

@ -195,6 +195,14 @@ func MiddlewareCORS(allowOrigin string) Middleware {
// MiddlewareStripPrefix instantiates middleware that removes the BaseURL from the path
func MiddlewareStripPrefix(prefix string) Middleware {
return func(next http.Handler) http.Handler {
return http.StripPrefix(prefix, next)
stripPrefixHandler := http.StripPrefix(prefix, next)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Allow OPTIONS on the root only
if r.URL.Path == "/" && r.Method == "OPTIONS" {
next.ServeHTTP(w, r)
return
}
stripPrefixHandler.ServeHTTP(w, r)
})
}
}

View File

@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"net/http"
"strings"
"testing"
"github.com/stretchr/testify/require"
@ -329,8 +330,11 @@ var _testCORSHeaderKeys = []string{
func TestMiddlewareCORS(t *testing.T) {
servers := []struct {
name string
http Config
name string
http Config
tryRoot bool
method string
status int
}{
{
name: "CustomOrigin",
@ -338,6 +342,40 @@ func TestMiddlewareCORS(t *testing.T) {
ListenAddr: []string{"127.0.0.1:0"},
AllowOrigin: "http://test.rclone.org",
},
method: "GET",
status: http.StatusOK,
},
{
name: "WithBaseURL",
http: Config{
ListenAddr: []string{"127.0.0.1:0"},
AllowOrigin: "http://test.rclone.org",
BaseURL: "/baseurl/",
},
method: "GET",
status: http.StatusOK,
},
{
name: "WithBaseURLTryRootGET",
http: Config{
ListenAddr: []string{"127.0.0.1:0"},
AllowOrigin: "http://test.rclone.org",
BaseURL: "/baseurl/",
},
method: "GET",
status: http.StatusNotFound,
tryRoot: true,
},
{
name: "WithBaseURLTryRootOPTIONS",
http: Config{
ListenAddr: []string{"127.0.0.1:0"},
AllowOrigin: "http://test.rclone.org",
BaseURL: "/baseurl/",
},
method: "OPTIONS",
status: http.StatusOK,
tryRoot: true,
},
}
@ -354,9 +392,14 @@ func TestMiddlewareCORS(t *testing.T) {
s.Serve()
url := testGetServerURL(t, s)
// Try the query on the root, ignoring the baseURL
if ss.tryRoot {
slash := strings.LastIndex(url[:len(url)-1], "/")
url = url[:slash+1]
}
client := &http.Client{}
req, err := http.NewRequest("GET", url, nil)
req, err := http.NewRequest(ss.method, url, nil)
require.NoError(t, err)
resp, err := client.Do(req)
@ -365,8 +408,11 @@ func TestMiddlewareCORS(t *testing.T) {
_ = resp.Body.Close()
}()
require.Equal(t, http.StatusOK, resp.StatusCode, "should return ok")
require.Equal(t, ss.status, resp.StatusCode, "should return expected error code")
if ss.status == http.StatusNotFound {
return
}
testExpectRespBody(t, resp, expected)
for _, key := range _testCORSHeaderKeys {