-
Notifications
You must be signed in to change notification settings - Fork 113
/
tus.go
117 lines (99 loc) · 3.29 KB
/
tus.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// Copyright 2018-2022 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// In applying this license, CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.
package tus
import (
"net/http"
"github.com/cs3org/reva/pkg/errtypes"
"github.com/cs3org/reva/pkg/rhttp/datatx"
"github.com/cs3org/reva/pkg/rhttp/datatx/manager/registry"
"github.com/cs3org/reva/pkg/rhttp/datatx/utils/download"
"github.com/cs3org/reva/pkg/storage"
"github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
tusd "github.com/tus/tusd/pkg/handler"
)
func init() {
registry.Register("tus", New)
}
type config struct{}
type manager struct {
conf *config
}
func parseConfig(m map[string]interface{}) (*config, error) {
c := &config{}
if err := mapstructure.Decode(m, c); err != nil {
err = errors.Wrap(err, "error decoding conf")
return nil, err
}
return c, nil
}
// New returns a datatx manager implementation that relies on HTTP PUT/GET.
func New(m map[string]interface{}) (datatx.DataTX, error) {
c, err := parseConfig(m)
if err != nil {
return nil, err
}
return &manager{conf: c}, nil
}
func (m *manager) Handler(fs storage.FS) (http.Handler, error) {
composable, ok := fs.(composable)
if !ok {
return nil, errtypes.NotSupported("file system does not support the tus protocol")
}
// A storage backend for tusd may consist of multiple different parts which
// handle upload creation, locking, termination and so on. The composer is a
// place where all those separated pieces are joined together. In this example
// we only use the file store but you may plug in multiple.
composer := tusd.NewStoreComposer()
// let the composable storage tell tus which extensions it supports
composable.UseIn(composer)
config := tusd.Config{
StoreComposer: composer,
}
handler, err := tusd.NewUnroutedHandler(config)
if err != nil {
return nil, err
}
h := handler.Middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
method := r.Method
// https://github.com/tus/tus-resumable-upload-protocol/blob/master/protocol.md#x-http-method-override
if r.Header.Get("X-HTTP-Method-Override") != "" {
method = r.Header.Get("X-HTTP-Method-Override")
}
switch method {
case http.MethodPost:
handler.PostFile(w, r)
case http.MethodHead:
handler.HeadFile(w, r)
case http.MethodPatch:
handler.PatchFile(w, r)
case "DELETE":
handler.DelFile(w, r)
case http.MethodGet:
download.GetOrHeadFile(w, r, fs, "")
default:
w.WriteHeader(http.StatusNotImplemented)
}
}))
return h, nil
}
// Composable is the interface that a struct needs to implement
// to be composable, so that it can support the TUS methods.
type composable interface {
UseIn(composer *tusd.StoreComposer)
}