Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions bin/configs/java-native-useGzipFeature.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ additionalProperties:
artifactId: petstore-native-useGzipFeature
hideGenerationTimestamp: "true"
useJakartaEe: "true"
useGzipFeature: "true"
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ public class ApiClient {
if (encoding.isPresent()) {
for (String token : encoding.get().split(",")) {
if ("gzip".equalsIgnoreCase(token.trim())) {
return new GZIPInputStream(body);
return new GZIPInputStream(body, 8192);
}
}
}
Expand Down Expand Up @@ -531,9 +531,9 @@ public class ApiClient {
}

private boolean fillBuffer() throws IOException {
ensureInitialized();
while (chunkPosition >= currentChunk.length) {
buffer.reset();
ensureInitialized();
if (finished) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import java.io.InputStream;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
Expand All @@ -37,6 +38,9 @@
import java.util.function.Consumer;
import java.util.Optional;
import java.util.zip.GZIPInputStream;
import java.util.function.Supplier;
import java.util.Objects;
import java.util.zip.GZIPOutputStream;
import java.util.stream.Collectors;

import static java.nio.charset.StandardCharsets.UTF_8;
Expand Down Expand Up @@ -478,11 +482,119 @@ public static InputStream getResponseBody(HttpResponse<InputStream> response) th
if (encoding.isPresent()) {
for (String token : encoding.get().split(",")) {
if ("gzip".equalsIgnoreCase(token.trim())) {
return new GZIPInputStream(body);
return new GZIPInputStream(body, 8192);
}
}
}
return body;
}

/**
* Wraps a request body supplier with a streaming GZIP compressor so large payloads
* can be sent without buffering the entire contents in memory.
*
* @param bodySupplier Supplies the original request body InputStream
* @return BodyPublisher that emits gzip-compressed bytes from the supplied stream
*/
public static HttpRequest.BodyPublisher gzipRequestBody(Supplier<InputStream> bodySupplier) {
Objects.requireNonNull(bodySupplier, "bodySupplier must not be null");
return HttpRequest.BodyPublishers.ofInputStream(() -> new GzipCompressingInputStream(bodySupplier));
}

private static final class GzipCompressingInputStream extends InputStream {
private final Supplier<InputStream> supplier;
private final byte[] readBuffer = new byte[8192];
private final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
private InputStream source;
private GZIPOutputStream gzipStream;
private byte[] currentChunk = new byte[0];
private int chunkPosition = 0;
private boolean finished = false;

private GzipCompressingInputStream(Supplier<InputStream> supplier) {
this.supplier = Objects.requireNonNull(supplier, "bodySupplier must not be null");
}

private void ensureInitialized() throws IOException {
if (source == null) {
source = Objects.requireNonNull(supplier.get(), "bodySupplier returned null InputStream");
gzipStream = new GZIPOutputStream(buffer, true);
}
}

private boolean fillBuffer() throws IOException {
while (chunkPosition >= currentChunk.length) {
buffer.reset();
ensureInitialized();
if (finished) {
return false;
}
int bytesRead = source.read(readBuffer);
if (bytesRead == -1) {
gzipStream.finish();
gzipStream.close();
source.close();
finished = true;
} else {
gzipStream.write(readBuffer, 0, bytesRead);
gzipStream.flush();
}
currentChunk = buffer.toByteArray();
chunkPosition = 0;
if (currentChunk.length == 0 && !finished) {
continue;
}
if (currentChunk.length == 0 && finished) {
return false;
}
return true;
}
return true;
}

@Override
public int read() throws IOException {
if (!fillBuffer()) {
return -1;
}
return currentChunk[chunkPosition++] & 0xFF;
}

@Override
public int read(byte[] b, int off, int len) throws IOException {
if (!fillBuffer()) {
return -1;
}
int bytesToCopy = Math.min(len, currentChunk.length - chunkPosition);
System.arraycopy(currentChunk, chunkPosition, b, off, bytesToCopy);
chunkPosition += bytesToCopy;
return bytesToCopy;
}

@Override
public void close() throws IOException {
IOException exception = null;
if (source != null) {
try {
source.close();
} catch (IOException e) {
exception = e;
} finally {
source = null;
}
}
if (gzipStream != null) {
try {
gzipStream.close();
} catch (IOException e) {
exception = exception == null ? e : exception;
} finally {
gzipStream = null;
}
}
if (exception != null) {
throw exception;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;

@jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.19.0-SNAPSHOT")
public class PetApi {
Expand Down Expand Up @@ -267,10 +268,13 @@ private HttpRequest.Builder addPetRequestBuilder(@jakarta.annotation.Nonnull Pet

localVarRequestBuilder.header("Content-Type", "application/json");
localVarRequestBuilder.header("Accept", "application/xml, application/json");
localVarRequestBuilder.header("Accept-Encoding", "gzip");

try {
byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes(pet);
localVarRequestBuilder.method("POST", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody));
Supplier<InputStream> localVarRequestBodySupplier = () -> new ByteArrayInputStream(localVarPostBody);
localVarRequestBuilder.header("Content-Encoding", "gzip");
localVarRequestBuilder.method("POST", ApiClient.gzipRequestBody(localVarRequestBodySupplier));
} catch (IOException e) {
throw new ApiException(e);
}
Expand Down
Loading