RestTemplate with custom HTTP headers

Spring Framework’s RestTemplate provides simple ways to make requests to RESTful services. When you want to set additional HTTP headers to such requests, then a tiny bit of more work is needed.

Starting from Spring Framework version 3.0.2 it is possible to utilise HttpEntity class. An example of querying a PDF file from a server:

private static final String APPLICATION_PDF = "application/pdf";

RestTemplate restTemplate = new RestTemplate();

@Test
public void acceptHeaderUsingHttpEntity() throws Exception {
  HttpHeaders headers = new HttpHeaders();
  headers.setAccept(singletonList(MediaType.valueOf(APPLICATION_PDF)));

  ResponseEntity<byte[]> response = restTemplate.exchange("http://example.com/file/123",
      GET,
      new HttpEntity<byte[]>(headers),
      byte[].class);

  String responseText = PdfTextExtractor.getTextFromPage(new PdfReader(response.getBody()), 1);
  assertEquals("Some text in PDF file", responseText);
}

(I’m using iText here for PDF file manipulation.)

Starting from Spring Framework version 3.1 there is a more powerful alternative — ClientHttpRequestInterceptor. ClientHttpRequestInterceptor.intercept() enables more control over the HTTP request that will be sent. Here’s the simple example again, using the interceptor concept:

private static final String APPLICATION_PDF = "application/pdf";

RestTemplate restTemplate = new RestTemplate();

@Test
public void acceptHeaderUsingHttpRequestInterceptors() throws Exception {
  ClientHttpRequestInterceptor acceptHeaderPdf = new AcceptHeaderHttpRequestInterceptor(
      APPLICATION_PDF);

  restTemplate.setInterceptors(singletonList(acceptHeaderPdf));

  byte[] response = restTemplate.getForObject("http://example.com/file/123", byte[].class);

  String responseText = PdfTextExtractor.getTextFromPage(new PdfReader(response), 1);
  assertEquals("Some text in PDF file", responseText);
}

class AcceptHeaderHttpRequestInterceptor implements ClientHttpRequestInterceptor {
  private final String headerValue;

  public AcceptHeaderHttpRequestInterceptor(String headerValue) {
    this.headerValue = headerValue;
  }

  @Override
  public ClientHttpResponse intercept(HttpRequest request, byte[] body,
      ClientHttpRequestExecution execution) throws IOException {

    HttpRequestWrapper requestWrapper = new HttpRequestWrapper(request);
    requestWrapper.getHeaders().setAccept(singletonList(MediaType.valueOf(headerValue)));

    return execution.execute(requestWrapper, body);
  }
}

