Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions sdk/core/azure-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

### Bugs Fixed

- Fixed a bug where retrying requests with bodies created from a mark/reset-capable `InputStream` could fail because the stream was closed between retry attempts. ([#49650](https://github.com/Azure/azure-sdk-for-java/pull/49650))

### Other Changes

## 1.58.1 (2026-06-08)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ public int available() throws IOException {

@Override
public void close() throws IOException {
inner.close();
// No-op. RestProxy length validation can wrap InputStreamContent during retryable requests. Closing the
// wrapper must not prematurely close the underlying stream between retry attempts.
}
Comment thread
arnabnandy7 marked this conversation as resolved.
Comment thread
arnabnandy7 marked this conversation as resolved.
Outdated
Comment thread
arnabnandy7 marked this conversation as resolved.

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

import static com.azure.core.CoreTestUtils.assertArraysEqual;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
Expand Down Expand Up @@ -210,6 +211,60 @@ public void expectedBodyLengthSync() throws IOException {
}
}

@Test
public void lengthValidatingInputStreamCloseDoesNotCloseUnderlying() throws IOException {
final boolean[] closed = new boolean[1];

try (InputStream innerStream = new InputStream() {
private final ByteArrayInputStream delegate = new ByteArrayInputStream(EXPECTED);

private void ensureOpen() throws IOException {
if (closed[0]) {
throw new IOException("Stream closed");
}
}

@Override
public void close() throws IOException {
closed[0] = true;
delegate.close();
}

@Override
public synchronized int read() throws IOException {
ensureOpen();
return delegate.read();
}

@Override
public synchronized void mark(int readlimit) {
delegate.mark(readlimit);
}

@Override
public synchronized void reset() throws IOException {
ensureOpen();
delegate.reset();
}

@Override
public boolean markSupported() {
return delegate.markSupported();
}
}) {
LengthValidatingInputStream validatingStream
= new LengthValidatingInputStream(innerStream, EXPECTED.length);

validatingStream.mark(EXPECTED.length);
assertEquals(EXPECTED[0], validatingStream.read());
validatingStream.close();
validatingStream.reset();

assertFalse(closed[0], "LengthValidatingInputStream.close() must not close the underlying stream.");
assertEquals(EXPECTED[0], validatingStream.read());
}
Comment thread
arnabnandy7 marked this conversation as resolved.
}
Comment thread
arnabnandy7 marked this conversation as resolved.
Comment thread
arnabnandy7 marked this conversation as resolved.

private static Mono<byte[]> validateAndCollectRequestAsync(HttpRequest request) {
return RestProxyUtils.validateLengthAsync(request)
.flatMap(r -> FluxUtil.collectBytesInByteBufferStream(r.getBody()));
Expand Down
Loading