diff --git a/handler.go b/handler.go index 705d37e..9892525 100644 --- a/handler.go +++ b/handler.go @@ -1,6 +1,7 @@ package tusd import ( + "encoding/base64" "errors" "io" "log" @@ -8,6 +9,7 @@ import ( "net/url" "os" "strconv" + "strings" "github.com/bmizerany/pat" ) @@ -127,7 +129,7 @@ func (handler *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } header.Set("TUS-Version", "1.0.0") - header.Set("TUS-Extension", "file-creation") + header.Set("TUS-Extension", "file-creation,metadata") w.WriteHeader(http.StatusNoContent) return @@ -158,8 +160,8 @@ func (handler *Handler) postFile(w http.ResponseWriter, r *http.Request) { return } - // @TODO: implement metadata extension - meta := make(map[string]string) + // Parse metadata + meta := parseMeta(r.Header.Get("Metadata")) id, err := handler.dataStore.NewUpload(size, meta) if err != nil { @@ -285,3 +287,31 @@ func (handler *Handler) absFileUrl(r *http.Request, id string) string { return url } + +// Parse the meatadata as defined in the Metadata extension. +// e.g. Metadata: key base64value, key2 base64value +func parseMeta(header string) map[string]string { + meta := make(map[string]string) + + for _, element := range strings.Split(header, ",") { + element := strings.TrimSpace(element) + + parts := strings.Split(element, " ") + + // Do not continue with this element if no key and value or presented + if len(parts) != 2 { + continue + } + + // Ignore corrent element if the value is no valid base64 + key := parts[0] + value, err := base64.StdEncoding.DecodeString(parts[1]) + if err != nil { + continue + } + + meta[key] = string(value) + } + + return meta +} diff --git a/handler_test.go b/handler_test.go index ea6dc03..d33b880 100644 --- a/handler_test.go +++ b/handler_test.go @@ -80,7 +80,7 @@ func TestProtocolDiscovery(t *testing.T) { } headers := map[string]string{ - "TUS-Extension": "file-creation", + "TUS-Extension": "file-creation,metadata", "TUS-Version": "1.0.0", "TUS-Resumable": "1.0.0", "TUS-Max-Size": "400", @@ -110,6 +110,19 @@ func (s postStore) NewUpload(size int64, metaData MetaData) (string, error) { if size != 300 { s.t.Errorf("Expected size to be 300 (got %v)", size) } + + if len(metaData) != 2 { + s.t.Errorf("Expected two elements in metadata") + } + + if v := metaData["foo"]; v != "hello" { + s.t.Errorf("Expected foo element to be 'hello' but got %s", v) + } + + if v := metaData["bar"]; v != "world" { + s.t.Errorf("Expected bar element to be 'world' but got %s", v) + } + return "foo", nil } @@ -126,6 +139,7 @@ func TestFileCreation(t *testing.T) { req, _ := http.NewRequest("POST", "", nil) req.Header.Set("TUS-Resumable", "1.0.0") req.Header.Set("Entity-Length", "300") + req.Header.Set("Metadata", "foo aGVsbG8=, bar d29ybGQ=") req.Host = "tus.io" w := httptest.NewRecorder() handler.ServeHTTP(w, req)