[SalesForce] Apex Rest Web Service not sending compressed gzip response

I have an Apex Rest web service that is being called from a Java client and I want the response to be in GZIP format.

Here is part of my code where from I am adding headers in the PATCH request from Java:

StringEntity messageEntity = new StringEntity(parentJSONObj.toString(), ContentType.create("application/json"));

HttpPatch httpPatchToSendUpdatedRecords = new HttpPatch(instanceURL + "/services/apexrest/SyncSFBusinessPartnerComp/");
httpPatchToSendUpdatedRecords.addHeader("Authorization", "OAuth " + accessToken);
httpPatchToSendUpdatedRecords.addHeader("Content-Type", "application/json");
httpPatchToSendUpdatedRecords.addHeader("Accept", "application/json");
httpPatchToSendUpdatedRecords.addHeader("Accept-Encoding", "gzip");
httpPatchToSendUpdatedRecords.setEntity(messageEntity);

However when I get back the response, the header Content-Encoding: gzip isn't there in the Response. I am checking the headers thus:

CloseableHttpResponse closeableresponse = httpclient.execute(httpPatchToSendUpdatedRecords);
for(Header header: closeableresponse.getAllHeaders()) {
    System.out.println("Header " + header.getName() + ":" + header.getValue());
}

So that means my response is not compressed, am I correct?

The second line here gives exception:

HttpEntity entity = closeableresponse.getEntity();
String content = EntityUtils.toString(entity);//Gives exception java.util.zip.ZipException: Not in GZIP format

Any ideas what I am missing? Do I have to write additional code on the server side to compress the response? This is what I am returning from server side:

RestContext.response.responseBody = Blob.valueOf(gen.getAsString());

where gen is a JSONGenerator object.

Edit:

I have found the cause of the ZipException, it was because I was forcefully trying to set the response header from the server in this way:
RestContext.response.addHeader('Content-Encoding', 'gzip');
On removing this line there are not more exceptions. All the same, the Content-Encoding header is still not there…

Here are my response headers:

Header Date:Tue, 10 Apr 2018 10:06:33 GMT
Header Strict-Transport-Security:max-age=31536000; includeSubDomains
Header X-Content-Type-Options:nosniff
Header X-XSS-Protection:1; mode=block
Header Content-Security-Policy:upgrade-insecure-requests
Header X-Robots-Tag:none
Header Cache-Control:no-cache,must-revalidate,max-age=0,no-store,private
Header Set-Cookie:BrowserId=Tg2r62kASpabEtQUVeSrXg;Path=/;Domain=.salesforce.com;Expires=Sat, 09-Jun-2018 10:06:33 GMT;Max-Age=5184000
Header Expires:Thu, 01 Jan 1970 00:00:00 GMT
Header Content-Type:application/json
Header Transfer-Encoding:chunked

Best Answer

Found this oddity in the Docs (my emphasis): Source - Using Compression

To use compression, include the HTTP header Accept-Encoding: gzip or Accept-Encoding: deflate in a request. The REST API compresses the response if the client properly specifies this header. The response includes the header Content-Encoding: gzip or Accept-Encoding: deflate. You can also compress any request by including a Content-Encoding: gzip or Content-Encoding: deflate header.

Response Compression

The REST API can optionally compress responses. Responses are compressed only if the client sends an Accept-Encoding header. The REST API is not required to compress the response even if you have specified Accept-Encoding, but it normally does. If the REST API compresses the response, it also specifies a Content-Encoding header.

It would appear that while they probably will send back a response compressed as you have requested they don't have to. It seems odd, and there is no further clarification provided in the docs on whey they might bypass the compression.

I suspect you will need to check the response headers before attempting to decompress it.


I've come across this before in gzip Compression not working on custom REST API.

In that case the issue was around sending the blob back directly in the response without explicitly setting the response content type.

Try something like:

RestContext.response.responseBody = Blob.valueOf(gen.getAsString());
RestContext.response.addHeader('Content-Type', 'application/json');

It might help to be explicit so the Salesforce knows what is going back and that it can be compressed.

Related Topic