tus-server 2.2.1 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +117 -85
- data/README.md +61 -28
- data/lib/tus/info.rb +9 -1
- data/lib/tus/server.rb +42 -63
- data/lib/tus/storage/filesystem.rb +0 -3
- data/lib/tus/storage/gridfs.rb +1 -4
- data/lib/tus/storage/s3.rb +58 -52
- data/tus-server.gemspec +3 -3
- metadata +12 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c07ca8df0a0b881580058e119e27a4cf63efbd0854018d00d8f3cd3f7a093b04
|
4
|
+
data.tar.gz: ea0da9293bee4cee32f77ce5383adc389d34d745a025a01d570ff971b21f2a0d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1284b1b2af5e29ccbd5ae20658da75f0ad8de5d11c2198ed98704f120aa8ebcbe6f9a9815d728d518dd12ea16046725733055a3868b8a2e0685985fedca4fa4f
|
7
|
+
data.tar.gz: 0a9779bc5f55e685329a7cc76ed071ecf4e73b574609da3db298303697da898cd32d4a7da3e41f4e7ef59b273abfd69c79f03ec9aecf94d754ef6ccbbcdb08cf
|
data/CHANGELOG.md
CHANGED
@@ -1,120 +1,152 @@
|
|
1
|
+
## 2.3.0 (2019-05-14)
|
2
|
+
|
3
|
+
* Allow uploading files larger than 50 GB to S3 storage by scaling the part size according to upload length (@janko)
|
4
|
+
|
5
|
+
* Allow S3 limits to be overriden via the `:limits` option (@janko)
|
6
|
+
|
7
|
+
* Reject uploads larger than 5 TB in `S3#create_file` (@janko)
|
8
|
+
|
9
|
+
* Remove superfluous `#head_object` operation from `S3#concatenate` (@janko)
|
10
|
+
|
11
|
+
* Validate that partial uploads are finished on the concatenation request (@janko)
|
12
|
+
|
13
|
+
* Unparallelize validating partial uploads for concatentation (@janko)
|
14
|
+
|
15
|
+
* Move total length calculation for concatenation into `Tus::Server` (@janko)
|
16
|
+
|
17
|
+
* Allow `Upload-Concat` and `Upload-Defer-Length` headers in CORS headers (@janko)
|
18
|
+
|
19
|
+
* Always override `:content_disposition` option with the value from `:upload_options` in `S3#create_file` (@janko)
|
20
|
+
|
21
|
+
* Apply `name`/`type` metadata to `:content_type`/`:content_disposition` options in `S3#create_file` (@janko)
|
22
|
+
|
23
|
+
* Use `content_disposition` gem for `:content_disposition` option in `S3#create_file` (@janko)
|
24
|
+
|
25
|
+
* Remove checks whether multipart upload was successfully aborted in S3 storage (@janko)
|
26
|
+
|
27
|
+
* Don't return any `Content-Type` when type is not specified in metadata (@janko)
|
28
|
+
|
29
|
+
* Add `ETag` header to download endpoint to prevent `Rack::ETag` buffering file content (@janko)
|
30
|
+
|
31
|
+
* Take `:prefix` into account in `Tus::Storage::S3#expire_files` (@janko)
|
32
|
+
|
1
33
|
## 2.2.1 (2018-12-19)
|
2
34
|
|
3
|
-
* Use `content_disposition` gem to generate `Content-Disposition` in download endpoint (@janko
|
35
|
+
* Use `content_disposition` gem to generate `Content-Disposition` in download endpoint (@janko)
|
4
36
|
|
5
37
|
## 2.2.0 (2018-12-02)
|
6
38
|
|
7
|
-
* Add `before_create`, `after_create`, `after_finish`, and `after_terminate` hooks (@janko
|
39
|
+
* Add `before_create`, `after_create`, `after_finish`, and `after_terminate` hooks (@janko)
|
8
40
|
|
9
|
-
* Rename `Tus::Info#concatenation?` to `Tus::Info#final?` (@janko
|
41
|
+
* Rename `Tus::Info#concatenation?` to `Tus::Info#final?` (@janko)
|
10
42
|
|
11
|
-
* Use `Storage#concurrency` for parallelized retrieval of partial uploads in `Upload-Concat` validation (@janko
|
43
|
+
* Use `Storage#concurrency` for parallelized retrieval of partial uploads in `Upload-Concat` validation (@janko)
|
12
44
|
|
13
|
-
* Replace `:thread_count` with `:concurrency` in S3 storage (@janko
|
45
|
+
* Replace `:thread_count` with `:concurrency` in S3 storage (@janko)
|
14
46
|
|
15
|
-
* Validate that sum of partial uploads doesn't exceed `Tus-Max-Size` on concatenation (@janko
|
47
|
+
* Validate that sum of partial uploads doesn't exceed `Tus-Max-Size` on concatenation (@janko)
|
16
48
|
|
17
|
-
* Drop MRI 2.2 support (@janko
|
49
|
+
* Drop MRI 2.2 support (@janko)
|
18
50
|
|
19
|
-
* Accept absolute URLs of partial uploads when creating a final upload (@janko
|
51
|
+
* Accept absolute URLs of partial uploads when creating a final upload (@janko)
|
20
52
|
|
21
53
|
## 2.1.2 (2018-10-21)
|
22
54
|
|
23
|
-
* Make tus-ruby-server fully work with non-rewindable Rack input (@janko
|
55
|
+
* Make tus-ruby-server fully work with non-rewindable Rack input (@janko)
|
24
56
|
|
25
57
|
## 2.1.1 (2018-05-26)
|
26
58
|
|
27
|
-
* Rename `:download_url` option to `:redirect_download` (@janko
|
59
|
+
* Rename `:download_url` option to `:redirect_download` (@janko)
|
28
60
|
|
29
61
|
## 2.1.0 (2018-05-15)
|
30
62
|
|
31
|
-
* Add `:download_url` server option for redirecting to a download URL (@janko
|
63
|
+
* Add `:download_url` server option for redirecting to a download URL (@janko)
|
32
64
|
|
33
|
-
* Allow application servers to serve files stored on disk via the `Rack::Sendfile` middleware (@janko
|
65
|
+
* Allow application servers to serve files stored on disk via the `Rack::Sendfile` middleware (@janko)
|
34
66
|
|
35
|
-
* Reject `Upload-Metadata` which contains key-value pairs separated by spaces (@janko
|
67
|
+
* Reject `Upload-Metadata` which contains key-value pairs separated by spaces (@janko)
|
36
68
|
|
37
|
-
* Don't overwite info file if it already exists in `Tus::Storage::FileSystem` (@janko
|
69
|
+
* Don't overwite info file if it already exists in `Tus::Storage::FileSystem` (@janko)
|
38
70
|
|
39
71
|
## 2.0.2 (2017-12-24)
|
40
72
|
|
41
|
-
* Handle `name` and `type` metadata for Uppy compatibility (@janko
|
73
|
+
* Handle `name` and `type` metadata for Uppy compatibility (@janko)
|
42
74
|
|
43
75
|
## 2.0.1 (2017-11-13)
|
44
76
|
|
45
|
-
* Add back support for Roda 2.x (@janko
|
77
|
+
* Add back support for Roda 2.x (@janko)
|
46
78
|
|
47
79
|
## 2.0.0 (2017-11-13)
|
48
80
|
|
49
|
-
* Upgrade to Roda 3 (@janko
|
81
|
+
* Upgrade to Roda 3 (@janko)
|
50
82
|
|
51
|
-
* Remove deprecated support for aws-sdk 2.x in `Tus::Storage::S3` (@janko
|
83
|
+
* Remove deprecated support for aws-sdk 2.x in `Tus::Storage::S3` (@janko)
|
52
84
|
|
53
|
-
* Drop official support for MRI 2.1 (@janko
|
85
|
+
* Drop official support for MRI 2.1 (@janko)
|
54
86
|
|
55
|
-
* Add generic `Tus::Response` class that storages can use (@janko
|
87
|
+
* Add generic `Tus::Response` class that storages can use (@janko)
|
56
88
|
|
57
|
-
* Remove `Tus::Response#length` (@janko
|
89
|
+
* Remove `Tus::Response#length` (@janko)
|
58
90
|
|
59
|
-
* Remove deprecated Goliath integration (@janko
|
91
|
+
* Remove deprecated Goliath integration (@janko)
|
60
92
|
|
61
|
-
* Return `400 Bad Request` instead of `404 Not Found` when some partial uploads are missing in a concatenation request (@janko
|
93
|
+
* Return `400 Bad Request` instead of `404 Not Found` when some partial uploads are missing in a concatenation request (@janko)
|
62
94
|
|
63
|
-
* Use Rack directly instead of Roda's `streaming` plugin for downloding (@janko
|
95
|
+
* Use Rack directly instead of Roda's `streaming` plugin for downloding (@janko)
|
64
96
|
|
65
97
|
## 1.2.1 (2017-11-05)
|
66
98
|
|
67
|
-
* Improve communication when handling `aws-sdk 2.x` fallback in `Tus::Storage::S3` (@janko
|
99
|
+
* Improve communication when handling `aws-sdk 2.x` fallback in `Tus::Storage::S3` (@janko)
|
68
100
|
|
69
101
|
## 1.2.0 (2017-09-18)
|
70
102
|
|
71
|
-
* Deprecate `aws-sdk` 2.x in favour of the new `aws-sdk-s3` gem (@janko
|
103
|
+
* Deprecate `aws-sdk` 2.x in favour of the new `aws-sdk-s3` gem (@janko)
|
72
104
|
|
73
105
|
## 1.1.3 (2017-09-17)
|
74
106
|
|
75
|
-
* Return `Accept-Ranges: bytes` response header in download endpoint (@janko
|
107
|
+
* Return `Accept-Ranges: bytes` response header in download endpoint (@janko)
|
76
108
|
|
77
109
|
## 1.1.2 (2017-09-12)
|
78
110
|
|
79
|
-
* Add support for the new `aws-sdk-s3` gem (@janko
|
111
|
+
* Add support for the new `aws-sdk-s3` gem (@janko)
|
80
112
|
|
81
113
|
## 1.1.1 (2017-07-23)
|
82
114
|
|
83
|
-
* Restore backwards compatibility with MRI 2.1 and MRI 2.2 that was broken in previous release (@janko
|
115
|
+
* Restore backwards compatibility with MRI 2.1 and MRI 2.2 that was broken in previous release (@janko)
|
84
116
|
|
85
117
|
## 1.1.0 (2017-07-23)
|
86
118
|
|
87
|
-
* Ignore retryable networking errors in `Tus::Storage::S3#patch_file` for resiliency (@janko
|
119
|
+
* Ignore retryable networking errors in `Tus::Storage::S3#patch_file` for resiliency (@janko)
|
88
120
|
|
89
|
-
* Deprecate `Tus::Server::Goliath` in favour of [goliath-rack_proxy](https://github.com/janko
|
121
|
+
* Deprecate `Tus::Server::Goliath` in favour of [goliath-rack_proxy](https://github.com/janko/goliath-rack_proxy) (@janko)
|
90
122
|
|
91
|
-
* Reduce string allocations in MRI 2.3+ with `frozen-string-literal: true` magic comments (@janko
|
123
|
+
* Reduce string allocations in MRI 2.3+ with `frozen-string-literal: true` magic comments (@janko)
|
92
124
|
|
93
125
|
## 1.0.0 (2017-07-17)
|
94
126
|
|
95
|
-
* Add Goliath integration (@janko
|
127
|
+
* Add Goliath integration (@janko)
|
96
128
|
|
97
|
-
* [BREAKING] Save data in `"#{uid}"` instead of `"#{uid}.file"` in `Tus::Storage::Filesystem` (@janko
|
129
|
+
* [BREAKING] Save data in `"#{uid}"` instead of `"#{uid}.file"` in `Tus::Storage::Filesystem` (@janko)
|
98
130
|
|
99
|
-
* Modify S3 storage to cache chunks into memory instead of disk, which reduces disk IO (@janko
|
131
|
+
* Modify S3 storage to cache chunks into memory instead of disk, which reduces disk IO (@janko)
|
100
132
|
|
101
|
-
* [BREAKING] Require each storage to return the number of bytes uploaded in `#patch_file` (@janko
|
133
|
+
* [BREAKING] Require each storage to return the number of bytes uploaded in `#patch_file` (@janko)
|
102
134
|
|
103
|
-
* Make S3 storage upload all received data from `tus-js-client` that doesn't have max chunk size configured (@janko
|
135
|
+
* Make S3 storage upload all received data from `tus-js-client` that doesn't have max chunk size configured (@janko)
|
104
136
|
|
105
|
-
* Verify that all partial uploads have `Upload-Concat: partial` before concatenation (@janko
|
137
|
+
* Verify that all partial uploads have `Upload-Concat: partial` before concatenation (@janko)
|
106
138
|
|
107
|
-
* Include CORS and tus response headers in 404 responses (@janko
|
139
|
+
* Include CORS and tus response headers in 404 responses (@janko)
|
108
140
|
|
109
|
-
* Improve streaming on dynamic Rack inputs such as `Unicorn::TeeInput` for S3 and Gridfs storage (@janko
|
141
|
+
* Improve streaming on dynamic Rack inputs such as `Unicorn::TeeInput` for S3 and Gridfs storage (@janko)
|
110
142
|
|
111
|
-
* Terminate HTTP connection to S3 when response is closed (@janko
|
143
|
+
* Terminate HTTP connection to S3 when response is closed (@janko)
|
112
144
|
|
113
|
-
* Allow `Transfer-Encoding: chunked` to be used, meaning `Content-Length` can be blank (@janko
|
145
|
+
* Allow `Transfer-Encoding: chunked` to be used, meaning `Content-Length` can be blank (@janko)
|
114
146
|
|
115
|
-
* Remove newlines from the base64-encoded CRC32 signature (@janko
|
147
|
+
* Remove newlines from the base64-encoded CRC32 signature (@janko)
|
116
148
|
|
117
|
-
* Lazily require `digest`, `zlib`, and `base64` standard libraries (@janko
|
149
|
+
* Lazily require `digest`, `zlib`, and `base64` standard libraries (@janko)
|
118
150
|
|
119
151
|
## 0.10.2 (2017-04-19)
|
120
152
|
|
@@ -122,94 +154,94 @@
|
|
122
154
|
|
123
155
|
## 0.10.1 (2017-04-13)
|
124
156
|
|
125
|
-
* Fix download endpoint returning incorrect response body in some cases in development (@janko
|
157
|
+
* Fix download endpoint returning incorrect response body in some cases in development (@janko)
|
126
158
|
|
127
|
-
* Remove `concatenation-unfinished` from list of supported extensions (@janko
|
159
|
+
* Remove `concatenation-unfinished` from list of supported extensions (@janko)
|
128
160
|
|
129
161
|
## 0.10.0 (2017-03-27)
|
130
162
|
|
131
|
-
* Fix invalid `Content-Disposition` header in GET requests to due mutation of `Tus::Server.opts[:disposition]` (@janko
|
163
|
+
* Fix invalid `Content-Disposition` header in GET requests to due mutation of `Tus::Server.opts[:disposition]` (@janko)
|
132
164
|
|
133
|
-
* Make `Response` object from `Tus::Server::S3` also respond to `#close` (@janko
|
165
|
+
* Make `Response` object from `Tus::Server::S3` also respond to `#close` (@janko)
|
134
166
|
|
135
|
-
* Don't return `Content-Type` header when there is no content returned (@janko
|
167
|
+
* Don't return `Content-Type` header when there is no content returned (@janko)
|
136
168
|
|
137
|
-
* Return `Content-Type: text/plain` when returning errors (@janko
|
169
|
+
* Return `Content-Type: text/plain` when returning errors (@janko)
|
138
170
|
|
139
|
-
* Return `Content-Type: application/octet-stream` by default in the GET endpoint (@janko
|
171
|
+
* Return `Content-Type: application/octet-stream` by default in the GET endpoint (@janko)
|
140
172
|
|
141
|
-
* Make UNIX permissions configurable via `:permissions` and `:directory_permissions` in `Tus::Storage::Filesystem` (@janko
|
173
|
+
* Make UNIX permissions configurable via `:permissions` and `:directory_permissions` in `Tus::Storage::Filesystem` (@janko)
|
142
174
|
|
143
|
-
* Apply UNIX permissions `0644` for files and `0777` for directories in `Tus::Storage::Filesystem` (@janko
|
175
|
+
* Apply UNIX permissions `0644` for files and `0777` for directories in `Tus::Storage::Filesystem` (@janko)
|
144
176
|
|
145
|
-
* Fix `creation-defer-length` feature not working with unlimited upload size (@janko
|
177
|
+
* Fix `creation-defer-length` feature not working with unlimited upload size (@janko)
|
146
178
|
|
147
|
-
* Make the filesize of accepted uploads unlimited by default (@janko
|
179
|
+
* Make the filesize of accepted uploads unlimited by default (@janko)
|
148
180
|
|
149
|
-
* Modify tus server to call `Storage#finalize_file` when the last chunk was uploaded (@janko
|
181
|
+
* Modify tus server to call `Storage#finalize_file` when the last chunk was uploaded (@janko)
|
150
182
|
|
151
|
-
* Don't require length of uploaded chunks to be a multiple of `:chunkSize` in `Tus::Storage::Gridfs` (@janko
|
183
|
+
* Don't require length of uploaded chunks to be a multiple of `:chunkSize` in `Tus::Storage::Gridfs` (@janko)
|
152
184
|
|
153
|
-
* Don't infer `:chunkSize` from first uploaded chunk in `Tus::Storage::Gridfs` (@janko
|
185
|
+
* Don't infer `:chunkSize` from first uploaded chunk in `Tus::Storage::Gridfs` (@janko)
|
154
186
|
|
155
|
-
* Add `#length` to `Response` objects returned from `Storage#get_file` (@janko
|
187
|
+
* Add `#length` to `Response` objects returned from `Storage#get_file` (@janko)
|
156
188
|
|
157
189
|
## 0.9.1 (2017-03-24)
|
158
190
|
|
159
|
-
* Fix `Tus::Storage::S3` not properly supporting the concatenation feature (@janko
|
191
|
+
* Fix `Tus::Storage::S3` not properly supporting the concatenation feature (@janko)
|
160
192
|
|
161
193
|
## 0.9.0 (2017-03-24)
|
162
194
|
|
163
|
-
* Add Amazon S3 storage under `Tus::Storage::S3` (@janko
|
195
|
+
* Add Amazon S3 storage under `Tus::Storage::S3` (@janko)
|
164
196
|
|
165
|
-
* Make the checksum feature actually work by generating the checksum correctly (@janko
|
197
|
+
* Make the checksum feature actually work by generating the checksum correctly (@janko)
|
166
198
|
|
167
|
-
* Make `Content-Disposition` header on the GET endpoint configurable (@janko
|
199
|
+
* Make `Content-Disposition` header on the GET endpoint configurable (@janko)
|
168
200
|
|
169
|
-
* Change `Content-Disposition` header on the GET endpoint from "attachment" to "inline" (@janko
|
201
|
+
* Change `Content-Disposition` header on the GET endpoint from "attachment" to "inline" (@janko)
|
170
202
|
|
171
|
-
* Delegate concatenation logic to individual storages, allowing the storages to implement it much more efficiently (@janko
|
203
|
+
* Delegate concatenation logic to individual storages, allowing the storages to implement it much more efficiently (@janko)
|
172
204
|
|
173
|
-
* Allow storages to save additional information in the info hash (@janko
|
205
|
+
* Allow storages to save additional information in the info hash (@janko)
|
174
206
|
|
175
|
-
* Don't automatically delete expired files, instead require the developer to call `Storage#expire_files` in a recurring task (@janko
|
207
|
+
* Don't automatically delete expired files, instead require the developer to call `Storage#expire_files` in a recurring task (@janko)
|
176
208
|
|
177
|
-
* Delegate expiration logic to the individual storages, allowing the storages to implement it much more efficiently (@janko
|
209
|
+
* Delegate expiration logic to the individual storages, allowing the storages to implement it much more efficiently (@janko)
|
178
210
|
|
179
|
-
* Modify storages to raise `Tus::NotFound` when file wasn't found (@janko
|
211
|
+
* Modify storages to raise `Tus::NotFound` when file wasn't found (@janko)
|
180
212
|
|
181
|
-
* Add `Tus::Error` which storages can use (@janko
|
213
|
+
* Add `Tus::Error` which storages can use (@janko)
|
182
214
|
|
183
|
-
* In `Tus::Storage::Gridfs` require that each uploaded chunk except the last one can be distributed into even Mongo chunks (@janko
|
215
|
+
* In `Tus::Storage::Gridfs` require that each uploaded chunk except the last one can be distributed into even Mongo chunks (@janko)
|
184
216
|
|
185
|
-
* Return `403 Forbidden` in the GET endpoint when attempting to download an unfinished upload (@janko
|
217
|
+
* Return `403 Forbidden` in the GET endpoint when attempting to download an unfinished upload (@janko)
|
186
218
|
|
187
|
-
* Allow client to send `Upload-Length` on any PATCH request when `Upload-Defer-Length` is used (@janko
|
219
|
+
* Allow client to send `Upload-Length` on any PATCH request when `Upload-Defer-Length` is used (@janko)
|
188
220
|
|
189
|
-
* Support `Range` requests in the GET endpoint (@janko
|
221
|
+
* Support `Range` requests in the GET endpoint (@janko)
|
190
222
|
|
191
|
-
* Stream file content in the GET endpoint directly from the storage (@janko
|
223
|
+
* Stream file content in the GET endpoint directly from the storage (@janko)
|
192
224
|
|
193
|
-
* Update `:length`, `:uploadDate` and `:contentType` Mongo fields on each PATCH request (@janko
|
225
|
+
* Update `:length`, `:uploadDate` and `:contentType` Mongo fields on each PATCH request (@janko)
|
194
226
|
|
195
|
-
* Insert all sub-chunks in a single Mongo operation in `Tus::Storage::Gridfs` (@janko
|
227
|
+
* Insert all sub-chunks in a single Mongo operation in `Tus::Storage::Gridfs` (@janko)
|
196
228
|
|
197
|
-
* Infer Mongo chunk size from the size of the first uploaded chunk (@janko
|
229
|
+
* Infer Mongo chunk size from the size of the first uploaded chunk (@janko)
|
198
230
|
|
199
|
-
* Add `:chunk_size` option to `Tus::Storage::Gridfs` (@janko
|
231
|
+
* Add `:chunk_size` option to `Tus::Storage::Gridfs` (@janko)
|
200
232
|
|
201
|
-
* Avoid reading the whole request body into memory by doing streaming uploads (@janko
|
233
|
+
* Avoid reading the whole request body into memory by doing streaming uploads (@janko)
|
202
234
|
|
203
235
|
## 0.2.0 (2016-11-23)
|
204
236
|
|
205
|
-
* Refresh `Upload-Expires` for the file after each PATCH request (@janko
|
237
|
+
* Refresh `Upload-Expires` for the file after each PATCH request (@janko)
|
206
238
|
|
207
239
|
## 0.1.1 (2016-11-21)
|
208
240
|
|
209
|
-
* Support Rack 1.x in addition to Rack 2.x (@janko
|
241
|
+
* Support Rack 1.x in addition to Rack 2.x (@janko)
|
210
242
|
|
211
|
-
* Don't return 404 when deleting a non-existing file (@janko
|
243
|
+
* Don't return 404 when deleting a non-existing file (@janko)
|
212
244
|
|
213
|
-
* Return 204 for OPTIONS requests even when the file is missing (@janko
|
245
|
+
* Return 204 for OPTIONS requests even when the file is missing (@janko)
|
214
246
|
|
215
|
-
* Make sure that none of the "empty status codes" return content (@janko
|
247
|
+
* Make sure that none of the "empty status codes" return content (@janko)
|
data/README.md
CHANGED
@@ -206,57 +206,90 @@ Tus::Server.opts[:storage] = Tus::Storage::S3.new(
|
|
206
206
|
)
|
207
207
|
```
|
208
208
|
|
209
|
-
|
210
|
-
|
211
|
-
specify on your tus client if you want to use the S3 storage.
|
209
|
+
If you want to files to be stored in a certain subdirectory, you can specify
|
210
|
+
a `:prefix` in the storage configuration.
|
212
211
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
212
|
+
```rb
|
213
|
+
Tus::Storage::S3.new(prefix: "tus", **options)
|
214
|
+
```
|
215
|
+
|
216
|
+
You can also specify additional options that will be fowarded to
|
217
|
+
[`Aws::S3::Client#create_multipart_upload`] using `:upload_options`.
|
217
218
|
|
218
219
|
```rb
|
219
|
-
Tus::
|
220
|
+
Tus::Storage::S3.new(upload_options: { acl: "public-read" }, **options)
|
220
221
|
```
|
221
222
|
|
222
|
-
|
223
|
-
to `:redirect_download`, which will then be evaluated in the context of the
|
224
|
-
`Tus::Server` instance (which allows accessing the `request` object). See
|
225
|
-
[`Aws::S3::Object#get`] for the list of options that
|
226
|
-
`Tus::Storage::S3#file_url` accepts.
|
223
|
+
All other options will be forwarded to [`Aws::S3::Client#initialize`]:
|
227
224
|
|
228
225
|
```rb
|
229
|
-
Tus::
|
230
|
-
|
231
|
-
|
226
|
+
Tus::Storage::S3.new(
|
227
|
+
use_accelerate_endpoint: true,
|
228
|
+
logger: Logger.new(STDOUT),
|
229
|
+
retry_limit: 5,
|
230
|
+
http_open_timeout: 10,
|
231
|
+
# ...
|
232
|
+
)
|
232
233
|
```
|
233
234
|
|
234
|
-
If you
|
235
|
-
|
235
|
+
If you're using [concatenation], you can specify the concurrency in which S3
|
236
|
+
storage will copy partial uploads to the final upload (defaults to `10`):
|
236
237
|
|
237
238
|
```rb
|
238
|
-
Tus::Storage::S3.new(
|
239
|
+
Tus::Storage::S3.new(concurrency: { concatenation: 20 }, **options)
|
239
240
|
```
|
240
241
|
|
241
|
-
|
242
|
-
|
242
|
+
#### Limits
|
243
|
+
|
244
|
+
Be aware that the AWS S3 Multipart Upload API has the following limits:
|
245
|
+
|
246
|
+
| Item | Specification |
|
247
|
+
| ---- | ------------- |
|
248
|
+
| Part size | 5 MB to 5 GB, last part can be < 5 MB |
|
249
|
+
| Maximum number of parts per upload | 10,000 |
|
250
|
+
| Maximum object size | 5 TB |
|
251
|
+
|
252
|
+
This means that if you're chunking uploads in your tus client, the chunk size
|
253
|
+
needs to be **5 MB or larger**. Furthermore, if you're allowing your users to
|
254
|
+
upload files larger than 50 GB, you will the minimum chunk size needs to be
|
255
|
+
higher (`ceil(max_length, max_multipart_parts)`). Note that chunking is
|
256
|
+
optional if you're running on Falcon, but it's mandatory if you're using Puma
|
257
|
+
or another web server.
|
258
|
+
|
259
|
+
`Tus::Storage::S3` is relying on the above limits for determining the multipart
|
260
|
+
part size. If you're using a different S3-compatible service which has different
|
261
|
+
limits, you should pass them in when initializing the storage:
|
243
262
|
|
244
263
|
```rb
|
245
|
-
Tus::Storage::S3.new(
|
264
|
+
Tus::Storage::S3.new(limits: {
|
265
|
+
min_part_size: 5 * 1024 * 1024,
|
266
|
+
max_part_size: 5 * 1024 * 1024 * 1024,
|
267
|
+
max_multipart_parts: 10_000,
|
268
|
+
max_object_size: 5 * 1024 * 1024 * 1024,
|
269
|
+
}, **options)
|
246
270
|
```
|
247
271
|
|
248
|
-
|
249
|
-
|
272
|
+
#### Serving files
|
273
|
+
|
274
|
+
If you'll be retrieving uploaded files through the tus server app, it's
|
275
|
+
recommended to set `Tus::Server.opts[:redirect_download]` to `true`. This will
|
276
|
+
avoid tus server downloading and serving the file from S3, and instead have the
|
277
|
+
download endpoint redirect to the direct S3 object URL.
|
250
278
|
|
251
279
|
```rb
|
252
|
-
Tus::
|
280
|
+
Tus::Server.opts[:redirect_download] = true
|
253
281
|
```
|
254
282
|
|
255
|
-
|
256
|
-
|
283
|
+
You can customize how the S3 object URL is being generated by passing a block
|
284
|
+
to `:redirect_download`, which will then be evaluated in the context of the
|
285
|
+
`Tus::Server` instance (which allows accessing the `request` object). See
|
286
|
+
[`Aws::S3::Object#get`] for the list of options that
|
287
|
+
`Tus::Storage::S3#file_url` accepts.
|
257
288
|
|
258
289
|
```rb
|
259
|
-
Tus::
|
290
|
+
Tus::Server.opts[:redirect_download] = -> (uid, info, **options) do
|
291
|
+
storage.file_url(uid, info, expires_in: 10, **options) # link expires after 10 seconds
|
292
|
+
end
|
260
293
|
```
|
261
294
|
|
262
295
|
### Google Cloud Storage, Microsoft Azure Blob Storage
|
data/lib/tus/info.rb
CHANGED
@@ -40,13 +40,21 @@ module Tus
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def offset
|
43
|
-
Integer(@hash["Upload-Offset"])
|
43
|
+
Integer(@hash["Upload-Offset"]) if @hash["Upload-Offset"]
|
44
44
|
end
|
45
45
|
|
46
46
|
def metadata
|
47
47
|
parse_metadata(@hash["Upload-Metadata"])
|
48
48
|
end
|
49
49
|
|
50
|
+
def name
|
51
|
+
metadata["name"] || metadata["filename"]
|
52
|
+
end
|
53
|
+
|
54
|
+
def type
|
55
|
+
metadata["type"] || metadata["content_type"]
|
56
|
+
end
|
57
|
+
|
50
58
|
def expires
|
51
59
|
Time.parse(@hash["Upload-Expires"])
|
52
60
|
end
|
data/lib/tus/server.rb
CHANGED
@@ -94,9 +94,9 @@ module Tus
|
|
94
94
|
before_create(uid, info)
|
95
95
|
|
96
96
|
if info.final?
|
97
|
-
validate_partial_uploads!(info.partial_uploads)
|
97
|
+
length = validate_partial_uploads!(info.partial_uploads)
|
98
98
|
|
99
|
-
|
99
|
+
storage.concatenate(uid, info.partial_uploads, info.to_h)
|
100
100
|
info["Upload-Length"] = length.to_s
|
101
101
|
info["Upload-Offset"] = length.to_s
|
102
102
|
else
|
@@ -185,26 +185,19 @@ module Tus
|
|
185
185
|
r.get do
|
186
186
|
validate_upload_finished!(info)
|
187
187
|
|
188
|
-
metadata = info.metadata
|
189
|
-
name = metadata["name"] || metadata["filename"]
|
190
|
-
type = metadata["type"] || metadata["content_type"]
|
191
|
-
|
192
|
-
content_disposition = ContentDisposition.(disposition: opts[:disposition], filename: name)
|
193
|
-
content_type = type || "application/octet-stream"
|
194
|
-
|
195
188
|
if redirect_download
|
196
189
|
redirect_url = instance_exec(uid, info.to_h,
|
197
|
-
content_type:
|
198
|
-
content_disposition:
|
190
|
+
content_type: info.type,
|
191
|
+
content_disposition: ContentDisposition.(disposition: opts[:disposition], filename: info.name),
|
199
192
|
&redirect_download)
|
200
193
|
|
201
194
|
r.redirect redirect_url
|
202
195
|
else
|
203
196
|
range = handle_range_request!(info.length)
|
204
197
|
|
205
|
-
response.headers["Content-
|
206
|
-
response.headers["Content-
|
207
|
-
response.headers["
|
198
|
+
response.headers["Content-Disposition"] = ContentDisposition.(disposition: opts[:disposition], filename: info.name)
|
199
|
+
response.headers["Content-Type"] = info.type if info.type
|
200
|
+
response.headers["ETag"] = %(W/"#{uid}")
|
208
201
|
|
209
202
|
body = storage.get_file(uid, info.to_h, range: range)
|
210
203
|
|
@@ -310,50 +303,34 @@ module Tus
|
|
310
303
|
end
|
311
304
|
end
|
312
305
|
|
313
|
-
# Validates that each partial upload exists and is marked as one
|
306
|
+
# Validates that each partial upload exists and is marked as one, and at the
|
307
|
+
# same time calculates the sum of part lengths.
|
314
308
|
def validate_partial_uploads!(part_uids)
|
315
|
-
|
316
|
-
part_uids.each { |part_uid| input << part_uid }
|
317
|
-
input.close
|
318
|
-
|
319
|
-
results = Queue.new
|
309
|
+
length = 0
|
320
310
|
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
begin
|
327
|
-
loop do
|
328
|
-
part_uid = input.pop or break
|
329
|
-
part_info = storage.read_info(part_uid)
|
330
|
-
results << Tus::Info.new(part_info)
|
331
|
-
end
|
332
|
-
nil
|
333
|
-
rescue => error
|
334
|
-
input.clear
|
335
|
-
error
|
336
|
-
end
|
311
|
+
part_uids.each do |part_uid|
|
312
|
+
begin
|
313
|
+
part_info = storage.read_info(part_uid)
|
314
|
+
rescue Tus::NotFound
|
315
|
+
error!(400, "Partial upload not found")
|
337
316
|
end
|
338
|
-
end
|
339
317
|
|
340
|
-
|
318
|
+
part_info = Tus::Info.new(part_info)
|
341
319
|
|
342
|
-
|
343
|
-
error!(400, "One or more partial uploads were not found")
|
344
|
-
elsif errors.any?
|
345
|
-
fail errors.first
|
346
|
-
end
|
320
|
+
error!(400, "Upload is not partial") unless part_info.partial?
|
347
321
|
|
348
|
-
|
322
|
+
unless part_info.length == part_info.offset
|
323
|
+
error!(400, "Partial upload is not finished")
|
324
|
+
end
|
349
325
|
|
350
|
-
|
351
|
-
error!(400, "One or more uploads were not partial")
|
326
|
+
length += part_info.length
|
352
327
|
end
|
353
328
|
|
354
|
-
if max_size &&
|
355
|
-
error!(400, "The sum of partial upload lengths
|
329
|
+
if max_size && length > max_size
|
330
|
+
error!(400, "The sum of partial upload lengths exceeds Tus-Max-Size")
|
356
331
|
end
|
332
|
+
|
333
|
+
length
|
357
334
|
end
|
358
335
|
|
359
336
|
def validate_upload_checksum!(input)
|
@@ -392,9 +369,24 @@ module Tus
|
|
392
369
|
response.headers["Content-Range"] = "bytes #{range.begin}-#{range.end}/#{length}"
|
393
370
|
end
|
394
371
|
|
372
|
+
response.headers["Content-Length"] = range.size.to_s
|
373
|
+
|
395
374
|
range
|
396
375
|
end
|
397
376
|
|
377
|
+
def redirect_download
|
378
|
+
value = opts[:redirect_download]
|
379
|
+
|
380
|
+
if opts[:download_url]
|
381
|
+
value ||= opts[:download_url]
|
382
|
+
warn "[TUS-RUBY-SERVER DEPRECATION] The :download_url option has been renamed to :redirect_download."
|
383
|
+
end
|
384
|
+
|
385
|
+
value = storage.method(:file_url) if value == true
|
386
|
+
|
387
|
+
value
|
388
|
+
end
|
389
|
+
|
398
390
|
def handle_cors!
|
399
391
|
origin = request.headers["Origin"]
|
400
392
|
|
@@ -404,10 +396,10 @@ module Tus
|
|
404
396
|
|
405
397
|
if request.options?
|
406
398
|
response.headers["Access-Control-Allow-Methods"] = "POST, GET, HEAD, PATCH, DELETE, OPTIONS"
|
407
|
-
response.headers["Access-Control-Allow-Headers"] = "Origin, X-Requested-With, Content-Type, Upload-Length, Upload-Offset, Tus-Resumable, Upload-Metadata"
|
399
|
+
response.headers["Access-Control-Allow-Headers"] = "Origin, X-Requested-With, Content-Type, Upload-Length, Upload-Offset, Tus-Resumable, Upload-Metadata, Upload-Defer-Length, Upload-Concat"
|
408
400
|
response.headers["Access-Control-Max-Age"] = "86400"
|
409
401
|
else
|
410
|
-
response.headers["Access-Control-Expose-Headers"] = "Upload-Offset, Location, Upload-Length, Tus-Version, Tus-Resumable, Tus-Max-Size, Tus-Extension, Upload-Metadata"
|
402
|
+
response.headers["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"
|
411
403
|
end
|
412
404
|
end
|
413
405
|
|
@@ -429,19 +421,6 @@ module Tus
|
|
429
421
|
request.halt
|
430
422
|
end
|
431
423
|
|
432
|
-
def redirect_download
|
433
|
-
value = opts[:redirect_download]
|
434
|
-
|
435
|
-
if opts[:download_url]
|
436
|
-
value ||= opts[:download_url]
|
437
|
-
warn "[TUS-RUBY-SERVER DEPRECATION] The :download_url option has been renamed to :redirect_download."
|
438
|
-
end
|
439
|
-
|
440
|
-
value = storage.method(:file_url) if value == true
|
441
|
-
|
442
|
-
value
|
443
|
-
end
|
444
|
-
|
445
424
|
def storage
|
446
425
|
opts[:storage] || Tus::Storage::Filesystem.new("data")
|
447
426
|
end
|
data/lib/tus/storage/gridfs.rb
CHANGED
@@ -53,7 +53,7 @@ module Tus
|
|
53
53
|
validate_parts!(grid_infos, part_uids)
|
54
54
|
|
55
55
|
length = grid_infos.map { |doc| doc[:length] }.reduce(0, :+)
|
56
|
-
content_type = Tus::Info.new(info).
|
56
|
+
content_type = Tus::Info.new(info).type
|
57
57
|
|
58
58
|
grid_file = create_grid_file(
|
59
59
|
filename: uid,
|
@@ -75,9 +75,6 @@ module Tus
|
|
75
75
|
|
76
76
|
# Delete the parts after concatenation.
|
77
77
|
files_collection.delete_many(filename: {"$in" => part_uids})
|
78
|
-
|
79
|
-
# Tus server requires us to return the size of the concatenated file.
|
80
|
-
length
|
81
78
|
end
|
82
79
|
|
83
80
|
# Appends data to the specified upload in a streaming fashion, and
|
data/lib/tus/storage/s3.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
gem "aws-sdk-s3", "~> 1.2"
|
4
4
|
|
5
5
|
require "aws-sdk-s3"
|
6
|
+
require "content_disposition"
|
6
7
|
|
7
8
|
require "tus/info"
|
8
9
|
require "tus/response"
|
@@ -14,12 +15,16 @@ require "cgi"
|
|
14
15
|
module Tus
|
15
16
|
module Storage
|
16
17
|
class S3
|
17
|
-
|
18
|
+
# AWS S3 multipart upload limits
|
19
|
+
MIN_PART_SIZE = 5 * 1024 * 1024
|
20
|
+
MAX_PART_SIZE = 5 * 1024 * 1024 * 1024
|
21
|
+
MAX_MULTIPART_PARTS = 10_000
|
22
|
+
MAX_OBJECT_SIZE = 5 * 1024 * 1024 * 1024 * 1024
|
18
23
|
|
19
|
-
attr_reader :client, :bucket, :prefix, :upload_options, :concurrency
|
24
|
+
attr_reader :client, :bucket, :prefix, :upload_options, :limits, :concurrency
|
20
25
|
|
21
26
|
# Initializes an aws-sdk-s3 client with the given credentials.
|
22
|
-
def initialize(bucket:, prefix: nil, upload_options: {}, concurrency: {}, thread_count: nil, **client_options)
|
27
|
+
def initialize(bucket:, prefix: nil, upload_options: {}, limits: {}, concurrency: {}, thread_count: nil, **client_options)
|
23
28
|
fail ArgumentError, "the :bucket option was nil" unless bucket
|
24
29
|
|
25
30
|
if thread_count
|
@@ -33,6 +38,7 @@ module Tus
|
|
33
38
|
@bucket = resource.bucket(bucket)
|
34
39
|
@prefix = prefix
|
35
40
|
@upload_options = upload_options
|
41
|
+
@limits = limits
|
36
42
|
@concurrency = concurrency
|
37
43
|
end
|
38
44
|
|
@@ -41,18 +47,15 @@ module Tus
|
|
41
47
|
def create_file(uid, info = {})
|
42
48
|
tus_info = Tus::Info.new(info)
|
43
49
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
if filename = tus_info.metadata["filename"]
|
48
|
-
# Aws-sdk-s3 doesn't sign non-ASCII characters correctly, and browsers
|
49
|
-
# will automatically URI-decode filenames.
|
50
|
-
filename = CGI.escape(filename).gsub("+", " ")
|
51
|
-
|
52
|
-
options[:content_disposition] ||= "inline"
|
53
|
-
options[:content_disposition] += "; filename=\"#{filename}\""
|
50
|
+
if tus_info.length && tus_info.length > max_object_size
|
51
|
+
fail Tus::Error, "upload length exceeds maximum S3 object size"
|
54
52
|
end
|
55
53
|
|
54
|
+
options = {}
|
55
|
+
options[:content_type] = tus_info.type if tus_info.type
|
56
|
+
options[:content_disposition] = ContentDisposition.inline(tus_info.name) if tus_info.name
|
57
|
+
options.merge!(upload_options)
|
58
|
+
|
56
59
|
multipart_upload = object(uid).initiate_multipart_upload(options)
|
57
60
|
|
58
61
|
info["multipart_id"] = multipart_upload.id
|
@@ -81,12 +84,8 @@ module Tus
|
|
81
84
|
finalize_file(uid, info)
|
82
85
|
|
83
86
|
delete(part_uids.flat_map { |part_uid| [object(part_uid), object("#{part_uid}.info")] })
|
84
|
-
|
85
|
-
# Tus server requires us to return the size of the concatenated file.
|
86
|
-
object = client.head_object(bucket: bucket.name, key: object(uid).key)
|
87
|
-
object.content_length
|
88
87
|
rescue => error
|
89
|
-
|
88
|
+
multipart_upload.abort if multipart_upload
|
90
89
|
raise error
|
91
90
|
end
|
92
91
|
|
@@ -109,21 +108,22 @@ module Tus
|
|
109
108
|
part_offset = info["multipart_parts"].count
|
110
109
|
bytes_uploaded = 0
|
111
110
|
|
112
|
-
|
113
|
-
|
111
|
+
part_size = calculate_part_size(tus_info.length)
|
112
|
+
|
113
|
+
chunk = input.read(part_size)
|
114
114
|
|
115
115
|
while chunk
|
116
|
-
next_chunk = input.read(
|
116
|
+
next_chunk = input.read(part_size)
|
117
117
|
|
118
118
|
# merge next chunk into previous if it's smaller than minimum chunk size
|
119
|
-
if next_chunk && next_chunk.bytesize <
|
119
|
+
if next_chunk && next_chunk.bytesize < part_size
|
120
120
|
chunk << next_chunk
|
121
121
|
next_chunk.clear
|
122
122
|
next_chunk = nil
|
123
123
|
end
|
124
124
|
|
125
|
-
# abort if chunk is smaller than
|
126
|
-
if chunk.bytesize <
|
125
|
+
# abort if chunk is smaller than part size and is not the last chunk
|
126
|
+
if chunk.bytesize < part_size
|
127
127
|
break if (tus_info.length && tus_info.offset) &&
|
128
128
|
chunk.bytesize + tus_info.offset < tus_info.length
|
129
129
|
end
|
@@ -197,7 +197,7 @@ module Tus
|
|
197
197
|
def delete_file(uid, info = {})
|
198
198
|
if info["multipart_id"]
|
199
199
|
multipart_upload = object(uid).multipart_upload(info["multipart_id"])
|
200
|
-
|
200
|
+
multipart_upload.abort
|
201
201
|
|
202
202
|
delete [object("#{uid}.info")]
|
203
203
|
else
|
@@ -209,21 +209,17 @@ module Tus
|
|
209
209
|
# multipart uploads still in progress, it checks the upload date of the
|
210
210
|
# last multipart part.
|
211
211
|
def expire_files(expiration_date)
|
212
|
-
|
213
|
-
object.last_modified <= expiration_date
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
if most_recent_part.nil? || most_recent_part.last_modified <= expiration_date
|
224
|
-
abort_multipart_upload(multipart_upload)
|
225
|
-
end
|
226
|
-
end
|
212
|
+
delete bucket.objects(prefix: @prefix)
|
213
|
+
.select { |object| object.last_modified <= expiration_date }
|
214
|
+
|
215
|
+
bucket.multipart_uploads
|
216
|
+
.select { |multipart_upload| multipart_upload.key.start_with?(prefix.to_s) }
|
217
|
+
.select { |multipart_upload| multipart_upload.initiated <= expiration_date }
|
218
|
+
.select { |multipart_upload|
|
219
|
+
last_modified = multipart_upload.parts.map(&:last_modified).max
|
220
|
+
last_modified.nil? || last_modified <= expiration_date
|
221
|
+
}
|
222
|
+
.each(&:abort)
|
227
223
|
end
|
228
224
|
|
229
225
|
private
|
@@ -240,6 +236,23 @@ module Tus
|
|
240
236
|
{ "part_number" => part_number, "etag" => response.etag }
|
241
237
|
end
|
242
238
|
|
239
|
+
# Calculates minimum multipart part size required to upload the whole
|
240
|
+
# file, taking into account AWS S3 multipart limits on part size and
|
241
|
+
# number of parts.
|
242
|
+
def calculate_part_size(length)
|
243
|
+
return min_part_size if length.nil?
|
244
|
+
return length if length <= min_part_size
|
245
|
+
return min_part_size if length <= min_part_size * max_multipart_parts
|
246
|
+
|
247
|
+
part_size = Rational(length, max_multipart_parts).ceil
|
248
|
+
|
249
|
+
if part_size > max_part_size
|
250
|
+
fail Tus::Error, "chunk size for upload exceeds maximum part size"
|
251
|
+
end
|
252
|
+
|
253
|
+
part_size
|
254
|
+
end
|
255
|
+
|
243
256
|
def delete(objects)
|
244
257
|
# S3 can delete maximum of 1000 objects in a single request
|
245
258
|
objects.each_slice(1000) do |objects_batch|
|
@@ -248,18 +261,6 @@ module Tus
|
|
248
261
|
end
|
249
262
|
end
|
250
263
|
|
251
|
-
# In order to ensure the multipart upload was successfully aborted,
|
252
|
-
# we need to check whether all parts have been deleted, and retry
|
253
|
-
# the abort if the list is nonempty.
|
254
|
-
def abort_multipart_upload(multipart_upload)
|
255
|
-
loop do
|
256
|
-
multipart_upload.abort
|
257
|
-
break unless multipart_upload.parts.any?
|
258
|
-
end
|
259
|
-
rescue Aws::S3::Errors::NoSuchUpload
|
260
|
-
# multipart upload was successfully aborted or doesn't exist
|
261
|
-
end
|
262
|
-
|
263
264
|
# Creates multipart parts for the specified multipart upload by copying
|
264
265
|
# given objects into them. It uses a queue and a fixed-size thread pool
|
265
266
|
# which consumes that queue.
|
@@ -325,6 +326,11 @@ module Tus
|
|
325
326
|
def object(key)
|
326
327
|
bucket.object([*prefix, key].join("/"))
|
327
328
|
end
|
329
|
+
|
330
|
+
def min_part_size; limits.fetch(:min_part_size, MIN_PART_SIZE); end
|
331
|
+
def max_part_size; limits.fetch(:max_part_size, MAX_PART_SIZE); end
|
332
|
+
def max_multipart_parts; limits.fetch(:max_multipart_parts, MAX_MULTIPART_PARTS); end
|
333
|
+
def max_object_size; limits.fetch(:max_object_size, MAX_OBJECT_SIZE); end
|
328
334
|
end
|
329
335
|
end
|
330
336
|
end
|
data/tus-server.gemspec
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
Gem::Specification.new do |gem|
|
2
2
|
gem.name = "tus-server"
|
3
|
-
gem.version = "2.
|
3
|
+
gem.version = "2.3.0"
|
4
4
|
|
5
5
|
gem.required_ruby_version = ">= 2.3"
|
6
6
|
|
7
7
|
gem.summary = "Ruby server implementation of tus.io, the open protocol for resumable file uploads."
|
8
8
|
|
9
|
-
gem.homepage = "https://github.com/janko
|
9
|
+
gem.homepage = "https://github.com/janko/tus-ruby-server"
|
10
10
|
gem.authors = ["Janko Marohnić"]
|
11
11
|
gem.email = ["janko.marohnic@gmail.com"]
|
12
12
|
gem.license = "MIT"
|
@@ -21,6 +21,6 @@ Gem::Specification.new do |gem|
|
|
21
21
|
gem.add_development_dependency "minitest", "~> 5.8"
|
22
22
|
gem.add_development_dependency "rack-test_app"
|
23
23
|
gem.add_development_dependency "cucumber", "~> 3.1"
|
24
|
-
gem.add_development_dependency "mongo"
|
25
24
|
gem.add_development_dependency "aws-sdk-s3", "~> 1.2"
|
25
|
+
gem.add_development_dependency "aws-sdk-core", "~> 3.23"
|
26
26
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tus-server
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Janko Marohnić
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-05-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: roda
|
@@ -101,33 +101,33 @@ dependencies:
|
|
101
101
|
- !ruby/object:Gem::Version
|
102
102
|
version: '3.1'
|
103
103
|
- !ruby/object:Gem::Dependency
|
104
|
-
name:
|
104
|
+
name: aws-sdk-s3
|
105
105
|
requirement: !ruby/object:Gem::Requirement
|
106
106
|
requirements:
|
107
|
-
- - "
|
107
|
+
- - "~>"
|
108
108
|
- !ruby/object:Gem::Version
|
109
|
-
version: '
|
109
|
+
version: '1.2'
|
110
110
|
type: :development
|
111
111
|
prerelease: false
|
112
112
|
version_requirements: !ruby/object:Gem::Requirement
|
113
113
|
requirements:
|
114
|
-
- - "
|
114
|
+
- - "~>"
|
115
115
|
- !ruby/object:Gem::Version
|
116
|
-
version: '
|
116
|
+
version: '1.2'
|
117
117
|
- !ruby/object:Gem::Dependency
|
118
|
-
name: aws-sdk-
|
118
|
+
name: aws-sdk-core
|
119
119
|
requirement: !ruby/object:Gem::Requirement
|
120
120
|
requirements:
|
121
121
|
- - "~>"
|
122
122
|
- !ruby/object:Gem::Version
|
123
|
-
version: '
|
123
|
+
version: '3.23'
|
124
124
|
type: :development
|
125
125
|
prerelease: false
|
126
126
|
version_requirements: !ruby/object:Gem::Requirement
|
127
127
|
requirements:
|
128
128
|
- - "~>"
|
129
129
|
- !ruby/object:Gem::Version
|
130
|
-
version: '
|
130
|
+
version: '3.23'
|
131
131
|
description:
|
132
132
|
email:
|
133
133
|
- janko.marohnic@gmail.com
|
@@ -150,7 +150,7 @@ files:
|
|
150
150
|
- lib/tus/storage/gridfs.rb
|
151
151
|
- lib/tus/storage/s3.rb
|
152
152
|
- tus-server.gemspec
|
153
|
-
homepage: https://github.com/janko
|
153
|
+
homepage: https://github.com/janko/tus-ruby-server
|
154
154
|
licenses:
|
155
155
|
- MIT
|
156
156
|
metadata: {}
|
@@ -169,8 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
169
169
|
- !ruby/object:Gem::Version
|
170
170
|
version: '0'
|
171
171
|
requirements: []
|
172
|
-
|
173
|
-
rubygems_version: 2.7.6
|
172
|
+
rubygems_version: 3.0.3
|
174
173
|
signing_key:
|
175
174
|
specification_version: 4
|
176
175
|
summary: Ruby server implementation of tus.io, the open protocol for resumable file
|