Resttemplate GET Request with Custom Headers
Asked Answered
L

3

9

I need to send a GET request with a header: Content-Type: application/camiant-msr-v2.0+xml. I expect an XML response from the server. I tested the request and response with Postman and everything is good. But when I try to do it in Spring with RestTemplate, I always get a 400 bad request. The exceptions from spring are:

Jul 09, 2016 12:53:38 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [dispatcherServlet] in context with path [/smp] threw exception [Request processing failed; nested exception is org.springframework.web.client.HttpClientErrorException: 400 Bad Request] with root cause
org.springframework.web.client.HttpClientErrorException: 400 Bad Request
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)
    at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:641)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:597)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:557)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:475)

My code:

MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
headers.add("Content-Type", "application/camiant-msr-v2.0+xml");

HttpEntity<?> entity = new HttpEntity<Object>(headers);
log.debug("request headers: " + entity.getHeaders());
ResponseEntity<String> response = restTemplate.exchange(queryUrl, HttpMethod.GET, entity, String.class);

The debug message shows the header as {Content-Type=[application/camiant-msr-v2.0+xml]}, which seems to be correct. I wonder what's wrong with my request and if there's a way to see the requests on the wire to debug.

Linehan answered 9/7, 2016 at 20:16 Comment(4)
If you are sending a GET, why are you providing a Content-Type header? Do you want it to be Accept instead?Pawl
@Pawl Because the server expects that, only by providing that header, can I get an XML response.Linehan
@Pawl I kinda understand what you mean, but the API spec says that, and also Postman works well.Linehan
@Pawl actually, changing it to Accept worked for me! I think it's because the Java library prevents irregular uses, such as set Content-Type in a GET request. Many thanks!Linehan
L
2

Actually the header to be passed should be named Accept rather than Content-Type, since it's a GET method. But the server API doc somehow says it expects Content-Type, and the API from command line/Postman worked well on both Content-Type and Accept. I think it's the Java library that prevents Content-Type header to be passed to GET requests.

Linehan answered 11/7, 2016 at 17:13 Comment(0)
P
7

The following worked for me:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

@Service
public class Http {

    @Autowired
    private RestTemplate restTemplate;

    public String doGet(final String url) throws Exception {
        MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
        headers.add(HttpHeaders.USER_AGENT, "Mozilla/5.0");
        headers.add(HttpHeaders.ACCEPT_LANGUAGE, "en-US,en;q=0.8");
        HttpEntity<?> entity = new HttpEntity<Object>(headers);
        HttpEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
        return response.getBody();
    }

}
Permission answered 25/8, 2018 at 9:42 Comment(0)
P
3

The possible interpretations of 400 are the content type is not acceptable for a request or url doesn't match.

From my personal experience I have a strong feeling you are messing up the queryUrl so to fine tune things here I would suggest you to use Spring's UriComponentsBuilder class.

UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url)
        .queryParam("data", data);

HttpEntity<?> entity = new HttpEntity<>(headers);

HttpEntity<String> response = restTemplate.exchange(
        builder.build().encode().toUri(), 
        HttpMethod.GET, 
        entity, 
        String.class);

Kindly let me know if it still doesn't work.

Potential answered 9/7, 2016 at 22:55 Comment(1)
thanks a lot for your reply. But I still get the bad request error with your method. I printed out the url, it's exactly the same as the one I used in Postman, which worked well.Linehan
L
2

Actually the header to be passed should be named Accept rather than Content-Type, since it's a GET method. But the server API doc somehow says it expects Content-Type, and the API from command line/Postman worked well on both Content-Type and Accept. I think it's the Java library that prevents Content-Type header to be passed to GET requests.

Linehan answered 11/7, 2016 at 17:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.