2222import io .trino .gateway .ha .config .ProxyResponseConfiguration ;
2323import io .trino .gateway .proxyserver .ProxyResponseHandler .ProxyResponse ;
2424
25+ import java .io .ByteArrayInputStream ;
2526import java .io .IOException ;
27+ import java .io .InputStream ;
2628import java .nio .charset .StandardCharsets ;
29+ import java .util .zip .GZIPInputStream ;
2730
2831import static java .util .Objects .requireNonNull ;
2932
@@ -47,7 +50,9 @@ public ProxyResponse handleException(Request request, Exception exception)
4750 public ProxyResponse handle (Request request , Response response )
4851 {
4952 try {
50- return new ProxyResponse (response .getStatusCode (), response .getHeaders (), new String (response .getInputStream ().readNBytes ((int ) responseSize .toBytes ()), StandardCharsets .UTF_8 ));
53+ // Store raw bytes to preserve compression
54+ byte [] responseBodyBytes = response .getInputStream ().readNBytes ((int ) responseSize .toBytes ());
55+ return new ProxyResponse (response .getStatusCode (), response .getHeaders (), responseBodyBytes );
5156 }
5257 catch (IOException e ) {
5358 throw new ProxyException ("Failed reading response from remote Trino server" , e );
@@ -57,11 +62,53 @@ public ProxyResponse handle(Request request, Response response)
5762 public record ProxyResponse (
5863 int statusCode ,
5964 ListMultimap <HeaderName , String > headers ,
60- String body )
65+ byte [] body )
6166 {
6267 public ProxyResponse
6368 {
6469 requireNonNull (headers , "headers is null" );
70+ requireNonNull (body , "body is null" );
71+ }
72+
73+ /**
74+ * Get the response body as raw bytes for sending to clients (preserves
75+ * compression)
76+ */
77+ public byte [] getRawBody ()
78+ {
79+ return body ;
80+ }
81+
82+ /**
83+ * Get the response body as a decompressed string for JSON parsing and logging.
84+ * Only call this when you need to parse the content, not when passing through
85+ * to clients.
86+ */
87+ public String getDecompressedBody ()
88+ {
89+ // Check if the response is gzip-compressed
90+ String contentEncoding = null ;
91+ for (HeaderName headerName : headers .keySet ()) {
92+ if (headerName .toString ().equalsIgnoreCase ("Content-Encoding" )) {
93+ contentEncoding = headers .get (headerName ).iterator ().next ();
94+ break ;
95+ }
96+ }
97+
98+ if ("gzip" .equalsIgnoreCase (contentEncoding )) {
99+ try {
100+ try (InputStream inputStream = new GZIPInputStream (new ByteArrayInputStream (body ))) {
101+ return new String (inputStream .readAllBytes (), StandardCharsets .UTF_8 );
102+ }
103+ }
104+ catch (IOException e ) {
105+ // If decompression fails, return the body as UTF-8 string
106+ return new String (body , StandardCharsets .UTF_8 );
107+ }
108+ }
109+
110+ // Not compressed, convert bytes to string
111+ return new String (body , StandardCharsets .UTF_8 );
65112 }
66113 }
67114}
0 commit comments