Add my custom http header to Spring RestTemplate request / extend RestTemplate
Asked Answered
L

4

51

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.

Lipfert answered 17/9, 2015 at 5:54 Comment(0)
V
64

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();
Volumed answered 17/9, 2015 at 6:7 Comment(11)
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 caseLipfert
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?Lipfert
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.Volumed
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 notLipfert
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.Volumed
OK, thanks for suggestion, acutally server does not provide any validation yet.Lipfert
I updated my question, sorry for removing 'accepted' - I need more info.Lipfert
https://mcmap.net/q/108782/-how-to-set-an-quot-accept-quot-header-on-spring-resttemplate-request . refer this link.Volumed
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: blog.tzolov.net/2010/03/…Lipfert
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.Pinery
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.Footer
E
47

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();
Entomology answered 31/3, 2020 at 11:6 Comment(5)
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.Tetrad
I want to do the same thing but for POST body instead of headers. I want to send same key:value pair in POST urlformencoded payload. Any idea how?Asuncionasunder
@BossMan What about modifying the bodybefore return execution.execute(request, body);?Entomology
@Entomology Type of body is byte[]. I guess I should have said "Any idea how to do it efficiently?"Asuncionasunder
@BossMan: well, maybe there are other options, but why not parsing the body, maybe convert it into a string and append, filter, prepend anything you want? If you find a static pattern you could preinitialize this data somehow and reuse it.Entomology
N
9

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());
Notional answered 10/1, 2019 at 15:9 Comment(2)
why/how is 'parameters' the proper way to set headers?Find
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.Byblow
S
2

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
  }
Silverware answered 23/12, 2020 at 21:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.