Skip to content

Commit c344980

Browse files
author
Local Merge
committed
content length override changes
1 parent 81d9e61 commit c344980

6 files changed

Lines changed: 29 additions & 92 deletions

File tree

sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/models/BlobsDownloadHeaders.java

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -301,11 +301,6 @@ public final class BlobsDownloadHeaders {
301301
@Generated
302302
private byte[] xMsContentCrc64;
303303

304-
/*
305-
* The x-ms-original-content-length property.
306-
*/
307-
private Long xMsOriginalContentLength;
308-
309304
private static final HttpHeaderName X_MS_CREATION_TIME = HttpHeaderName.fromString("x-ms-creation-time");
310305

311306
private static final HttpHeaderName X_MS_OR_POLICY_ID = HttpHeaderName.fromString("x-ms-or-policy-id");
@@ -374,9 +369,6 @@ public final class BlobsDownloadHeaders {
374369

375370
private static final HttpHeaderName X_MS_CONTENT_CRC64 = HttpHeaderName.fromString("x-ms-content-crc64");
376371

377-
private static final HttpHeaderName X_MS_ORIGINAL_CONTENT_LENGTH
378-
= HttpHeaderName.fromString("x-ms-original-content-length");
379-
380372
// HttpHeaders containing the raw property values.
381373
/**
382374
* Creates an instance of BlobsDownloadHeaders class.
@@ -543,12 +535,6 @@ public BlobsDownloadHeaders(HttpHeaders rawHeaders) {
543535
} else {
544536
this.xMsContentCrc64 = null;
545537
}
546-
String xMsOriginalContentLength = rawHeaders.getValue(X_MS_ORIGINAL_CONTENT_LENGTH);
547-
if (xMsOriginalContentLength != null) {
548-
this.xMsOriginalContentLength = Long.parseLong(xMsOriginalContentLength);
549-
} else {
550-
this.xMsOriginalContentLength = null;
551-
}
552538
Map<String, String> xMsMetaHeaderCollection = new LinkedHashMap<>();
553539
Map<String, String> xMsOrHeaderCollection = new LinkedHashMap<>();
554540

@@ -1619,24 +1605,4 @@ public BlobsDownloadHeaders setXMsContentCrc64(byte[] xMsContentCrc64) {
16191605
this.xMsContentCrc64 = CoreUtils.clone(xMsContentCrc64);
16201606
return this;
16211607
}
1622-
1623-
/**
1624-
* Get the xMsOriginalContentLength property: The wire size of the encoded structured message body before decoding.
1625-
*
1626-
* @return the xMsOriginalContentLength value.
1627-
*/
1628-
public Long getXMsOriginalContentLength() {
1629-
return this.xMsOriginalContentLength;
1630-
}
1631-
1632-
/**
1633-
* Set the xMsOriginalContentLength property: The wire size of the encoded structured message body before decoding.
1634-
*
1635-
* @param xMsOriginalContentLength the xMsOriginalContentLength value to set.
1636-
* @return the BlobsDownloadHeaders object itself.
1637-
*/
1638-
public BlobsDownloadHeaders setXMsOriginalContentLength(Long xMsOriginalContentLength) {
1639-
this.xMsOriginalContentLength = xMsOriginalContentLength;
1640-
return this;
1641-
}
16421608
}

sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobDownloadHeaders.java

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,24 +1045,4 @@ public BlobDownloadHeaders setCreationTime(OffsetDateTime creationTime) {
10451045
return this;
10461046
}
10471047

1048-
/**
1049-
* Get the originalContentLength property: The wire size of the encoded structured message body before decoding.
1050-
* Only present when content validation is active and the response was decoded transparently.
1051-
*
1052-
* @return the originalContentLength value.
1053-
*/
1054-
public Long getOriginalContentLength() {
1055-
return internalHeaders.getXMsOriginalContentLength();
1056-
}
1057-
1058-
/**
1059-
* Set the originalContentLength property: The wire size of the encoded structured message body before decoding.
1060-
*
1061-
* @param originalContentLength the originalContentLength value to set.
1062-
* @return the BlobDownloadHeaders object itself.
1063-
*/
1064-
public BlobDownloadHeaders setOriginalContentLength(Long originalContentLength) {
1065-
internalHeaders.setXMsOriginalContentLength(originalContentLength);
1066-
return this;
1067-
}
10681048
}

