Skip to content

Commit

Permalink
handler: Simultaneous support for -01 and -02 of IETF draft (#1066)
Browse files Browse the repository at this point in the history
* [ADD] support for both draft v01 and v02 for the upload protocol

This improves commit 09f105d to support both draft v01 and draft v02 versions of the ietf upload protocol

* [ADD] config.go allowheaders

* [ADD] tests to cors head and post

Patch coming next

* [HF] minor be even more explicit on which version has which headers

* [ADD] patch test works now

* [REFACTOR] don't use slices since not supported

Error: pkg/handler/unrouted_handler.go:12:2: package slices is not in GOROOT (/Users/runner/hostedtoolcache/go/1.20.12/x64/src/slices)

* [FIX] easy comments

* [HF] extract isDraftVersionResumableUploadComplete

* [HF] more consistent naming

* [HF slightly cleaner code

* [HF] comments on functions

* [HF] bad find and replace

* [REFACTOR] deduplicate code on post_test.go

* [REFACTOR] head_test to deduplicate code

* [REFACTOR] patch test to not repeat itself + standardize post test with othes

* Make interop versions unexported and add comment

* Rename some function to be shorter and clearer

* Update variable names for distinguishing them

* Put setting of Upload-Complete into own function

* Typo

* Refactor HEAD tests

* Refactor POST tests

* Refactor PATCH test

* Reuse test helper

* Move setting of interop version out of unrelated function

---------

Co-authored-by: Marius Kleidl <[email protected]>
  • Loading branch information
Nealsoni00 and Acconut authored Mar 1, 2024
1 parent bbc40a9 commit 9801b91
Show file tree
Hide file tree
Showing 7 changed files with 488 additions and 413 deletions.
4 changes: 2 additions & 2 deletions pkg/handler/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,9 @@ var DefaultCorsConfig = CorsConfig{
AllowOrigin: regexp.MustCompile(".*"),
AllowCredentials: false,
AllowMethods: "POST, HEAD, PATCH, OPTIONS, GET, DELETE",
AllowHeaders: "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, Upload-Complete, Upload-Draft-Interop-Version",
AllowHeaders: "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, Upload-Incomplete, Upload-Complete, Upload-Draft-Interop-Version",
MaxAge: "86400",
ExposeHeaders: "Upload-Offset, Location, Upload-Length, Tus-Version, Tus-Resumable, Tus-Max-Size, Tus-Extension, Upload-Metadata, Upload-Defer-Length, Upload-Concat, Upload-Complete, Upload-Draft-Interop-Version",
ExposeHeaders: "Upload-Offset, Location, Upload-Length, Tus-Version, Tus-Resumable, Tus-Max-Size, Tus-Extension, Upload-Metadata, Upload-Defer-Length, Upload-Concat, Upload-Incomplete, Upload-Complete, Upload-Draft-Interop-Version",
}

func (config *Config) validate() error {
Expand Down
8 changes: 4 additions & 4 deletions pkg/handler/cors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestCORS(t *testing.T) {
},
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, Upload-Complete, Upload-Draft-Interop-Version",
"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, Upload-Incomplete, Upload-Complete, Upload-Draft-Interop-Version",
"Access-Control-Allow-Methods": "POST, HEAD, PATCH, OPTIONS, GET, DELETE",
"Access-Control-Max-Age": "86400",
"Access-Control-Allow-Origin": "https://tus.io",
Expand All @@ -40,7 +40,7 @@ func TestCORS(t *testing.T) {
},
ResHeader: map[string]string{
"Access-Control-Allow-Origin": "https://tus.io",
"Access-Control-Expose-Headers": "Upload-Offset, Location, Upload-Length, Tus-Version, Tus-Resumable, Tus-Max-Size, Tus-Extension, Upload-Metadata, Upload-Defer-Length, Upload-Concat, Upload-Complete, Upload-Draft-Interop-Version",
"Access-Control-Expose-Headers": "Upload-Offset, Location, Upload-Length, Tus-Version, Tus-Resumable, Tus-Max-Size, Tus-Extension, Upload-Metadata, Upload-Defer-Length, Upload-Concat, Upload-Incomplete, Upload-Complete, Upload-Draft-Interop-Version",
"Vary": "Origin",
"Access-Control-Allow-Methods": "",
"Access-Control-Allow-Headers": "",
Expand Down Expand Up @@ -72,7 +72,7 @@ func TestCORS(t *testing.T) {
},
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, Upload-Complete, Upload-Draft-Interop-Version",
"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, Upload-Incomplete, Upload-Complete, Upload-Draft-Interop-Version",
"Access-Control-Allow-Methods": "POST, HEAD, PATCH, OPTIONS, GET, DELETE",
"Access-Control-Max-Age": "86400",
"Access-Control-Allow-Origin": "http://tus.io",
Expand All @@ -89,7 +89,7 @@ func TestCORS(t *testing.T) {
},
ResHeader: map[string]string{
"Access-Control-Allow-Origin": "http://tus.io",
"Access-Control-Expose-Headers": "Upload-Offset, Location, Upload-Length, Tus-Version, Tus-Resumable, Tus-Max-Size, Tus-Extension, Upload-Metadata, Upload-Defer-Length, Upload-Concat, Upload-Complete, Upload-Draft-Interop-Version",
"Access-Control-Expose-Headers": "Upload-Offset, Location, Upload-Length, Tus-Version, Tus-Resumable, Tus-Max-Size, Tus-Extension, Upload-Metadata, Upload-Defer-Length, Upload-Concat, Upload-Incomplete, Upload-Complete, Upload-Draft-Interop-Version",
"Vary": "Origin",
"Access-Control-Allow-Methods": "",
"Access-Control-Allow-Headers": "",
Expand Down
199 changes: 100 additions & 99 deletions pkg/handler/head_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,105 +145,106 @@ func TestHead(t *testing.T) {
})

SubTest(t, "ExperimentalProtocol", func(t *testing.T, _ *MockFullDataStore, _ *StoreComposer) {
SubTest(t, "IncompleteUpload", func(t *testing.T, store *MockFullDataStore, composer *StoreComposer) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
upload := NewMockFullUpload(ctrl)

gomock.InOrder(
store.EXPECT().GetUpload(gomock.Any(), "yes").Return(upload, nil),
upload.EXPECT().GetInfo(gomock.Any()).Return(FileInfo{
SizeIsDeferred: false,
Size: 10,
Offset: 5,
}, nil),
)

handler, _ := NewHandler(Config{
StoreComposer: composer,
EnableExperimentalProtocol: true,
for _, interopVersion := range []string{"3", "4"} {
SubTest(t, "InteropVersion"+interopVersion, func(t *testing.T, _ *MockFullDataStore, _ *StoreComposer) {
SubTest(t, "IncompleteUpload", func(t *testing.T, store *MockFullDataStore, composer *StoreComposer) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
upload := NewMockFullUpload(ctrl)

gomock.InOrder(
store.EXPECT().GetUpload(gomock.Any(), "yes").Return(upload, nil),
upload.EXPECT().GetInfo(gomock.Any()).Return(FileInfo{
SizeIsDeferred: false,
Size: 10,
Offset: 5,
}, nil),
)

handler, _ := NewHandler(Config{
StoreComposer: composer,
EnableExperimentalProtocol: true,
})

(&httpTest{
Method: "HEAD",
URL: "yes",
ReqHeader: map[string]string{
"Upload-Draft-Interop-Version": interopVersion,
},
Code: http.StatusNoContent,
ResHeader: addIETFUploadCompleteHeader(map[string]string{
"Upload-Draft-Interop-Version": interopVersion,
"Upload-Offset": "5",
}, false, interopVersion),
}).Run(handler, t)
})

SubTest(t, "CompleteUpload", func(t *testing.T, store *MockFullDataStore, composer *StoreComposer) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
upload := NewMockFullUpload(ctrl)

gomock.InOrder(
store.EXPECT().GetUpload(gomock.Any(), "yes").Return(upload, nil),
upload.EXPECT().GetInfo(gomock.Any()).Return(FileInfo{
SizeIsDeferred: false,
Size: 10,
Offset: 10,
}, nil),
)

handler, _ := NewHandler(Config{
StoreComposer: composer,
EnableExperimentalProtocol: true,
})

(&httpTest{
Method: "HEAD",
URL: "yes",
ReqHeader: map[string]string{
"Upload-Draft-Interop-Version": interopVersion,
},
Code: http.StatusNoContent,
ResHeader: addIETFUploadCompleteHeader(map[string]string{
"Upload-Draft-Interop-Version": interopVersion,
"Upload-Offset": "10",
}, true, interopVersion),
}).Run(handler, t)
})

SubTest(t, "DeferredLength", func(t *testing.T, store *MockFullDataStore, composer *StoreComposer) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
upload := NewMockFullUpload(ctrl)

gomock.InOrder(
store.EXPECT().GetUpload(gomock.Any(), "yes").Return(upload, nil),
upload.EXPECT().GetInfo(gomock.Any()).Return(FileInfo{
SizeIsDeferred: true,
Offset: 5,
}, nil),
)

handler, _ := NewHandler(Config{
StoreComposer: composer,
EnableExperimentalProtocol: true,
})

(&httpTest{
Method: "HEAD",
URL: "yes",
ReqHeader: map[string]string{
"Upload-Draft-Interop-Version": interopVersion,
},
Code: http.StatusNoContent,
ResHeader: addIETFUploadCompleteHeader(map[string]string{
"Upload-Draft-Interop-Version": interopVersion,
"Upload-Offset": "5",
}, false, interopVersion),
}).Run(handler, t)
})
})

(&httpTest{
Method: "HEAD",
URL: "yes",
ReqHeader: map[string]string{
"Upload-Draft-Interop-Version": "4",
},
Code: http.StatusNoContent,
ResHeader: map[string]string{
"Upload-Draft-Interop-Version": "4",
"Upload-Complete": "?0",
"Upload-Offset": "5",
},
}).Run(handler, t)
})

SubTest(t, "CompleteUpload", func(t *testing.T, store *MockFullDataStore, composer *StoreComposer) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
upload := NewMockFullUpload(ctrl)

gomock.InOrder(
store.EXPECT().GetUpload(gomock.Any(), "yes").Return(upload, nil),
upload.EXPECT().GetInfo(gomock.Any()).Return(FileInfo{
SizeIsDeferred: false,
Size: 10,
Offset: 10,
}, nil),
)

handler, _ := NewHandler(Config{
StoreComposer: composer,
EnableExperimentalProtocol: true,
})

(&httpTest{
Method: "HEAD",
URL: "yes",
ReqHeader: map[string]string{
"Upload-Draft-Interop-Version": "4",
},
Code: http.StatusNoContent,
ResHeader: map[string]string{
"Upload-Draft-Interop-Version": "4",
"Upload-Complete": "?1",
"Upload-Offset": "10",
},
}).Run(handler, t)
})

SubTest(t, "DeferredLength", func(t *testing.T, store *MockFullDataStore, composer *StoreComposer) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
upload := NewMockFullUpload(ctrl)

gomock.InOrder(
store.EXPECT().GetUpload(gomock.Any(), "yes").Return(upload, nil),
upload.EXPECT().GetInfo(gomock.Any()).Return(FileInfo{
SizeIsDeferred: true,
Offset: 5,
}, nil),
)

handler, _ := NewHandler(Config{
StoreComposer: composer,
EnableExperimentalProtocol: true,
})

(&httpTest{
Method: "HEAD",
URL: "yes",
ReqHeader: map[string]string{
"Upload-Draft-Interop-Version": "4",
},
Code: http.StatusNoContent,
ResHeader: map[string]string{
"Upload-Draft-Interop-Version": "4",
"Upload-Complete": "?0",
"Upload-Offset": "5",
},
}).Run(handler, t)
})
}
})
}
Loading

0 comments on commit 9801b91

Please sign in to comment.