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 f62e7b5b30
commit 42914bc0b0
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 // MiddlewareStripPrefix instantiates middleware that removes the BaseURL from the path
func MiddlewareStripPrefix(prefix string) Middleware { func MiddlewareStripPrefix(prefix string) Middleware {
return func(next http.Handler) http.Handler { 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" "errors"
"fmt" "fmt"
"net/http" "net/http"
"strings"
"testing" "testing"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -329,8 +330,11 @@ var _testCORSHeaderKeys = []string{
func TestMiddlewareCORS(t *testing.T) { func TestMiddlewareCORS(t *testing.T) {
servers := []struct { servers := []struct {
name string name string
http Config http Config
tryRoot bool
method string
status int
}{ }{
{ {
name: "CustomOrigin", name: "CustomOrigin",
@ -338,6 +342,40 @@ func TestMiddlewareCORS(t *testing.T) {
ListenAddr: []string{"127.0.0.1:0"}, ListenAddr: []string{"127.0.0.1:0"},
AllowOrigin: "http://test.rclone.org", 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() s.Serve()
url := testGetServerURL(t, s) 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{} client := &http.Client{}
req, err := http.NewRequest("GET", url, nil) req, err := http.NewRequest(ss.method, url, nil)
require.NoError(t, err) require.NoError(t, err)
resp, err := client.Do(req) resp, err := client.Do(req)
@ -365,8 +408,11 @@ func TestMiddlewareCORS(t *testing.T) {
_ = resp.Body.Close() _ = 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) testExpectRespBody(t, resp, expected)
for _, key := range _testCORSHeaderKeys { for _, key := range _testCORSHeaderKeys {