Spring Framework
  1. Spring Framework
  2. SPR-9999

Spring RestTemplate does not capture response body when error code 40x is returned

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Duplicate
    • Affects Version/s: 3.1.2
    • Fix Version/s: None
    • Component/s: Web, Web:Client
    • Labels:
      None

      Description

      When invoking rest endpoints with HTTP POST protocol via spring RestTemplate,
      given error code 4xx is encountered, the response body is not captured and made available to the caller.

      An example snippet code is as followed:

      try {
        // invoking a rest endpoint that expects string object in returned,
        // even when the target rest endpoint returns a 4xx status code.
        String response = this.restTemplate.postForObject(url, form, String.class);
      } catch (HtttpClientErrorException hcee) {
        // encountered 4xx problem from the server, but response body is not 
        // captured
        // the following assertion failed because the response body is expected to contain string values,   
        Assert.assertTrue(hcee.getResponseBodyAsByteArray().length > 0);
      }
      

      An example of response content (both header and body) is demonstrated with an invocation to the REST end point via curl: (response body contains exception name with name and message)

      $ curl -id "username=blah&password=blah" http://localhost:8088/opensso/identity/authenticate
        % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                       Dload  Upload   Total   Spent    Left  Speed
      100   110  100    83  100    27   2677    870 --:--:-- --:--:-- --:--:--  5533HTTP/1.1 401 Unauthorized
      Server: Apache-Coyote/1.1
      Set-Cookie: amlbcookie=01; Path=/
      Content-Type: text/plain;charset=UTF-8
      Content-Length: 83
      Date: Fri, 16 Nov 2012 15:34:41 GMT
      
      exception.name=com.sun.identity.idsvcs.InvalidCredentials Authentication Failed!!
      

      Note the similar invocation using HTTP GET protocol works just fine (i.e. restTemplate.getForObject(..) ), as described in the forum thread attached in this jira ticket.

        Activity

        Hide
        Rossen Stoyanchev added a comment -

        Strange indeed since the DefaultResponseErrorHandler raises the HttpClientErrorException with the response body regardless of the HTTP method. It would help if could help demonstrate the issue.

        Show
        Rossen Stoyanchev added a comment - Strange indeed since the DefaultResponseErrorHandler raises the HttpClientErrorException with the response body regardless of the HTTP method. It would help if could help demonstrate the issue .
        Hide
        Ho Tri Bao added a comment -

        I have got the same problem.

        Scenario:

        • If there is failure (for example: invalid password), an 401-Unauthorized status code is returned and the body of the response contains the exception describing the problem.
        • Use the default constructor to create RestTemplate instance
        • Result: HttpClientErrorException.getResponseBodyAsString() return null

        =====
        The cause may be: the default constructor of RestTemplate will use SimpleClientHttpRequestFactory which will produce SimpleClientHttpResponse. The method getBody() of SimpleClientHttpResponse looks like
        InputStream errorStream = this.connection.getErrorStream();
        return (errorStream != null ? errorStream : this.connection.getInputStream());

        The getErrorStream() return null thus the getInputStream() will be calle. In this case, which in turn, will result an exception with the message "cannot retry due to server authentication, in streaming mode". The method getResponseBody() of the DefaultResponseErrorHandler ignore all exceptions and return null.

        === Workaround, don't use SimpleClientHttpRequestFactory, use HttpComponentsClientHttpRequestFactory:
        RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());

        Show
        Ho Tri Bao added a comment - I have got the same problem. Scenario: use RestTemplate to invoke a REST endpoint of OpenAM which authenticate a user ( https://wikis.forgerock.org/confluence/display/openam/Use+OpenAM+RESTful+Services#UseOpenAMRESTfulServices-Authentication ) If there is failure (for example: invalid password), an 401-Unauthorized status code is returned and the body of the response contains the exception describing the problem. Use the default constructor to create RestTemplate instance Result: HttpClientErrorException.getResponseBodyAsString() return null ===== The cause may be: the default constructor of RestTemplate will use SimpleClientHttpRequestFactory which will produce SimpleClientHttpResponse. The method getBody() of SimpleClientHttpResponse looks like InputStream errorStream = this.connection.getErrorStream(); return (errorStream != null ? errorStream : this.connection.getInputStream()); The getErrorStream() return null thus the getInputStream() will be calle. In this case, which in turn, will result an exception with the message "cannot retry due to server authentication, in streaming mode". The method getResponseBody() of the DefaultResponseErrorHandler ignore all exceptions and return null. === Workaround, don't use SimpleClientHttpRequestFactory, use HttpComponentsClientHttpRequestFactory: RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
        Hide
        Rossen Stoyanchev added a comment -

        This looks the same as the issue described in SPR-9367. I added a warning in the reference documentation. I'm open to suggestions for where else to document that might have helped you notice it.

        Show
        Rossen Stoyanchev added a comment - This looks the same as the issue described in SPR-9367 . I added a warning in the reference documentation. I'm open to suggestions for where else to document that might have helped you notice it.

          People

          • Assignee:
            Rossen Stoyanchev
            Reporter:
            Wei Teh
            Last updater:
            Rossen Stoyanchev
          • Votes:
            2 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:
              Days since last comment:
              50 weeks ago