-
Notifications
You must be signed in to change notification settings - Fork 477
/
config.go
195 lines (178 loc) · 9.25 KB
/
config.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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
package handler
import (
"errors"
"net/url"
"regexp"
"time"
"golang.org/x/exp/slog"
)
// Config provides a way to configure the Handler depending on your needs.
type Config struct {
// StoreComposer points to the store composer from which the core data store
// and optional dependencies should be taken. May only be nil if DataStore is
// set.
StoreComposer *StoreComposer
// MaxSize defines how many bytes may be stored in one single upload. If its
// value is is 0 or smaller no limit will be enforced.
MaxSize int64
// BasePath defines the URL path used for handling uploads, e.g. "/files/".
// If no trailing slash is presented it will be added. You may specify an
// absolute URL containing a scheme, e.g. "http://tus.io"
BasePath string
isAbs bool
// EnableExperimentalProtocol controls whether the new resumable upload protocol draft
// from the IETF's HTTP working group is accepted next to the current tus v1 protocol.
// See https://datatracker.ietf.org/doc/draft-ietf-httpbis-resumable-upload/
EnableExperimentalProtocol 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
// Cors can be used to customize the handling of Cross-Origin Resource Sharing (CORS).
// See the CorsConfig struct for more details.
// Defaults to DefaultCorsConfig.
Cors *CorsConfig
// NotifyCompleteUploads indicates whether sending notifications about
// completed uploads using the CompleteUploads channel should be enabled.
NotifyCompleteUploads bool
// NotifyTerminatedUploads indicates whether sending notifications about
// terminated uploads using the TerminatedUploads channel should be enabled.
NotifyTerminatedUploads bool
// NotifyUploadProgress indicates whether sending notifications about
// the upload progress using the UploadProgress channel should be enabled.
NotifyUploadProgress bool
// NotifyCreatedUploads indicates whether sending notifications about
// the upload having been created using the CreatedUploads channel should be enabled.
NotifyCreatedUploads bool
// UploadProgressInterval specifies the interval at which the upload progress
// notifications are sent to the UploadProgress channel, if enabled.
// Defaults to 1s.
UploadProgressInterval time.Duration
// Logger is the logger to use internally, mostly for printing requests.
Logger *slog.Logger
// Respect the X-Forwarded-Host, X-Forwarded-Proto and Forwarded headers
// potentially set by proxies when generating an absolute URL in the
// response to POST requests.
RespectForwardedHeaders bool
// PreUploadCreateCallback will be invoked before a new upload is created, if the
// property is supplied. If the callback returns no error, the upload will be created
// and optional values from HTTPResponse will be contained in the HTTP response.
// If the error is non-nil, the upload will not be created. This can be used to implement
// validation of upload metadata etc. Furthermore, HTTPResponse will be ignored and
// the error value can contain values for the HTTP response.
// If the error is nil, FileInfoChanges can be filled out to specify individual properties
// that should be overwriten before the upload is create. See its type definition for
// more details on its behavior. If you do not want to make any changes, return an empty struct.
PreUploadCreateCallback func(hook HookEvent) (HTTPResponse, FileInfoChanges, error)
// PreFinishResponseCallback will be invoked after an upload is completed but before
// a response is returned to the client. This can be used to implement post-processing validation.
// If the callback returns no error, optional values from HTTPResponse will be contained in the HTTP response.
// If the error is non-nil, the error will be forwarded to the client. Furthermore,
// HTTPResponse will be ignored and the error value can contain values for the HTTP response.
PreFinishResponseCallback func(hook HookEvent) (HTTPResponse, error)
// GracefulRequestCompletionTimeout is the timeout for operations to complete after an HTTP
// request has ended (successfully or by error). For example, if an HTTP request is interrupted,
// instead of stopping immediately, the handler and data store will be given some additional
// time to wrap up their operations and save any uploaded data. GracefulRequestCompletionTimeout
// controls this time.
// See HookEvent.Context for more details.
// Defaults to 10s.
GracefulRequestCompletionTimeout time.Duration
// AcquireLockTimeout is the duration that a request handler will wait to acquire a lock for
// an upload. If the timeout is reached, it will stop waiting and send an error response to the
// client.
// Defaults to 20s.
AcquireLockTimeout time.Duration
// NetworkTimeout is the timeout for individual read operations on the request body. If the
// read operation succeeds in this time window, the handler will continue consuming the body.
// If a read operation times out, the handler will stop reading and close the request.
// This ensures that an upload is consumed while data is being transmitted, while also closing
// dead connections.
// Under the hood, this is passed to ResponseController.SetReadDeadline
// Defaults to 60s
NetworkTimeout time.Duration
}
// CorsConfig provides a way to customize the the handling of Cross-Origin Resource Sharing (CORS).
// More details about CORS are available at https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS.
type CorsConfig struct {
// Disable instructs the handler to ignore all CORS-related headers and never set a
// CORS-related header in a response. This is useful if CORS is already handled by a proxy.
Disable bool
// AllowOrigin is a regular expression used to check if a request is allowed to participate in the
// CORS protocol. If the request's Origin header matches the regular expression, CORS is allowed.
// If not, a 403 Forbidden response is sent, rejecting the CORS request.
AllowOrigin *regexp.Regexp
// AllowCredentials defines whether the `Access-Control-Allow-Credentials: true` header should be
// included in CORS responses. This allows clients to share credentials using the Cookie and
// Authorization header
AllowCredentials bool
// AllowMethods defines the value for the `Access-Control-Allow-Methods` header in the response to
// preflight requests. You can add custom methods here, but make sure that all tus-specific methods
// from DefaultConfig.AllowMethods are included as well.
AllowMethods string
// AllowHeaders defines the value for the `Access-Control-Allow-Headers` header in the response to
// preflight requests. You can add custom headers here, but make sure that all tus-specific header
// from DefaultConfig.AllowHeaders are included as well.
AllowHeaders string
// MaxAge defines the value for the `Access-Control-Max-Age` header in the response to preflight
// requests.
MaxAge string
// ExposeHeaders defines the value for the `Access-Control-Expose-Headers` header in the response to
// actual requests. You can add custom headers here, but make sure that all tus-specific header
// from DefaultConfig.ExposeHeaders are included as well.
ExposeHeaders string
}
// DefaultCorsConfig is the configuration that will be used in none is provided.
var DefaultCorsConfig = CorsConfig{
Disable: false,
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-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-Incomplete, Upload-Complete, Upload-Draft-Interop-Version",
}
func (config *Config) validate() error {
if config.Logger == nil {
config.Logger = slog.Default()
}
base := config.BasePath
uri, err := url.Parse(base)
if err != nil {
return err
}
// Ensure base path ends with slash to remove logic from absFileURL
if base != "" && string(base[len(base)-1]) != "/" {
base += "/"
}
// Ensure base path begins with slash if not absolute (starts with scheme)
if !uri.IsAbs() && len(base) > 0 && string(base[0]) != "/" {
base = "/" + base
}
config.BasePath = base
config.isAbs = uri.IsAbs()
if config.StoreComposer == nil {
return errors.New("tusd: StoreComposer must no be nil")
}
if config.StoreComposer.Core == nil {
return errors.New("tusd: StoreComposer in Config needs to contain a non-nil core")
}
if config.UploadProgressInterval <= 0 {
config.UploadProgressInterval = 1 * time.Second
}
if config.GracefulRequestCompletionTimeout <= 0 {
config.GracefulRequestCompletionTimeout = 10 * time.Second
}
if config.AcquireLockTimeout <= 0 {
config.AcquireLockTimeout = 20 * time.Second
}
if config.NetworkTimeout <= 0 {
config.NetworkTimeout = 60 * time.Second
}
if config.Cors == nil {
config.Cors = &DefaultCorsConfig
}
return nil
}