|
17 | 17 | package com.google.cloud.storage;
|
18 | 18 |
|
19 | 19 | import static com.google.cloud.storage.Utils.ifNonNull;
|
| 20 | +import static java.util.Objects.requireNonNull; |
20 | 21 |
|
21 | 22 | import com.google.api.client.http.HttpHeaders;
|
22 | 23 | import com.google.api.client.http.HttpResponse;
|
|
49 | 50 | import java.nio.channels.ReadableByteChannel;
|
50 | 51 | import java.nio.channels.ScatteringByteChannel;
|
51 | 52 | import java.util.List;
|
| 53 | +import java.util.Locale; |
52 | 54 | import java.util.Map;
|
53 | 55 | import java.util.function.Function;
|
54 | 56 | import javax.annotation.concurrent.Immutable;
|
@@ -82,13 +84,9 @@ class ApiaryUnbufferedReadableByteChannel implements UnbufferedReadableByteChann
|
82 | 84 | this.options = options;
|
83 | 85 | this.resultRetryAlgorithm = resultRetryAlgorithm;
|
84 | 86 | this.open = true;
|
85 |
| -this.position = |
86 |
| -apiaryReadRequest.getByteRangeSpec() != null |
87 |
| -? apiaryReadRequest.getByteRangeSpec().beginOffset() |
88 |
| -: 0; |
| 87 | +this.position = apiaryReadRequest.getByteRangeSpec().beginOffset(); |
89 | 88 | }
|
90 | 89 |
|
91 |
| -@SuppressWarnings("UnnecessaryContinue") |
92 | 90 | @Override
|
93 | 91 | public long read(ByteBuffer[] dsts, int offset, int length) throws IOException {
|
94 | 92 | do {
|
@@ -113,12 +111,10 @@ public long read(ByteBuffer[] dsts, int offset, int length) throws IOException {
|
113 | 111 | // if our retry algorithm COULD allow a retry, continue the loop and allow trying to
|
114 | 112 | // open the stream again.
|
115 | 113 | sbc = null;
|
116 |
| -continue; |
117 | 114 | } else if (t instanceof IOException) {
|
118 | 115 | IOException ioE = (IOException) t;
|
119 | 116 | if (resultRetryAlgorithm.shouldRetry(StorageException.translate(ioE), null)) {
|
120 | 117 | sbc = null;
|
121 |
| -continue; |
122 | 118 | } else {
|
123 | 119 | throw ioE;
|
124 | 120 | }
|
@@ -148,11 +144,8 @@ private void setXGoogGeneration(long xGoogGeneration) {
|
148 | 144 |
|
149 | 145 | private ScatteringByteChannel open() {
|
150 | 146 | try {
|
151 |
| -Boolean b = |
152 |
| -(Boolean) apiaryReadRequest.options.get(StorageRpc.Option.RETURN_RAW_INPUT_STREAM); |
153 |
| -boolean returnRawInputStream = b != null ? b : true; |
154 | 147 | ApiaryReadRequest request = apiaryReadRequest.withNewBeginOffset(position);
|
155 |
| -Get get = createGetRequest(request, storage.objects(), xGoogGeneration, returnRawInputStream); |
| 148 | +Get get = createGetRequest(request, storage.objects(), xGoogGeneration); |
156 | 149 |
|
157 | 150 | HttpResponse media = get.executeMedia();
|
158 | 151 | InputStream content = media.getContent();
|
@@ -215,10 +208,7 @@ private ScatteringByteChannel open() {
|
215 | 208 |
|
216 | 209 | @VisibleForTesting
|
217 | 210 | static Get createGetRequest(
|
218 |
| -ApiaryReadRequest apiaryReadRequest, |
219 |
| -Objects objects, |
220 |
| -Long xGoogGeneration, |
221 |
| -boolean returnRawInputStream) |
| 211 | +ApiaryReadRequest apiaryReadRequest, Objects objects, Long xGoogGeneration) |
222 | 212 | throws IOException {
|
223 | 213 | StorageObject from = apiaryReadRequest.getObject();
|
224 | 214 | Map<StorageRpc.Option, ?> options = apiaryReadRequest.getOptions();
|
@@ -262,7 +252,9 @@ static Get createGetRequest(
|
262 | 252 | base64.encode(hashFunction.hashBytes(base64.decode(key)).asBytes()));
|
263 | 253 | });
|
264 | 254 |
|
265 |
| -get.setReturnRawInputStream(returnRawInputStream); |
| 255 | +// gzip handling is performed upstream of here. Ensure we always get the raw input stream from |
| 256 | +// the request |
| 257 | +get.setReturnRawInputStream(true); |
266 | 258 | String range = apiaryReadRequest.getByteRangeSpec().getHttpRangeHeader();
|
267 | 259 | if (range != null) {
|
268 | 260 | get.getRequestHeaders().setRange(range);
|
@@ -288,7 +280,7 @@ private static String getHeaderValue(@NonNull HttpHeaders headers, @NonNull Stri
|
288 | 280 | if (list.isEmpty()) {
|
289 | 281 | return null;
|
290 | 282 | } else {
|
291 |
| -return list.get(0); |
| 283 | +return list.get(0).trim().toLowerCase(Locale.ENGLISH); |
292 | 284 | }
|
293 | 285 | } else if (o instanceof String) {
|
294 | 286 | return (String) o;
|
@@ -303,27 +295,32 @@ private static String getHeaderValue(@NonNull HttpHeaders headers, @NonNull Stri
|
303 | 295 | static final class ApiaryReadRequest implements Serializable {
|
304 | 296 | private static final long serialVersionUID = -4059435314115374448L;
|
305 | 297 | private static final Gson gson = new Gson();
|
306 |
| -private transient StorageObject object; |
307 |
| -private final Map<StorageRpc.Option, ?> options; |
308 |
| -private final ByteRangeSpec byteRangeSpec; |
| 298 | +@NonNull private transient StorageObject object; |
| 299 | +@NonNull private final Map<StorageRpc.Option, ?> options; |
| 300 | +@NonNull private final ByteRangeSpec byteRangeSpec; |
309 | 301 |
|
310 | 302 | private volatile String objectJson;
|
311 | 303 |
|
312 | 304 | ApiaryReadRequest(
|
313 |
| -StorageObject object, Map<StorageRpc.Option, ?> options, ByteRangeSpec byteRangeSpec) { |
314 |
| -this.object = object; |
315 |
| -this.options = options; |
316 |
| -this.byteRangeSpec = byteRangeSpec; |
| 305 | +@NonNull StorageObject object, |
| 306 | +@NonNull Map<StorageRpc.Option, ?> options, |
| 307 | +@NonNull ByteRangeSpec byteRangeSpec) { |
| 308 | +this.object = requireNonNull(object, "object must be non null"); |
| 309 | +this.options = requireNonNull(options, "options must be non null"); |
| 310 | +this.byteRangeSpec = requireNonNull(byteRangeSpec, "byteRangeSpec must be non null"); |
317 | 311 | }
|
318 | 312 |
|
| 313 | +@NonNull |
319 | 314 | StorageObject getObject() {
|
320 | 315 | return object;
|
321 | 316 | }
|
322 | 317 |
|
| 318 | +@NonNull |
323 | 319 | Map<StorageRpc.Option, ?> getOptions() {
|
324 | 320 | return options;
|
325 | 321 | }
|
326 | 322 |
|
| 323 | +@NonNull |
327 | 324 | ByteRangeSpec getByteRangeSpec() {
|
328 | 325 | return byteRangeSpec;
|
329 | 326 | }
|
|
0 commit comments