Commit 75848b2
Fix the S3 defects a 10-reviewer audit found in the SDK v2 port
**Silent data loss on multipart upload.** `uploadPart` was handed a `BoundedInputStream`
over a `FileInputStream`, which cannot be reset, so the SDK refused to retry a part after
any transient error ("Request cannot be retried, because the request stream could not be
reset"). The v1 SDK passed the file plus an offset and retried freely. The failure then
landed in a catch that logged and swallowed, `completeMultipartUpload` never ran, and
`put()` carried on setting size and checksum - DSpace recorded a bitstream that S3 does
not hold, with no error anywhere.
Now uses the public `AsyncRequestBody.fromFile(FileRequestBodyConfiguration)` with
`position`/`numBytesToRead`, which is file-backed and therefore retryable; this also
removes the hand-rolled `openPart` helper and its executor. A failed upload now aborts the
multipart upload (parts were previously leaked and billed) and throws instead of returning
normally.
**The multipart loop was never executed more than once.** 50 MB part size against a 23-byte
fixture meant one iteration with offset 0, so the offset arithmetic and last-part handling
this port rewrote had no coverage at all. `uploadPartSizeBytes` is now settable and
`syncStoreUploadsInMultipleParts` uploads 5 MB + 4 KB across a real part boundary, verifying
the object byte for byte.
**A tripwire in `amazonClientBuilderBy` left all 21 S3 tests green.** Every test injects a
ready-made client, so `FunctionalUtils.getDefaultOrBuild` never called the supplier and
`endpointOverride`, `forcePathStyle`, `maxConcurrency` and the part sizes never ran - the
fork's headline delta, configurable `pathStyleAccessEnabled`, was verified only at its
getter. `clientBuilderAppliesEndpointAndPathStyle` builds a client through that method and
uses it against LocalStack. Verified it detects breakage: removing `endpointOverride` turns
it red, restoring it turns it green.
**Content-Disposition had two implementations and the newer one was wrong.** It escaped `"`
but not `\`, so a bitstream named `evil\` terminated the quoted string and swallowed
`filename*`; and it used `URLEncoder` directly, so a space arrived as `+`, which RFC 8187
reads literally - re-introducing the bug vanilla had just fixed. Extracted the correct
implementation to `org.dspace.util.ContentDispositionUtils`, now used by both call sites.
**Enabling direct downloads silently disabled inline preview.** The redirect hardcoded
`attachment`, discarding the disposition the allowlist and the 8 MB threshold had just
computed. `generatePresignedUrl` takes the caller's disposition; `BitstreamRestController`
passes the exact header the non-redirect path would have sent.
**Presigner region could diverge from the client's.** It hardcoded `us-east-1` while the
client leaves the region to the default provider chain when no credentials are configured,
so presigned URLs would be signed for the wrong region on an IAM role outside us-east-1. It
now mirrors `init()` branch for branch.
**A 403 was reported as "bucket absent".** `doesBucketExist` treated everything except
`NoSuchBucketException` as absent, so `init()` would try to create a bucket that already
exists; a least-privilege policy denies that and the assetstore comes up dead. Only 404 and
`NoSuchBucketException` now answer false. `doesObjectExist` likewise stops reporting a 403
or a timeout as "object does not exist" with the cause hidden at DEBUG.
**`s3ChecksumAlgorithm` was dead configuration.** `bitstore.xml` wires
`SyncS3BitStoreService`, which overrides `put()`, so the parent's `putObject` - the only
consumer - never ran. `uploadFluently` now applies it. Also `${assetstore.s3.endpoint:}` is
self-defaulting, matching vanilla.
Tests: S3BitStoreServiceIT 15, ClarinS3BitStoreServiceIT 8, S3DirectDownloadServiceTest 11,
ContentDispositionUtilsTest 9 - all 0 failures, checkstyle 0 violations. Maven does not
recompile edited sources reliably here, so every run used
`-Dmaven.compiler.useIncrementalCompilation=false`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>1 parent 1bfc45b commit 75848b2
11 files changed
Lines changed: 395 additions & 71 deletions
File tree
- dspace-api/src
- main/java/org/dspace
- storage/bitstore
- service
- util
- test/java/org/dspace
- storage/bitstore
- util
- dspace-server-webapp/src/main/java/org/dspace/app/rest
- dspace/config/spring/api
Lines changed: 11 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
58 | 58 | | |
59 | 59 | | |
60 | 60 | | |
| 61 | + | |
61 | 62 | | |
62 | 63 | | |
63 | 64 | | |
| |||
262 | 263 | | |
263 | 264 | | |
264 | 265 | | |
265 | | - | |
266 | | - | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
267 | 271 | | |
268 | 272 | | |
269 | | - | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
270 | 278 | | |
271 | 279 | | |
272 | 280 | | |
| |||
Lines changed: 50 additions & 16 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
13 | | - | |
14 | 12 | | |
| 13 | + | |
15 | 14 | | |
16 | 15 | | |
17 | 16 | | |
18 | 17 | | |
| 18 | + | |
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| 24 | + | |
24 | 25 | | |
25 | 26 | | |
26 | 27 | | |
27 | 28 | | |
| 29 | + | |
| 30 | + | |
28 | 31 | | |
29 | 32 | | |
30 | 33 | | |
| |||
90 | 93 | | |
91 | 94 | | |
92 | 95 | | |
93 | | - | |
94 | | - | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
95 | 100 | | |
96 | | - | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
97 | 112 | | |
98 | | - | |
| 113 | + | |
99 | 114 | | |
100 | 115 | | |
101 | 116 | | |
102 | 117 | | |
103 | | - | |
104 | 118 | | |
105 | 119 | | |
106 | 120 | | |
| |||
115 | 129 | | |
116 | 130 | | |
117 | 131 | | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
118 | 136 | | |
119 | 137 | | |
120 | 138 | | |
121 | 139 | | |
122 | 140 | | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
123 | 152 | | |
124 | | - | |
| 153 | + | |
125 | 154 | | |
126 | 155 | | |
127 | 156 | | |
128 | 157 | | |
| 158 | + | |
129 | 159 | | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
130 | 166 | | |
131 | 167 | | |
132 | 168 | | |
| |||
140 | 176 | | |
141 | 177 | | |
142 | 178 | | |
143 | | - | |
144 | | - | |
145 | | - | |
146 | | - | |
147 | | - | |
148 | | - | |
149 | | - | |
150 | | - | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
151 | 185 | | |
152 | 186 | | |
153 | 187 | | |
| |||
Lines changed: 53 additions & 31 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
22 | | - | |
23 | | - | |
24 | 22 | | |
25 | 23 | | |
26 | | - | |
27 | 24 | | |
28 | 25 | | |
29 | 26 | | |
30 | 27 | | |
31 | 28 | | |
32 | 29 | | |
33 | 30 | | |
| 31 | + | |
34 | 32 | | |
35 | 33 | | |
| 34 | + | |
36 | 35 | | |
37 | 36 | | |
38 | 37 | | |
| |||
52 | 51 | | |
53 | 52 | | |
54 | 53 | | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
55 | 58 | | |
56 | | - | |
| 59 | + | |
57 | 60 | | |
58 | 61 | | |
59 | 62 | | |
| |||
189 | 192 | | |
190 | 193 | | |
191 | 194 | | |
192 | | - | |
193 | | - | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
194 | 204 | | |
195 | 205 | | |
196 | 206 | | |
| |||
217 | 227 | | |
218 | 228 | | |
219 | 229 | | |
220 | | - | |
221 | 230 | | |
222 | 231 | | |
223 | 232 | | |
224 | 233 | | |
225 | 234 | | |
226 | 235 | | |
227 | 236 | | |
228 | | - | |
| 237 | + | |
229 | 238 | | |
230 | 239 | | |
231 | 240 | | |
232 | 241 | | |
233 | 242 | | |
234 | 243 | | |
235 | | - | |
236 | | - | |
237 | | - | |
238 | | - | |
239 | | - | |
240 | | - | |
241 | | - | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
242 | 255 | | |
243 | 256 | | |
244 | 257 | | |
| |||
263 | 276 | | |
264 | 277 | | |
265 | 278 | | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
266 | 282 | | |
267 | | - | |
268 | | - | |
269 | | - | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
270 | 287 | | |
271 | 288 | | |
272 | 289 | | |
273 | 290 | | |
274 | | - | |
| 291 | + | |
| 292 | + | |
275 | 293 | | |
276 | | - | |
277 | | - | |
278 | | - | |
279 | | - | |
280 | | - | |
| 294 | + | |
| 295 | + | |
281 | 296 | | |
282 | | - | |
283 | | - | |
| 297 | + | |
284 | 298 | | |
285 | | - | |
286 | | - | |
287 | | - | |
288 | | - | |
289 | | - | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
290 | 304 | | |
291 | 305 | | |
292 | 306 | | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
293 | 315 | | |
294 | 316 | | |
295 | 317 | | |
| |||
Lines changed: 16 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
29 | 45 | | |
Lines changed: 57 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 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 | + | |
0 commit comments