sdk/storage/azure-storage-common/src/main/java/com/azure/storage/common/implementation/Constants.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -264,11 +264,6 @@ public static final class HeaderConstants {
264264
public static final HttpHeaderName STRUCTURED_CONTENT_LENGTH_HEADER_NAME
265265
= HttpHeaderName.fromString(STRUCTURED_CONTENT_LENGTH);
266266

267-
public static final String ORIGINAL_CONTENT_LENGTH = "x-ms-original-content-length";
268-
269-
public static final HttpHeaderName ORIGINAL_CONTENT_LENGTH_HEADER_NAME
270-
= HttpHeaderName.fromString(ORIGINAL_CONTENT_LENGTH);
271-
272267
/**
273268
* Metadata key ("hdi_isfolder") used to mark virtual directories in Azure Blob Storage.
274269
*

sdk/storage/azure-storage-common/src/main/java/com/azure/storage/common/policy/DecodedResponse.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import com.azure.core.http.HttpResponse;
99
import com.azure.core.util.CoreUtils;
1010
import com.azure.core.util.FluxUtil;
11-
import com.azure.storage.common.implementation.Constants;
1211
import reactor.core.publisher.Flux;
1312
import reactor.core.publisher.Mono;
1413

@@ -33,23 +32,19 @@ class DecodedResponse extends HttpResponse {
3332
* Wraps {@code httpResponse} with a body backed by {@code decodedBody}.
3433
*
3534
* <p>{@code Content-Length} is overridden to {@code decodedContentLength} so callers see the size of the bytes
36-
* they will actually read. The original wire size is preserved in {@code x-ms-original-content-length}.</p>
35+
* they will actually read from the decoded payload, not the larger wire size of the structured message.</p>
3736
*
3837
* @param httpResponse The original response from the storage service.
3938
* @param decodedBody The Flux of CRC-validated, framing-stripped payload bytes produced by the decoder pipeline.
40-
* @param originalContentLength The wire size of the encoded structured message body.
4139
* @param decodedContentLength The size of the decoded payload that callers will consume.
4240
*/
43-
DecodedResponse(HttpResponse httpResponse, Flux<ByteBuffer> decodedBody, long originalContentLength,
44-
long decodedContentLength) {
41+
DecodedResponse(HttpResponse httpResponse, Flux<ByteBuffer> decodedBody, long decodedContentLength) {
4542
super(httpResponse.getRequest());
4643
this.originalResponse = httpResponse;
4744
this.decodedBody = decodedBody;
4845
HttpHeaders headers = new HttpHeaders();
4946
httpResponse.getHeaders().stream().forEach(h -> headers.set(h.getName(), h.getValue()));
5047
headers.set(HttpHeaderName.CONTENT_LENGTH, String.valueOf(decodedContentLength));
51-
headers.set(Constants.HeaderConstants.ORIGINAL_CONTENT_LENGTH_HEADER_NAME,
52-
String.valueOf(originalContentLength));
5348
this.adjustedHeaders = headers;
5449
}
5550

sdk/storage/azure-storage-common/src/main/java/com/azure/storage/common/policy/StorageContentValidationDecoderPolicy.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,16 @@ public Mono<HttpResponse> process(HttpPipelineCallContext context, HttpPipelineN
7474
validateStructuredMessageHeaders(httpResponse);
7575

7676
Long decodedContentLength = getStructuredContentLength(httpResponse.getHeaders());
77+
if (decodedContentLength == null) {
78+
throw LOGGER.logExceptionAsError(new IllegalStateException(
79+
"x-ms-structured-content-length header is present but could not be parsed as a long."));
80+
}
7781

7882
// Fresh decoder per response so retries each get a clean state machine.
7983
StructuredMessageDecoder decoder = new StructuredMessageDecoder(contentLength);
8084

8185
Flux<ByteBuffer> decodedStream = decodeStream(httpResponse.getBody(), decoder);
82-
// decodedContentLength is guaranteed non-null here: validateStructuredMessageHeaders confirmed its presence.
83-
return new DecodedResponse(httpResponse, decodedStream, contentLength, decodedContentLength);
86+
return new DecodedResponse(httpResponse, decodedStream, decodedContentLength);
8487
});
8588
}
8689

