handler, cli: Add a flag to disable downloads and termination of uploads (#668)
* Add a flag to disable downloads of uploaded files * Add a flag to disable deletion of uploaded files * Fix spelling error * Rename `DisableDelete` to `DisableTermination` * Also rename CLI flag * Conditionally build the `Access-Control-Allow-Methods` headers * Update tests with new order of allowed methods header * Add test for checking conditional `Access-Control-Allow-Methods` header
This commit is contained in:
parent
374404c26c
commit
3feef174fd
|
@ -21,6 +21,8 @@ var Flags struct {
|
||||||
UploadDir string
|
UploadDir string
|
||||||
Basepath string
|
Basepath string
|
||||||
ShowGreeting bool
|
ShowGreeting bool
|
||||||
|
DisableDownload bool
|
||||||
|
DisableTermination bool
|
||||||
Timeout int64
|
Timeout int64
|
||||||
S3Bucket string
|
S3Bucket string
|
||||||
S3ObjectPrefix string
|
S3ObjectPrefix string
|
||||||
|
@ -68,6 +70,8 @@ func ParseFlags() {
|
||||||
flag.StringVar(&Flags.UploadDir, "upload-dir", "./data", "Directory to store uploads in")
|
flag.StringVar(&Flags.UploadDir, "upload-dir", "./data", "Directory to store uploads in")
|
||||||
flag.StringVar(&Flags.Basepath, "base-path", "/files/", "Basepath of the HTTP server")
|
flag.StringVar(&Flags.Basepath, "base-path", "/files/", "Basepath of the HTTP server")
|
||||||
flag.BoolVar(&Flags.ShowGreeting, "show-greeting", true, "Show the greeting message")
|
flag.BoolVar(&Flags.ShowGreeting, "show-greeting", true, "Show the greeting message")
|
||||||
|
flag.BoolVar(&Flags.DisableDownload, "disable-download", false, "Disable the download endpoint")
|
||||||
|
flag.BoolVar(&Flags.DisableTermination, "disable-termination", false, "Disable the termination endpoint")
|
||||||
flag.Int64Var(&Flags.Timeout, "timeout", 6*1000, "Read timeout for connections in milliseconds. A zero value means that reads will not timeout")
|
flag.Int64Var(&Flags.Timeout, "timeout", 6*1000, "Read timeout for connections in milliseconds. A zero value means that reads will not timeout")
|
||||||
flag.StringVar(&Flags.S3Bucket, "s3-bucket", "", "Use AWS S3 with this bucket as storage backend (requires the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_REGION environment variables to be set)")
|
flag.StringVar(&Flags.S3Bucket, "s3-bucket", "", "Use AWS S3 with this bucket as storage backend (requires the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_REGION environment variables to be set)")
|
||||||
flag.StringVar(&Flags.S3ObjectPrefix, "s3-object-prefix", "", "Prefix for S3 object names")
|
flag.StringVar(&Flags.S3ObjectPrefix, "s3-object-prefix", "", "Prefix for S3 object names")
|
||||||
|
|
|
@ -27,6 +27,8 @@ func Serve() {
|
||||||
MaxSize: Flags.MaxSize,
|
MaxSize: Flags.MaxSize,
|
||||||
BasePath: Flags.Basepath,
|
BasePath: Flags.Basepath,
|
||||||
RespectForwardedHeaders: Flags.BehindProxy,
|
RespectForwardedHeaders: Flags.BehindProxy,
|
||||||
|
DisableDownload: Flags.DisableDownload,
|
||||||
|
DisableTermination: Flags.DisableTermination,
|
||||||
StoreComposer: Composer,
|
StoreComposer: Composer,
|
||||||
NotifyCompleteUploads: true,
|
NotifyCompleteUploads: true,
|
||||||
NotifyTerminatedUploads: true,
|
NotifyTerminatedUploads: true,
|
||||||
|
|
|
@ -22,6 +22,12 @@ type Config struct {
|
||||||
// absolute URL containing a scheme, e.g. "http://tus.io"
|
// absolute URL containing a scheme, e.g. "http://tus.io"
|
||||||
BasePath string
|
BasePath string
|
||||||
isAbs bool
|
isAbs bool
|
||||||
|
// DisableDownload indicates whether the server will refuse downloads of the
|
||||||
|
// uploaded file, by not mounting the GET handler.
|
||||||
|
DisableDownload bool
|
||||||
|
// DisableTermination indicates whether the server will refuse termination
|
||||||
|
// requests of the uploaded file, by not mounting the DELETE handler.
|
||||||
|
DisableTermination bool
|
||||||
// NotifyCompleteUploads indicates whether sending notifications about
|
// NotifyCompleteUploads indicates whether sending notifications about
|
||||||
// completed uploads using the CompleteUploads channel should be enabled.
|
// completed uploads using the CompleteUploads channel should be enabled.
|
||||||
NotifyCompleteUploads bool
|
NotifyCompleteUploads bool
|
||||||
|
|
|
@ -22,7 +22,29 @@ func TestCORS(t *testing.T) {
|
||||||
Code: http.StatusOK,
|
Code: http.StatusOK,
|
||||||
ResHeader: map[string]string{
|
ResHeader: map[string]string{
|
||||||
"Access-Control-Allow-Headers": "Authorization, Origin, X-Requested-With, X-Request-ID, X-HTTP-Method-Override, Content-Type, Upload-Length, Upload-Offset, Tus-Resumable, Upload-Metadata, Upload-Defer-Length, Upload-Concat",
|
"Access-Control-Allow-Headers": "Authorization, Origin, X-Requested-With, X-Request-ID, X-HTTP-Method-Override, Content-Type, Upload-Length, Upload-Offset, Tus-Resumable, Upload-Metadata, Upload-Defer-Length, Upload-Concat",
|
||||||
"Access-Control-Allow-Methods": "POST, GET, HEAD, PATCH, DELETE, OPTIONS",
|
"Access-Control-Allow-Methods": "POST, HEAD, PATCH, OPTIONS, GET, DELETE",
|
||||||
|
"Access-Control-Max-Age": "86400",
|
||||||
|
"Access-Control-Allow-Origin": "tus.io",
|
||||||
|
},
|
||||||
|
}).Run(handler, t)
|
||||||
|
})
|
||||||
|
|
||||||
|
SubTest(t, "Conditional allow methods", func(t *testing.T, store *MockFullDataStore, composer *StoreComposer) {
|
||||||
|
handler, _ := NewHandler(Config{
|
||||||
|
StoreComposer: composer,
|
||||||
|
DisableTermination: true,
|
||||||
|
DisableDownload: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
(&httpTest{
|
||||||
|
Method: "OPTIONS",
|
||||||
|
ReqHeader: map[string]string{
|
||||||
|
"Origin": "tus.io",
|
||||||
|
},
|
||||||
|
Code: http.StatusOK,
|
||||||
|
ResHeader: map[string]string{
|
||||||
|
"Access-Control-Allow-Headers": "Authorization, Origin, X-Requested-With, X-Request-ID, X-HTTP-Method-Override, Content-Type, Upload-Length, Upload-Offset, Tus-Resumable, Upload-Metadata, Upload-Defer-Length, Upload-Concat",
|
||||||
|
"Access-Control-Allow-Methods": "POST, HEAD, PATCH, OPTIONS",
|
||||||
"Access-Control-Max-Age": "86400",
|
"Access-Control-Max-Age": "86400",
|
||||||
"Access-Control-Allow-Origin": "tus.io",
|
"Access-Control-Allow-Origin": "tus.io",
|
||||||
},
|
},
|
||||||
|
|
|
@ -40,10 +40,12 @@ func NewHandler(config Config) (*Handler, error) {
|
||||||
mux.Post("", http.HandlerFunc(handler.PostFile))
|
mux.Post("", http.HandlerFunc(handler.PostFile))
|
||||||
mux.Head(":id", http.HandlerFunc(handler.HeadFile))
|
mux.Head(":id", http.HandlerFunc(handler.HeadFile))
|
||||||
mux.Add("PATCH", ":id", http.HandlerFunc(handler.PatchFile))
|
mux.Add("PATCH", ":id", http.HandlerFunc(handler.PatchFile))
|
||||||
|
if !config.DisableDownload {
|
||||||
mux.Get(":id", http.HandlerFunc(handler.GetFile))
|
mux.Get(":id", http.HandlerFunc(handler.GetFile))
|
||||||
|
}
|
||||||
|
|
||||||
// Only attach the DELETE handler if the Terminate() method is provided
|
// Only attach the DELETE handler if the Terminate() method is provided
|
||||||
if config.StoreComposer.UsesTerminater {
|
if config.StoreComposer.UsesTerminater && !config.DisableTermination {
|
||||||
mux.Del(":id", http.HandlerFunc(handler.DelFile))
|
mux.Del(":id", http.HandlerFunc(handler.DelFile))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -221,8 +221,17 @@ func (handler *UnroutedHandler) Middleware(h http.Handler) http.Handler {
|
||||||
header.Set("Access-Control-Allow-Origin", origin)
|
header.Set("Access-Control-Allow-Origin", origin)
|
||||||
|
|
||||||
if r.Method == "OPTIONS" {
|
if r.Method == "OPTIONS" {
|
||||||
|
allowedMethods := "POST, HEAD, PATCH, OPTIONS"
|
||||||
|
if !handler.config.DisableDownload {
|
||||||
|
allowedMethods += ", GET"
|
||||||
|
}
|
||||||
|
|
||||||
|
if !handler.config.DisableTermination {
|
||||||
|
allowedMethods += ", DELETE"
|
||||||
|
}
|
||||||
|
|
||||||
// Preflight request
|
// Preflight request
|
||||||
header.Add("Access-Control-Allow-Methods", "POST, GET, HEAD, PATCH, DELETE, OPTIONS")
|
header.Add("Access-Control-Allow-Methods", allowedMethods)
|
||||||
header.Add("Access-Control-Allow-Headers", "Authorization, Origin, X-Requested-With, X-Request-ID, X-HTTP-Method-Override, Content-Type, Upload-Length, Upload-Offset, Tus-Resumable, Upload-Metadata, Upload-Defer-Length, Upload-Concat")
|
header.Add("Access-Control-Allow-Headers", "Authorization, Origin, X-Requested-With, X-Request-ID, X-HTTP-Method-Override, Content-Type, Upload-Length, Upload-Offset, Tus-Resumable, Upload-Metadata, Upload-Defer-Length, Upload-Concat")
|
||||||
header.Set("Access-Control-Max-Age", "86400")
|
header.Set("Access-Control-Max-Age", "86400")
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue