Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add deflate as a supported REST response encoding #5016

Merged
merged 1 commit into from
Nov 5, 2024
Merged
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@
import java.math.BigDecimal;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.Inflater;
import net.rptools.maptool.client.AppPreferences;
import net.rptools.maptool.client.MapTool;
import net.rptools.maptool.language.I18N;
Expand All @@ -33,11 +35,17 @@
import net.rptools.parser.VariableResolver;
import net.rptools.parser.function.AbstractFunction;
import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.BufferedSource;
import okio.GzipSource;
import okio.InflaterSource;
import okio.Okio;

/**
* RESTful based functions REST.get, REST.post, REST.put, REST.patch, REST.delete
Expand Down Expand Up @@ -67,7 +75,7 @@ public static RESTfulFunctions getInstance() {
return instance;
}

private final OkHttpClient client = new OkHttpClient();
private final OkHttpClient client = buildClient();
private final Gson gson = new Gson();

@Override
Expand Down Expand Up @@ -236,6 +244,72 @@ private Object executeClientCall(String functionName, Request request, boolean f
}
}

private OkHttpClient buildClient() {
return new OkHttpClient.Builder()
.addInterceptor(
(Interceptor.Chain chain) -> {
var oldRequest = chain.request();

// If the macro has passed its own Accept-Encoding
// it's indicating it expects to somehow handle it itself.
if (oldRequest.header("Accept-Encoding") != null) {
return chain.proceed(oldRequest);
}

// Augment request saying we accept multiple content encodings
var newHeaders =
oldRequest
.headers()
.newBuilder()
.add("Accept-Encoding", "deflate")
.add("Accept-Encoding", "gzip")
.build();

var newRequest = oldRequest.newBuilder().headers(newHeaders).build();

var oldResponse = chain.proceed(newRequest);

// Replace the response's request with the original one
var responseBuilder = oldResponse.newBuilder().request(oldRequest);

// We might not have a body to decompress
var body = oldResponse.body();
if (body != null) {
BufferedSource source = body.source();
// The body may have been wrapped in an arbitrary encoding sequence
// and the server returns them in the order it encoded them
// so we wrap them with decoders in reverse order.
var encodings = oldResponse.headers().values("Content-Encoding");
Collections.reverse(encodings);
for (var encoding : encodings) {
if ("deflate".equalsIgnoreCase(encoding)) {
var inflater = new Inflater(true);
source = Okio.buffer(new InflaterSource(source, inflater));
} else if ("gzip".equalsIgnoreCase(encoding)) {
source = Okio.buffer(new GzipSource(source));
}
}

// Strip encoding and length headers as we've already handled them
var strippedHeaders =
oldResponse
.headers()
.newBuilder()
.removeAll("Content-Encoding")
.removeAll("Content-Length")
.build();
responseBuilder.headers(strippedHeaders);
var contentType = MediaType.parse(oldResponse.header("Content-Type"));
// Construct a new body with an inferred Content-Length
var newBody = ResponseBody.create(contentType, -1L, source);
responseBuilder.body(newBody);
}

return responseBuilder.build();
})
.build();
}

private Headers buildHeaders(Map<String, List<String>> headerMap) {
Headers.Builder headerBuilder = new Headers.Builder();

Expand Down
Loading