sdk/storage/azure-storage-common/src/test/java/com/azure/storage/common/policy/DecodedResponseTests.java

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import com.azure.core.http.HttpResponse;
1111
import com.azure.core.test.http.MockHttpResponse;
1212
import com.azure.core.util.BinaryData;
13-
import com.azure.storage.common.implementation.Constants;
1413
import org.junit.jupiter.api.Test;
1514
import reactor.core.publisher.Flux;
1615
import reactor.test.StepVerifier;
@@ -65,7 +64,7 @@ public void preservesRequestStatusCodeAndHeaders() {
6564
HttpHeaders h = new HttpHeaders().set(HttpHeaderName.CONTENT_LENGTH, "100").set(CUSTOM_HEADER, "value");
6665
MockHttpResponse original = mockResponse(206, h, bytes("encoded"));
6766

68-
DecodedResponse wrapper = new DecodedResponse(original, fluxOf(bytes("decoded")), 100L, 80L);
67+
DecodedResponse wrapper = new DecodedResponse(original, fluxOf(bytes("decoded")), 80L);
6968

7069
assertSame(original.getRequest(), wrapper.getRequest());
7170
assertEquals(206, wrapper.getStatusCode());
@@ -77,7 +76,7 @@ public void preservesRequestStatusCodeAndHeaders() {
7776
@Test
7877
public void getHeaderValueByStringReturnsHeaderValue() {
7978
HttpHeaders h = headers(CUSTOM_HEADER, "value");
80-
DecodedResponse wrapper = new DecodedResponse(mockResponse(200, h, new byte[0]), fluxOf(new byte[0]), 0L, 0L);
79+
DecodedResponse wrapper = new DecodedResponse(mockResponse(200, h, new byte[0]), fluxOf(new byte[0]), 0L);
8180

8281
assertEquals("value", wrapper.getHeaderValue(CUSTOM_HEADER.getCaseInsensitiveName()));
8382
assertNull(wrapper.getHeaderValue("nonexistent"));
@@ -87,7 +86,7 @@ public void getHeaderValueByStringReturnsHeaderValue() {
8786
public void getBodyReturnsDecodedFlux() {
8887
byte[] decoded = bytes("decoded body");
8988
DecodedResponse wrapper
90-
= new DecodedResponse(mockResponse(200, new HttpHeaders(), bytes("encoded")), fluxOf(decoded), 0L, 0L);
89+
= new DecodedResponse(mockResponse(200, new HttpHeaders(), bytes("encoded")), fluxOf(decoded), 0L);
9190

9291
StepVerifier.create(wrapper.getBody().reduce(new ByteArrayOutputStream(), (sink, buf) -> {
9392
byte[] copy = new byte[buf.remaining()];
@@ -101,7 +100,7 @@ public void getBodyReturnsDecodedFlux() {
101100
public void getBodyAsByteArrayReturnsDecodedBytes() {
102101
byte[] decoded = bytes("decoded body");
103102
DecodedResponse wrapper
104-
= new DecodedResponse(mockResponse(200, new HttpHeaders(), bytes("encoded")), fluxOf(decoded), 0L, 0L);
103+
= new DecodedResponse(mockResponse(200, new HttpHeaders(), bytes("encoded")), fluxOf(decoded), 0L);
105104

106105
StepVerifier.create(wrapper.getBodyAsByteArray())
107106
.expectNextMatches(b -> Arrays.equals(decoded, b))
@@ -114,7 +113,7 @@ public void getBodyAsStringDefaultsToUtf8WhenNoCharsetSpecified() {
114113
// BOM nor a Content-Type charset parameter is present. This test pins the "no headers, no BOM" path.
115114
String text = "héllo wörld – ✓";
116115
DecodedResponse wrapper = new DecodedResponse(mockResponse(200, new HttpHeaders(), new byte[0]),
117-
fluxOf(text.getBytes(StandardCharsets.UTF_8)), 0L, 0L);
116+
fluxOf(text.getBytes(StandardCharsets.UTF_8)), 0L);
118117

119118
StepVerifier.create(wrapper.getBodyAsString()).expectNext(text).verifyComplete();
120119
}
@@ -127,7 +126,7 @@ public void getBodyAsStringHonorsCharsetFromContentTypeHeader() {
127126
String text = "ümlaut";
128127
byte[] iso = text.getBytes(StandardCharsets.ISO_8859_1);
129128
HttpHeaders h = new HttpHeaders().set(HttpHeaderName.CONTENT_TYPE, "text/plain; charset=ISO-8859-1");
130-
DecodedResponse wrapper = new DecodedResponse(mockResponse(200, h, new byte[0]), fluxOf(iso), 0L, 0L);
129+
DecodedResponse wrapper = new DecodedResponse(mockResponse(200, h, new byte[0]), fluxOf(iso), 0L);
131130

132131
StepVerifier.create(wrapper.getBodyAsString()).expectNext(text).verifyComplete();
133132
}
@@ -143,7 +142,7 @@ public void getBodyAsStringDetectsUtf8BomAndStripsIt() {
143142
System.arraycopy(bom, 0, withBom, 0, bom.length);
144143
System.arraycopy(payload, 0, withBom, bom.length, payload.length);
145144
DecodedResponse wrapper
146-
= new DecodedResponse(mockResponse(200, new HttpHeaders(), new byte[0]), fluxOf(withBom), 0L, 0L);
145+
= new DecodedResponse(mockResponse(200, new HttpHeaders(), new byte[0]), fluxOf(withBom), 0L);
147146

148147
StepVerifier.create(wrapper.getBodyAsString()).expectNext(text).verifyComplete();
149148
}
@@ -153,7 +152,7 @@ public void getBodyAsStringDecodesUsingProvidedCharset() {
153152
String text = "ümlaut";
154153
byte[] latin1 = text.getBytes(StandardCharsets.ISO_8859_1);
155154
DecodedResponse wrapper
156-
= new DecodedResponse(mockResponse(200, new HttpHeaders(), new byte[0]), fluxOf(latin1), 0L, 0L);
155+
= new DecodedResponse(mockResponse(200, new HttpHeaders(), new byte[0]), fluxOf(latin1), 0L);
157156

158157
StepVerifier.create(wrapper.getBodyAsString(StandardCharsets.ISO_8859_1)).expectNext(text).verifyComplete();
159158
}
@@ -163,7 +162,7 @@ public void inheritedGetBodyAsInputStreamUsesDecodedBytes() throws IOException {
163162
// Base getBodyAsInputStream() routes through getBodyAsByteArray(), so the override is exercised end-to-end.
164163
byte[] decoded = bytes("decoded stream");
165164
DecodedResponse wrapper
166-
= new DecodedResponse(mockResponse(200, new HttpHeaders(), bytes("encoded")), fluxOf(decoded), 0L, 0L);
165+
= new DecodedResponse(mockResponse(200, new HttpHeaders(), bytes("encoded")), fluxOf(decoded), 0L);
167166

168167
try (InputStream stream = wrapper.getBodyAsInputStream().block()) {
169168
assertNotNull(stream);
@@ -175,7 +174,7 @@ public void inheritedGetBodyAsInputStreamUsesDecodedBytes() throws IOException {
175174
public void inheritedWriteBodyToWritesDecodedBytes() throws IOException {
176175
byte[] decoded = bytes("write me");
177176
DecodedResponse wrapper
178-
= new DecodedResponse(mockResponse(200, new HttpHeaders(), bytes("encoded")), fluxOf(decoded), 0L, 0L);
177+
= new DecodedResponse(mockResponse(200, new HttpHeaders(), bytes("encoded")), fluxOf(decoded), 0L);
179178

180179
ByteArrayOutputStream sink = new ByteArrayOutputStream();
181180
try (WritableByteChannel channel = Channels.newChannel(sink)) {
@@ -189,7 +188,7 @@ public void inheritedWriteBodyToWritesDecodedBytes() throws IOException {
189188
public void inheritedBufferReturnsResponseBackedByDecodedBytes() {
190189
byte[] decoded = bytes("buffered");
191190
DecodedResponse wrapper
192-
= new DecodedResponse(mockResponse(200, new HttpHeaders(), bytes("encoded")), fluxOf(decoded), 0L, 0L);
191+
= new DecodedResponse(mockResponse(200, new HttpHeaders(), bytes("encoded")), fluxOf(decoded), 0L);
193192

194193
HttpResponse buffered = wrapper.buffer();
195194
assertNotNull(buffered);
@@ -204,30 +203,29 @@ public void inheritedGetBodyAsBinaryDataReturnsDecodedBytes() {
204203
// must contain the decoded payload, not the original wire body. A divergent Content-Length header is set
205204
// to make the wire vs decoded distinction explicit and guard against regressions in header forwarding.
206205
byte[] decoded = bytes("decoded payload");
207-
long originalSize = decoded.length + 32;
208-
HttpHeaders h = new HttpHeaders().set(HttpHeaderName.CONTENT_LENGTH, String.valueOf(originalSize));
209-
DecodedResponse wrapper = new DecodedResponse(mockResponse(200, h, bytes("encoded wire body")), fluxOf(decoded),
210-
originalSize, decoded.length);
206+
long decodedSize = decoded.length;
207+
HttpHeaders h = new HttpHeaders().set(HttpHeaderName.CONTENT_LENGTH, String.valueOf(decodedSize + 32));
208+
DecodedResponse wrapper
209+
= new DecodedResponse(mockResponse(200, h, bytes("encoded wire body")), fluxOf(decoded), decodedSize);
211210

212211
BinaryData data = wrapper.getBodyAsBinaryData();
213212
assertNotNull(data);
214213
assertArrayEquals(decoded, data.toBytes());
215214
}
216215

217216
@Test
218-
public void contentLengthIsOverriddenToDecodedSizeAndOriginalIsPreserved() {
219-
long originalSize = 500L;
217+
public void contentLengthIsOverriddenToDecodedSize() {
218+
long wireSize = 500L;
220219
long decodedSize = 300L;
221-
HttpHeaders h = new HttpHeaders().set(HttpHeaderName.CONTENT_LENGTH, String.valueOf(originalSize))
220+
HttpHeaders h = new HttpHeaders()
221+
.set(HttpHeaderName.CONTENT_LENGTH, String.valueOf(wireSize))
222222
.set(CUSTOM_HEADER, "preserve-me");
223-
DecodedResponse wrapper
224-
= new DecodedResponse(mockResponse(200, h, new byte[0]), fluxOf(new byte[0]), originalSize, decodedSize);
223+
DecodedResponse wrapper = new DecodedResponse(mockResponse(200, h, new byte[0]), fluxOf(new byte[0]),
224+
decodedSize);
225225

226226
assertEquals(String.valueOf(decodedSize), wrapper.getHeaders().getValue(HttpHeaderName.CONTENT_LENGTH));
227-
assertEquals(String.valueOf(originalSize),
228-
wrapper.getHeaders().getValue(Constants.HeaderConstants.ORIGINAL_CONTENT_LENGTH_HEADER_NAME));
229227
assertEquals("preserve-me", wrapper.getHeaders().getValue(CUSTOM_HEADER));
230-
// Deprecated getHeaderValue must reflect the same overrides.
228+
// Deprecated getHeaderValue must reflect the same override.
231229
assertEquals(String.valueOf(decodedSize),
232230
wrapper.getHeaderValue(HttpHeaderName.CONTENT_LENGTH.getCaseInsensitiveName()));
233231
}

0 commit comments

Comments
 (0)