41

My current code:

RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
Mall[] malls = restTemplate.getForObject(url, Mall[].class);

I need to add some custom headers for my request, in form:

X-TP-DeviceID : <GUID>

What is the simplest way to do that in my case? Is there any way to add custom headers definition to my restTemplate object before I send the request to server?

[edit]

Is it correct?

RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());

HttpHeaders headers = new HttpHeaders();
headers.set("X-TP-DeviceID", "1234567890");
HttpEntity entity = new HttpEntity(headers);

HttpEntity<Mall[]> response = restTemplate.exchange(url, HttpMethod.GET, entity, Mall[].class);

Mall[] malls = response.getBody();

[added]

So, I managed to get it working. However, I'm not fully satisfied with that. In my case I will need to provide the same custom headers for all the calls I make.

So, my next question is - Is it possible to set my custom headers to be added automatically on each web-service call, for example, by extending RestTemplate class and putting all custom headers there? Then, all I would be needing to do would be to simply use my custom extended RestTemplate instead of the stock one, and all my custom headers will be present there by default.

djm.im
  • 2,652
  • 3
  • 24
  • 40
user1209216
  • 5,410
  • 7
  • 45
  • 95

4 Answers4

54

You can pass custom http headers with RestTemplate exchange method as below.

HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(new MediaType[] { MediaType.APPLICATION_JSON }));
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("X-TP-DeviceID", "your value");

HttpEntity<RestRequest> entityReq = new HttpEntity<RestRequest>(request, headers);

RestTemplate template = new RestTemplate();

ResponseEntity<RestResponse> respEntity = template
    .exchange("RestSvcUrl", HttpMethod.POST, entityReq, RestResponse.class);

EDIT : Below is the updated code. This link has several ways of calling rest service with examples

RestTemplate restTemplate = new RestTemplate();

HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("X-TP-DeviceID", "your value");

HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);

ResponseEntity<Mall[]> respEntity = restTemplate.exchange(url, HttpMethod.POST, entity, Mall[].class);

Mall[] resp = respEntity.getBody();
kswaughs
  • 2,623
  • 1
  • 13
  • 19
  • Sorry, it's still not clear for me. Can you provide modified version of my code? Do you mean I will have Mall[] instead of RestRresponse? What is "request"? Should I add your respEntity object as parameter to getForObject call? Also I need http method get in my case – user1209216 Sep 17 '15 at 06:14
  • Thx, I also found slightly different solution, is it correct too? I updated my question. Btw I can use headers.add or headers.set, what is the difference between them? – user1209216 Sep 17 '15 at 06:37
  • Your code seems correct to me but couldn't tell until I test it. If it is working for you. then it is correct. I don't know exact difference between add or set. – kswaughs Sep 17 '15 at 06:46
  • 1
    Can I check somehow if my custom header is really set? Without access to server logs. It works, I can get response succesfully but I don't know if my app actually send my custom header or not – user1209216 Sep 17 '15 at 06:51
  • I am not sure but you can write a new Interceptor ClientHttpRequestInterceptor and override intercept method and log the request. But this code sends headers in the request. or try with wrong value of X-TP-DeviceID if your service has some validation on it. – kswaughs Sep 17 '15 at 07:13
  • OK, thanks for suggestion, acutally server does not provide any validation yet. – user1209216 Sep 17 '15 at 08:06
  • I updated my question, sorry for removing 'accepted' - I need more info. – user1209216 Sep 17 '15 at 09:57
  • [http://stackoverflow.com/a/28363700/5038825](http://stackoverflow.com/a/28363700/5038825) . refer this link. – kswaughs Sep 17 '15 at 10:03
  • Ok, but I still need to set interceptor for each RestTemplate. In my case I have multiple RestTemplate objects in use, so approach you proposed does not help too much. It would be better to have custom RestTemplate class, with all headers already preset. Something like this: http://blog.tzolov.net/2010/03/spring-3-resttemplate-access-to-request.html – user1209216 Sep 17 '15 at 10:09
  • 2
    Please clarify what "parameters" means in the HttpEntity ctor. Is this a magic value (must be exactly that), is there a constant somewhere that could be used, or is it ignored? Thx in adv. – chrisinmtown May 15 '18 at 12:48
  • 1
    yikes. crazy how bad this is. It's sort of a deal breaker for using RestTemplate. It's very common for webservice clients to pass a few custom default headers. – dustinevan Oct 25 '19 at 20:14
21

If the goal is to have a reusable RestTemplate which is in general useful for attaching the same header to a series of similar request a org.springframework.boot.web.client.RestTemplateCustomizer parameter can be used with a RestTemplateBuilder:

 String accessToken= "<the oauth 2 token>";
 RestTemplate restTemplate = new RestTemplateBuilder(rt-> rt.getInterceptors().add((request, body, execution) -> {
        request.getHeaders().add("Authorization", "Bearer "+accessToken);
        return execution.execute(request, body);
    })).build();
k_o_
  • 2,597
  • 19
  • 26
  • 3
    Not sure why this one was downvoted to the point of being negative as it seems exactly on point to me and once I epurated it from RestTemplateBuilder (not a spring-boot project in my case) it worked flawlessly. – Filippo Possenti May 14 '20 at 12:57
4

Add a "User-Agent" header to your request.

Some servers attempt to block spidering programs and scrapers from accessing their server because, in earlier days, requests did not send a user agent header.

You can either try to set a custom user agent value or use some value that identifies a Browser like "Mozilla/5.0 Firefox/26.0"

RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();

headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("user-agent", "Mozilla/5.0 Firefox/26.0");
headers.set("user-key", "your-password-123"); // optional - in case you auth in headers
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
ResponseEntity<Game[]> respEntity = restTemplate.exchange(url, HttpMethod.GET, entity, Game[].class);

logger.info(respEntity.toString());
djm.im
  • 2,652
  • 3
  • 24
  • 40
Sean Gildea
  • 171
  • 1
  • 4
  • 1
    why/how is 'parameters' the proper way to set headers? – beauXjames Feb 19 '20 at 16:32
  • Note that the difference between `HttpHeaders#add` and `HttpHeaders#set` is that the former will add a new header while the latter will overwrite a header, should it already exist. – Tim Biegeleisen Apr 01 '21 at 03:21
1

Here's a method I wrote to check if an URL exists or not. I had a requirement to add a request header. It's Groovy but should be fairly simple to adapt to Java. Essentially I'm using the org.springframework.web.client.RestTemplate#execute(java.lang.String, org.springframework.http.HttpMethod, org.springframework.web.client.RequestCallback, org.springframework.web.client.ResponseExtractor<T>, java.lang.Object...) API method. I guess the solution you arrive at depends at least in part on the HTTP method you want to execute. The key take away from example below is that I'm passing a Groovy closure (The third parameter to method restTemplate.execute(), which is more or less, loosely speaking a Lambda in Java world) that is executed by the Spring API as a callback to be able to manipulate the request object before Spring executes the command,

boolean isUrlExists(String url) {
    try {
      return (restTemplate.execute(url, HttpMethod.HEAD,
              { ClientHttpRequest request -> request.headers.add('header-name', 'header-value') },
              { ClientHttpResponse response -> response.headers }) as HttpHeaders)?.get('some-response-header-name')?.contains('some-response-header-value')
    } catch (Exception e) {
      log.warn("Problem checking if $url exists", e)
    }
    false
  }
Jose Quijada
  • 339
  • 1
  • 10