I am trying to submit a POST request to an API to get a JSON payload in Response. My application is a Spring Boot 3.5 application. I am using RestClient to make the request. The request is accepted successfully, but the response I get back in the response body is unprintable / encoded characters. Status Code is 200. I am able to make successful request in Postman
Here is my constructor code which sets up the RestClient object:
public VivxWebApiService(RestClient.Builder restClientBuilder, ApplicationLocationConfiguration applicationLocationConfiguration) {
List<HttpMessageConverter<?>> vivxHttpMessageConverters = new ArrayList<>();
vivxHttpMessageConverters.add(new FormHttpMessageConverter());
vivxHttpMessageConverters.add(new MappingJackson2HttpMessageConverter());
this.restClient = restClientBuilder
.baseUrl(applicationLocationConfiguration.getVivxWebApi())
.messageConverters(vivxHttpMessageConverters)
.build();
this.restClient.head().accept(MediaType.APPLICATION_JSON);
}
The method that does the actual POST call:
public void getDesignColors(String designName) {
LOG.debug("Attempting to get design colors for design: {}", designName);
String getColorsUri = "/design/colors";
MultiValueMap<String, String> mvMap = new LinkedMultiValueMap<>();
mvMap.add("name",designName);
ResponseEntity<VivxDesignColorDataResponse> getColorsResponse = restClient.post()
.uri(getColorsUri)
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.body(mvMap)
.retrieve()
.toEntity(VivxDesignColorDataResponse.class);
LOG.debug("GetColorResponse: {}", getColorsResponse);
}
I have tried many different iterations of using ".toEntity()" or ".body()" to get the response, but nothing seems to work.
I did put a request interceptor in the RestClient to get debug, and this is what it shows:
2025-07-23T21:23:03.758-05:00 DEBUG 3000 --- [art-services] [nio-8083-exec-1] c.j.b.a.service.VivxWebApiService : Attempting to get design colors for design: 3408315_SP032826_71153
2025-07-23T21:23:03.762-05:00 DEBUG 3000 --- [art-services] [nio-8083-exec-1] o.s.web.client.DefaultRestClient : Writing [{name=[3408315_SP032826_71153]}] as "application/x-www-form-urlencoded" with org.springframework.http.converter.FormHttpMessageConverter
2025-07-23T21:23:08.478-05:00 INFO 3000 --- [art-services] [nio-8083-exec-1] c.j.b.a.service.VivxWebApiService : Request: POST https://devneffvivx.jostensaws.com/vivxwebapi/design/colors
2025-07-23T21:23:08.478-05:00 INFO 3000 --- [art-services] [nio-8083-exec-1] c.j.b.a.service.VivxWebApiService : Response headers: [Content-Type:"application/x-www-form-urlencoded", Content-Length:"27"]
2025-07-23T21:23:08.478-05:00 INFO 3000 --- [art-services] [nio-8083-exec-1] c.j.b.a.service.VivxWebApiService : Request body: name=3408315_SP032826_71153
2025-07-23T21:23:10.645-05:00 INFO 3000 --- [art-services] [nio-8083-exec-1] c.j.b.a.service.VivxWebApiService : Response status: 200 OK
2025-07-23T21:23:10.645-05:00 INFO 3000 --- [art-services] [nio-8083-exec-1] c.j.b.a.service.VivxWebApiService : Response headers: [:status:"200", access-control-allow-headers:"Content-Type", access-control-allow-origin:"*", content-encoding:"gzip", content-type:"application/json", date:"Thu, 24 Jul 2025 02:23:08 GMT", server:"Microsoft-HTTPAPI/2.0"]
2025-07-23T21:23:14.496-05:00 INFO 3000 --- [art-services] [nio-8083-exec-1] c.j.b.a.service.VivxWebApiService : Response body: �
�C�!�=���9�iHq��h껬&
2025-07-23T21:23:14.498-05:00 DEBUG 3000 --- [art-services] [nio-8083-exec-1] c.j.b.a.service.VivxWebApiService : GetColorResponse: <200 OK OK,[:status:"200", access-control-allow-headers:"Content-Type", access-control-allow-origin:"*", content-encoding:"gzip", content-type:"application/json", date:"Thu, 24 Jul 2025 02:23:08 GMT", server:"Microsoft-HTTPAPI/2.0"]>
Any idea what setup I may have incorrect/missing?
2025-07-23T21:23:10.645-05:00 INFO 3000 --- [art-services] [nio-8083-exec-1] c.j.b.a.service.VivxWebApiService : Response headers: [:status:"200", access-control-allow-headers:"Content-Type", access-control-allow-origin:"*", content-encoding:"gzip", content-type:"application/json", date:"Thu, 24 Jul 2025 02:23:08 GMT", server:"Microsoft-HTTPAPI/2.0"]
This line says it all. To be more precise this header content-encoding:"gzip",
gives it away, you are getting a gzipped response. Which you must first decompress before you can use it.
You can do this in 2 ways
ClientInterceptor
to wrap the incoming response to decompressFirst create a custom response
public class GzipDecompressingClientHttpResponse implements ClientHttpResponse {
private final ClientHttpResponse response;
public GzipDecompressingClientHttpResponse(ClientHttpResponse response) {
this.response = response;
}
@Override
public InputStream getBody() throws IOException {
InputStream body = response.getBody();
if (isGzipped(response)) {
return new GZIPInputStream(new BufferedInputStream(body));
}
return body;
}
private boolean isGzipped(ClientHttpResponse response) {
String contentEncoding = response.getHeaders().getFirst("Content-Encoding");
return contentEncoding != null && contentEncoding.toLowerCase().contains("gzip");
}
@Override
public HttpStatusCode getStatusCode() throws IOException {
return response.getStatusCode();
}
@Override
public String getStatusText() throws IOException {
return response.getStatusText();
}
@Override
public void close() {
response.close();
}
@Override
public org.springframework.http.HttpHeaders getHeaders() {
return response.getHeaders();
}
}
Then add an interceptor to wrap the incoming ClientResponse
with this GzipDecompressingClientHttpResponse
.
public class GzipResponseInterceptor implements ClientHttpRequestInterceptor {
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
throws IOException {
return new GzipDecompressingClientHttpResponse(execution.execute(request, body));
}
}
this.restClient = restClientBuilder
.baseUrl(applicationLocationConfiguration.getVivxWebApi())
.messageConverters(vivxHttpMessageConverters)
.requestInterceptor(new GzipResponseInterceptor());
.build();
Benefit of this solution is that it will work regardless of the technology in use.
You can also switch the HTTP client used by the RestClient
when using the default it will use the JDK provided HTTP client. You can switch this to one that automatically will support gzip responses, like Apache Http Client.
You will need to add a dependency on the client and configure the builder to take that as the HTTP client to use.
this.restClient = restClientBuilder
.baseUrl(applicationLocationConfiguration.getVivxWebApi())
.messageConverters(vivxHttpMessageConverters)
.requestFactory(new HttpComponentsClientHttpRequestFactory(HttpClientBuilder.create().build())););
.build();
This will work without adding an additional interceptor, drawback is you need an additional dependency.
See also this answer and this blog which were used as inspiration for this answer.