17 thoughts on “RestTemplate with custom HTTP headers

  1. This is awesome! thanks for the code. I am running into a problem with using exchange() on spring 3.0.6 where HttpMethod.DELETE is not allowed to have a body. I have tried many many configurations, and every time my handler functions get an empty ” @RequestBody String bodyData “. Do you think I could use this Interceptor to add a body when using a delete? Or possibly start off with POST and then rewrite to DELETE so that the body is preserved!? I understand that this requires an upgrade to 3.1. Thanks so much for this article!

  2. Sven Filatov says:

    RestTemplate by default uses Spring’s own SimpleClientHttpRequestFactory. This factory creates requests with such settings, that HTTP body is supported by POST and PUT methods only. Forcing SimpleClientHttpRequestFactory to use HTTP body in case of DELETE method won’t work, because JDK’s HttpURLConnection does not enable this (you would get an IOException during runtime if you try that).

    Switching RestTemplate’s request factory simply to Apache HTTPClient’s HttpComponentsClientHttpRequestFactory unfortunately won’t help either, because HttpDelete does not support HttpEntity, unlike HttpPost and HttpPut.

    So it seems JDK and Apache HttpClient HTTP request factories work the same way. I’m afraid using an interceptor won’t improve things in this case either.

    Interestingly, HTTP RFC does not forbid using HTTP body with DELETE. See also http://stackoverflow.com/questions/299628/is-an-entity-body-allowed-for-an-http-delete-request for more information about this.

    With some level of hacking (YMMV), it is possible to make RestTemplate handle HTTP body for DELETE requests. For this, you need to create a custom request factory that is able to create a custom implementation for DELETE method requests. Something like this:

    The test:

        RestTemplate restTemplate = new RestTemplate();
    
        public static class HttpEntityEnclosingDeleteRequest extends HttpEntityEnclosingRequestBase {
    
            public HttpEntityEnclosingDeleteRequest(final URI uri) {
                super();
                setURI(uri);
            }
    
            @Override
            public String getMethod() {
                return "DELETE";
            }
        }
    
        @Test
        public void bodyWithDeleteRequest() throws Exception {
            restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory() {
                @Override
                protected HttpUriRequest createHttpUriRequest(HttpMethod httpMethod, URI uri) {
                    if (HttpMethod.DELETE == httpMethod) {
                        return new HttpEntityEnclosingDeleteRequest(uri);
                    }
                    return super.createHttpUriRequest(httpMethod, uri);
                }
            });
    
            ResponseEntity<String> exchange = restTemplate.exchange(
                    "http://example.com/file",
                    HttpMethod.DELETE,
                    new HttpEntity<String>("some sample body sent along the DELETE request"),
                    String.class);
            assertEquals("Got body: some sample body sent along the DELETE request", exchange.getBody());
        }
    

    The server/controller under test:

        @RequestMapping(value = "/file", method = DELETE)
        @ResponseBody
        public String deleteSecci(@RequestBody String body) {
            return "Got body: " + body;
        }
    
  3. Sven,

    Thank you so much for posting this! I almost feel like this could be it’s own blog post. I haven’t tried this yet, but I will check it out very soon and get back to you. I am using this code as part of a unit test for my own REST api, but I can live without this test for now.

    It’s annoying to learn that Java (and others!) don’t allow a body for DELETE even tho the HTTP RCF allows it. I really appreciate you spending the time to respond to me. Great blog keep it up!

  4. Sven Filatov says:

    Thanks, Benjamin! 🙂

  5. Yogev says:

    Great Post Sven! I just based my integration tests on this post, it was exactly what I was looking for. Thank you so much for posting it!!!

  6. KKK says:

    Great Post. Helped me a lot, Thanks!!!

  7. Mike says:

    Thank you Sven. I knew there was a better way to set headers. Thanks!!!!

  8. NG says:

    Thanks

  9. Sam Mohamed says:

    Perfect post….. helped me a lot!

  10. Jason C says:

    Very helpful! Thanks!

  11. shailendra says:

    hi,
    I have a query . I want to send some string values as well as pdf’s byte array . Can i do that in one call ? if yes how to achive that ?

    • Sven Filatov says:

      Not entirely sure what you want to do. Do you want to send a POST/PUT request with essentially multiple objects (strings and a PDF)? If so, the request body should be a container or envelope of some sort I suppose. In regard to what HTTP headers should be sent along the message, it really depends on what the server expects.

  12. selenefox says:

    Reblogged this on S.F.F.S. — Selene Fox Free Spaces and commented:
    相当赞的一篇博文,Big Thanks

  13. Johne643 says:

    Do you mind if I quote a few of your posts as long as I provide credit and sources back to your weblog? My blog is in the very same niche as yours and my users would truly benefit from a lot of the information you present here. Please let me know if this alright with you. Thank you! feekdeeeeecd

  14. easoncxz says:

    I must say thanks – this saved me a lot of time!

    I was searching on “Spring RestTemplate set header”, and the results I get are all like (these ones are among the more useful ones):

    http://stackoverflow.com/questions/19238715/how-to-set-an-accept-header-on-spring-resttemplate-request
    http://stackoverflow.com/questions/11579621/spring-resttemplate-postforobject-with-header-webservice-cant-find-my-header-p

    But yes, your one is what I have in mind but didn’t know exists!

  15. We can use it in Spring boot for GET Method in the below manner :

    @SpringBootApplication
    public class Application implements CommandLineRunner{

    private static final Logger log = LoggerFactory.getLogger(Application.class);

    public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
    }

    @Override
    public void run(String… args) throws Exception {
    try{
    RestTemplate restTemplate = new RestTemplate();
    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders = this.createHeaders();
    ResponseEntity response;
    response = restTemplate.exchange(“”,HttpMethod.GET,new HttpEntity(httpHeaders),String.class);
    log.info(response.toString());
    }
    catch(Exception e)
    {
    System.out.println(“Exception”+e);
    }

    }

    private HttpHeaders createHeaders(){
    HttpHeaders headers = new HttpHeaders(){
    {
    set( “Authorization”, “3ee140”);
    }
    };

    return headers;
    }

    }

Leave a reply to Sam Mohamed Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.