mirror of
https://github.com/rclone/rclone.git
synced 2025-06-24 22:11:45 +02:00
serve webdav: convert options to new style
This commit is contained in:
parent
6054c4e49d
commit
3c981e6c2c
@ -33,41 +33,42 @@ import (
|
|||||||
"golang.org/x/net/webdav"
|
"golang.org/x/net/webdav"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// OptionsInfo describes the Options in use
|
||||||
|
var OptionsInfo = fs.Options{{
|
||||||
|
Name: "etag_hash",
|
||||||
|
Default: "",
|
||||||
|
Help: "Which hash to use for the ETag, or auto or blank for off",
|
||||||
|
}, {
|
||||||
|
Name: "disable_dir_list",
|
||||||
|
Default: false,
|
||||||
|
Help: "Disable HTML directory list on GET request for a directory",
|
||||||
|
}}.
|
||||||
|
Add(libhttp.ConfigInfo).
|
||||||
|
Add(libhttp.AuthConfigInfo).
|
||||||
|
Add(libhttp.TemplateConfigInfo)
|
||||||
|
|
||||||
// Options required for http server
|
// Options required for http server
|
||||||
type Options struct {
|
type Options struct {
|
||||||
Auth libhttp.AuthConfig
|
Auth libhttp.AuthConfig
|
||||||
HTTP libhttp.Config
|
HTTP libhttp.Config
|
||||||
Template libhttp.TemplateConfig
|
Template libhttp.TemplateConfig
|
||||||
HashName string
|
EtagHash string `config:"etag_hash"`
|
||||||
HashType hash.Type
|
DisableDirList bool `config:"disable_dir_list"`
|
||||||
DisableGETDir bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultOpt is the default values used for Options
|
|
||||||
var DefaultOpt = Options{
|
|
||||||
Auth: libhttp.DefaultAuthCfg(),
|
|
||||||
HTTP: libhttp.DefaultCfg(),
|
|
||||||
Template: libhttp.DefaultTemplateCfg(),
|
|
||||||
HashType: hash.None,
|
|
||||||
DisableGETDir: false,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opt is options set by command line flags
|
// Opt is options set by command line flags
|
||||||
var Opt = DefaultOpt
|
var Opt Options
|
||||||
|
|
||||||
// flagPrefix is the prefix used to uniquely identify command line flags.
|
// flagPrefix is the prefix used to uniquely identify command line flags.
|
||||||
// It is intentionally empty for this package.
|
// It is intentionally empty for this package.
|
||||||
const flagPrefix = ""
|
const flagPrefix = ""
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
fs.RegisterGlobalOptions(fs.OptionsInfo{Name: "webdav", Opt: &Opt, Options: OptionsInfo})
|
||||||
flagSet := Command.Flags()
|
flagSet := Command.Flags()
|
||||||
libhttp.AddAuthFlagsPrefix(flagSet, flagPrefix, &Opt.Auth)
|
flags.AddFlagsFromOptions(flagSet, "", OptionsInfo)
|
||||||
libhttp.AddHTTPFlagsPrefix(flagSet, flagPrefix, &Opt.HTTP)
|
|
||||||
libhttp.AddTemplateFlagsPrefix(flagSet, "", &Opt.Template)
|
|
||||||
vfsflags.AddFlags(flagSet)
|
vfsflags.AddFlags(flagSet)
|
||||||
proxyflags.AddFlags(flagSet)
|
proxyflags.AddFlags(flagSet)
|
||||||
flags.StringVarP(flagSet, &Opt.HashName, "etag-hash", "", "", "Which hash to use for the ETag, or auto or blank for off", "")
|
|
||||||
flags.BoolVarP(flagSet, &Opt.DisableGETDir, "disable-dir-list", "", false, "Disable HTML directory list on GET request for a directory", "")
|
|
||||||
cmdserve.Command.AddCommand(Command)
|
cmdserve.Command.AddCommand(Command)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,18 +144,6 @@ done by the permissions on the socket.
|
|||||||
} else {
|
} else {
|
||||||
cmd.CheckArgs(0, 0, command, args)
|
cmd.CheckArgs(0, 0, command, args)
|
||||||
}
|
}
|
||||||
Opt.HashType = hash.None
|
|
||||||
if Opt.HashName == "auto" {
|
|
||||||
Opt.HashType = f.Hashes().GetOne()
|
|
||||||
} else if Opt.HashName != "" {
|
|
||||||
err := Opt.HashType.Set(Opt.HashName)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if Opt.HashType != hash.None {
|
|
||||||
fs.Debugf(f, "Using hash %v for ETag", Opt.HashType)
|
|
||||||
}
|
|
||||||
cmd.Run(false, false, command, func() error {
|
cmd.Run(false, false, command, func() error {
|
||||||
s, err := newWebDAV(context.Background(), f, &Opt)
|
s, err := newWebDAV(context.Background(), f, &Opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -192,6 +181,7 @@ type WebDAV struct {
|
|||||||
webdavhandler *webdav.Handler
|
webdavhandler *webdav.Handler
|
||||||
proxy *proxy.Proxy
|
proxy *proxy.Proxy
|
||||||
ctx context.Context // for global config
|
ctx context.Context // for global config
|
||||||
|
etagHashType hash.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
// check interface
|
// check interface
|
||||||
@ -200,9 +190,21 @@ var _ webdav.FileSystem = (*WebDAV)(nil)
|
|||||||
// Make a new WebDAV to serve the remote
|
// Make a new WebDAV to serve the remote
|
||||||
func newWebDAV(ctx context.Context, f fs.Fs, opt *Options) (w *WebDAV, err error) {
|
func newWebDAV(ctx context.Context, f fs.Fs, opt *Options) (w *WebDAV, err error) {
|
||||||
w = &WebDAV{
|
w = &WebDAV{
|
||||||
f: f,
|
f: f,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
opt: *opt,
|
opt: *opt,
|
||||||
|
etagHashType: hash.None,
|
||||||
|
}
|
||||||
|
if opt.EtagHash == "auto" {
|
||||||
|
w.etagHashType = f.Hashes().GetOne()
|
||||||
|
} else if opt.EtagHash != "" {
|
||||||
|
err := w.etagHashType.Set(opt.EtagHash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if w.etagHashType != hash.None {
|
||||||
|
fs.Debugf(f, "Using hash %v for ETag", w.etagHashType)
|
||||||
}
|
}
|
||||||
if proxy.Opt.AuthProxy != "" {
|
if proxy.Opt.AuthProxy != "" {
|
||||||
w.proxy = proxy.New(ctx, &proxy.Opt, &vfscommon.Opt)
|
w.proxy = proxy.New(ctx, &proxy.Opt, &vfscommon.Opt)
|
||||||
@ -333,7 +335,7 @@ func (w *WebDAV) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
|||||||
urlPath := r.URL.Path
|
urlPath := r.URL.Path
|
||||||
isDir := strings.HasSuffix(urlPath, "/")
|
isDir := strings.HasSuffix(urlPath, "/")
|
||||||
remote := strings.Trim(urlPath, "/")
|
remote := strings.Trim(urlPath, "/")
|
||||||
if !w.opt.DisableGETDir && (r.Method == "GET" || r.Method == "HEAD") && isDir {
|
if !w.opt.DisableDirList && (r.Method == "GET" || r.Method == "HEAD") && isDir {
|
||||||
w.serveDir(rw, r, remote)
|
w.serveDir(rw, r, remote)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -517,16 +519,16 @@ func (h Handle) DeadProps() (map[xml.Name]webdav.Property, error) {
|
|||||||
property webdav.Property
|
property webdav.Property
|
||||||
properties = make(map[xml.Name]webdav.Property)
|
properties = make(map[xml.Name]webdav.Property)
|
||||||
)
|
)
|
||||||
if h.w.opt.HashType != hash.None {
|
if h.w.etagHashType != hash.None {
|
||||||
entry := h.Handle.Node().DirEntry()
|
entry := h.Handle.Node().DirEntry()
|
||||||
if o, ok := entry.(fs.Object); ok {
|
if o, ok := entry.(fs.Object); ok {
|
||||||
hash, err := o.Hash(h.ctx, h.w.opt.HashType)
|
hash, err := o.Hash(h.ctx, h.w.etagHashType)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
xmlName.Space = "http://owncloud.org/ns"
|
xmlName.Space = "http://owncloud.org/ns"
|
||||||
xmlName.Local = "checksums"
|
xmlName.Local = "checksums"
|
||||||
property.XMLName = xmlName
|
property.XMLName = xmlName
|
||||||
property.InnerXML = append(property.InnerXML, "<checksum xmlns=\"http://owncloud.org/ns\">"...)
|
property.InnerXML = append(property.InnerXML, "<checksum xmlns=\"http://owncloud.org/ns\">"...)
|
||||||
property.InnerXML = append(property.InnerXML, strings.ToUpper(h.w.opt.HashType.String())...)
|
property.InnerXML = append(property.InnerXML, strings.ToUpper(h.w.etagHashType.String())...)
|
||||||
property.InnerXML = append(property.InnerXML, ':')
|
property.InnerXML = append(property.InnerXML, ':')
|
||||||
property.InnerXML = append(property.InnerXML, hash...)
|
property.InnerXML = append(property.InnerXML, hash...)
|
||||||
property.InnerXML = append(property.InnerXML, "</checksum>"...)
|
property.InnerXML = append(property.InnerXML, "</checksum>"...)
|
||||||
@ -579,7 +581,7 @@ type FileInfo struct {
|
|||||||
// ETag returns an ETag for the FileInfo
|
// ETag returns an ETag for the FileInfo
|
||||||
func (fi FileInfo) ETag(ctx context.Context) (etag string, err error) {
|
func (fi FileInfo) ETag(ctx context.Context) (etag string, err error) {
|
||||||
// defer log.Trace(fi, "")("etag=%q, err=%v", &etag, &err)
|
// defer log.Trace(fi, "")("etag=%q, err=%v", &etag, &err)
|
||||||
if fi.w.opt.HashType == hash.None {
|
if fi.w.etagHashType == hash.None {
|
||||||
return "", webdav.ErrNotImplemented
|
return "", webdav.ErrNotImplemented
|
||||||
}
|
}
|
||||||
node, ok := (fi.FileInfo).(vfs.Node)
|
node, ok := (fi.FileInfo).(vfs.Node)
|
||||||
@ -592,7 +594,7 @@ func (fi FileInfo) ETag(ctx context.Context) (etag string, err error) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return "", webdav.ErrNotImplemented
|
return "", webdav.ErrNotImplemented
|
||||||
}
|
}
|
||||||
hash, err := o.Hash(ctx, fi.w.opt.HashType)
|
hash, err := o.Hash(ctx, fi.w.etagHashType)
|
||||||
if err != nil || hash == "" {
|
if err != nil || hash == "" {
|
||||||
return "", webdav.ErrNotImplemented
|
return "", webdav.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,6 @@ import (
|
|||||||
"github.com/rclone/rclone/fs/config/configmap"
|
"github.com/rclone/rclone/fs/config/configmap"
|
||||||
"github.com/rclone/rclone/fs/config/obscure"
|
"github.com/rclone/rclone/fs/config/obscure"
|
||||||
"github.com/rclone/rclone/fs/filter"
|
"github.com/rclone/rclone/fs/filter"
|
||||||
"github.com/rclone/rclone/fs/hash"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"golang.org/x/net/webdav"
|
"golang.org/x/net/webdav"
|
||||||
@ -48,13 +47,13 @@ var (
|
|||||||
func TestWebDav(t *testing.T) {
|
func TestWebDav(t *testing.T) {
|
||||||
// Configure and start the server
|
// Configure and start the server
|
||||||
start := func(f fs.Fs) (configmap.Simple, func()) {
|
start := func(f fs.Fs) (configmap.Simple, func()) {
|
||||||
opt := DefaultOpt
|
opt := Opt
|
||||||
opt.HTTP.ListenAddr = []string{testBindAddress}
|
opt.HTTP.ListenAddr = []string{testBindAddress}
|
||||||
opt.HTTP.BaseURL = "/prefix"
|
opt.HTTP.BaseURL = "/prefix"
|
||||||
opt.Auth.BasicUser = testUser
|
opt.Auth.BasicUser = testUser
|
||||||
opt.Auth.BasicPass = testPass
|
opt.Auth.BasicPass = testPass
|
||||||
opt.Template.Path = testTemplate
|
opt.Template.Path = testTemplate
|
||||||
opt.HashType = hash.MD5
|
opt.EtagHash = "MD5"
|
||||||
|
|
||||||
// Start the server
|
// Start the server
|
||||||
w, err := newWebDAV(context.Background(), f, &opt)
|
w, err := newWebDAV(context.Background(), f, &opt)
|
||||||
@ -98,7 +97,7 @@ func TestHTTPFunction(t *testing.T) {
|
|||||||
f, err := fs.NewFs(context.Background(), "../http/testdata/files")
|
f, err := fs.NewFs(context.Background(), "../http/testdata/files")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
opt := DefaultOpt
|
opt := Opt
|
||||||
opt.HTTP.ListenAddr = []string{testBindAddress}
|
opt.HTTP.ListenAddr = []string{testBindAddress}
|
||||||
opt.Template.Path = testTemplate
|
opt.Template.Path = testTemplate
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user