Lets have a look on how to send HTTP GET Request with a Request Body using RestTemplate!
As much as I dislike the idea of having a HTTP GET request with a request body, I recently got stuck with one. I had to call an external service endpoint, in one of my projects last week. Sadly it was a HTTP GET API endpoint but it required a… wait for it… REQUEST BODY!
The project uses RestTemplate as a main HTTP Client for all API calls. I tried using exchange
method with different combinations or request body and headers but failed, as the request body wasn’t being sent to the external service. Guess what’s the worse part? They didn’t have meaningful error messages either. IKR?!
After spending more than 4 hours, I figured out that RestTemplate doesn’t support Http Get request with a Request Body by default. As the RestTemplate was massively used throughout the project, I couldn’t migrate to any other client. I figured out a way to keep using RestTemplate while making sure the request body is sent in the GET request – and that too without any hacks.
Here is a small code that you need to add to your spring project and it would start working.
import java.net.URI; import org.springframework.http.HttpEntity; import org.springframework.http.HttpMethod; import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; import org.apache.http.client.methods.HttpUriRequest; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; . . . public class Client { private final RestTemplate restTemplate; public Client() { restTemplate = new RestTemplate(new CustomHttpComponentsClientHttpRequestFactory()); } private void getWithBody(Object requestBody) { String responseBody = restTemplate.exchange(endpoint, HttpMethod.GET, new HttpEntity<>(requestBody), String.class).getBody(); } private static final class CustomHttpComponentsClientHttpRequestFactory extends HttpComponentsClientHttpRequestFactory { @Override protected HttpUriRequest createHttpUriRequest(HttpMethod httpMethod, URI uri) { if (HttpMethod.GET.equals(httpMethod)) { return new HttpEntityEnclosingGetRequestBase(uri); } return super.createHttpUriRequest(httpMethod, uri); } } private static final class HttpEntityEnclosingGetRequestBase extends HttpEntityEnclosingRequestBase { public HttpEntityEnclosingGetRequestBase(final URI uri) { super.setURI(uri); } @Override public String getMethod() { return HttpMethod.GET.name(); } } }
Now that we have the config is ready to use, lets override the request-factory for our RestTemplate instance. All you need need to do is use the setRequestFactory
method of your RestTemplate instance and inject a new instance of CustomHttpComponentsClientHttpRequestFactory
class
restTemplate.setRequestFactory(new CustomHttpComponentsClientHttpRequestFactory());
And… you are welcome mates!
Do not forget to share this with your team mates, if that solves your problem. Cheers 🙂
Paul J. Suraez says
BRILLIANT! I’ve been scratching my head why my request is not going through!
Thanks youu!!!
Fabrice says
Thank you very much!!
Brandon Gallagher says
thanks! that was super helpful and easy to implement.
Mike Y says
You are a genius my man
Sadik says
dude you deserve respect
Ryan says
It is just me that the solution is not working for?
thegeekyasian says
Please feel free to share the issue you are facing
Nikolai says
public String getWithBody(String endpoint, String requestBody) {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setContentLength(requestBody.length());
return restTemplate.exchange(endpoint, HttpMethod.GET, new HttpEntity(requestBody, headers), String.class).getBody();
}