feat: add a config option to bypass mime content type sniffing (#60)

This commit is contained in:
Justyn
2021-01-14 14:47:33 +00:00
committed by GitHub
parent 8cd6d0a585
commit 099479a894
3 changed files with 99 additions and 8 deletions
+12 -5
View File
@@ -122,8 +122,11 @@ func parseUsers(raw []interface{}, c *lib.Config) {
}
user.Handler = &webdav.Handler{
Prefix: c.User.Handler.Prefix,
FileSystem: webdav.Dir(user.Scope),
Prefix: c.User.Handler.Prefix,
FileSystem: lib.WebDavDir{
Dir: webdav.Dir(user.Scope),
NoSniff: c.NoSniff,
},
LockSystem: webdav.NewMemLS(),
}
@@ -179,12 +182,16 @@ func readConfig(flags *pflag.FlagSet) *lib.Config {
Modify: getOptB(flags, "modify"),
Rules: []*lib.Rule{},
Handler: &webdav.Handler{
Prefix: getOpt(flags, "prefix"),
FileSystem: webdav.Dir(getOpt(flags, "scope")),
Prefix: getOpt(flags, "prefix"),
FileSystem: lib.WebDavDir{
Dir: webdav.Dir(getOpt(flags, "scope")),
NoSniff: getOptB(flags, "nosniff"),
},
LockSystem: webdav.NewMemLS(),
},
},
Auth: getOptB(flags, "auth"),
Auth: getOptB(flags, "auth"),
NoSniff: getOptB(flags, "nosniff"),
Cors: lib.CorsCfg{
Enabled: false,
Credentials: false,
+83
View File
@@ -0,0 +1,83 @@
package lib
import (
"context"
"mime"
"os"
"path"
"golang.org/x/net/webdav"
)
// NoSniffFileInfo wraps any generic FileInfo interface and bypasses mime type sniffing.
type NoSniffFileInfo struct {
os.FileInfo
}
func (w NoSniffFileInfo) ContentType(ctx context.Context) (contentType string, err error) {
if mimeType := mime.TypeByExtension(path.Ext(w.FileInfo.Name())); mimeType != "" {
// We can figure out the mime from the extension.
return mimeType, nil
} else {
// We can't figure out the mime type without sniffing, call it an octet stream.
return "application/octet-stream", nil
}
}
type WebDavDir struct {
webdav.Dir
NoSniff bool
}
func (d WebDavDir) Stat(ctx context.Context, name string) (os.FileInfo, error) {
// Skip wrapping if NoSniff is off
if !d.NoSniff {
return d.Dir.Stat(ctx, name)
}
info, err := d.Dir.Stat(ctx, name)
if err != nil {
return nil, err
}
return NoSniffFileInfo{info}, nil
}
func (d WebDavDir) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (webdav.File, error) {
// Skip wrapping if NoSniff is off
if !d.NoSniff {
return d.Dir.OpenFile(ctx, name, flag, perm)
}
file, err := d.Dir.OpenFile(ctx, name, flag, perm)
if err != nil {
return nil, err
}
return WebDavFile{File: file}, nil
}
type WebDavFile struct {
webdav.File
}
func (f WebDavFile) Stat() (os.FileInfo, error) {
info, err := f.File.Stat()
if err != nil {
return nil, err
}
return NoSniffFileInfo{info}, nil
}
func (f WebDavFile) Readdir(count int) (fis []os.FileInfo, err error) {
fis, err = f.File.Readdir(count)
if err != nil {
return nil, err
}
for i := range fis {
fis[i] = NoSniffFileInfo{fis[i]}
}
return fis, nil
}
+4 -3
View File
@@ -20,9 +20,10 @@ type CorsCfg struct {
// Config is the configuration of a WebDAV instance.
type Config struct {
*User
Auth bool
Cors CorsCfg
Users map[string]*User
Auth bool
NoSniff bool
Cors CorsCfg
Users map[string]*User
}
// ServeHTTP determines if the request is for this plugin, and if all prerequisites are met.