63

I am trying to get Apache HttpClient to fire an HTTP request, and then display the HTTP response code (200, 404, 500, etc.) as well as the HTTP response body (text string). It is important to note that I am using v4.2.2 because most HttpClient examples out there are from v.3.x.x and the API changed greatly from version 3 to version 4.

Unfortunately I've only been able to get HttpClient returning the status code or the response body (but not both).

Here's what I have:

// Getting the status code.
HttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet("http://whatever.blah.com");
HttpResponse resp = client.execute(httpGet);

int statusCode = resp.getStatusLine().getStatusCode();


// Getting the response body.
HttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet("http://whatever.blah.com");
ResponseHandler<String> handler = new BasicResponseHandler();

String body = client.execute(httpGet, handler);

So I ask: Using the v4.2.2 library, how can I obtain both status code and response body from the same client.execute(...) call?

starball
  • 20,030
  • 7
  • 43
  • 238
IAmYourFaja
  • 55,468
  • 181
  • 466
  • 756
  • 1
    What happens when you try to read both values from the same call? AFAIK there should be no problem with it. Also, keep in mind that it is possible, for error codes, that the server sends no content at all (for example, if there is no `whatever.blah.com` server). – SJuan76 Dec 24 '12 at 18:36
  • See also http://stackoverflow.com/questions/5769717/how-can-i-get-an-http-response-body-as-a-string-in-java – Vadzim Apr 04 '14 at 18:24
  • I have added this to the jira board for the project https://issues.apache.org/jira/browse/HTTPCLIENT-1581 – javamonkey79 Nov 21 '14 at 17:56

5 Answers5

76

Don't provide the handler to execute.

Get the HttpResponse object, use the handler to get the body and get the status code from it directly

try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
    final HttpGet httpGet = new HttpGet(GET_URL);

    try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
        StatusLine statusLine = response.getStatusLine();
        System.out.println(statusLine.getStatusCode() + " " + statusLine.getReasonPhrase());
        String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
        System.out.println("Response body: " + responseBody);
    }
}

For quick single calls, the fluent API is useful:

Response response = Request.Get(uri)
        .connectTimeout(MILLIS_ONE_SECOND)
        .socketTimeout(MILLIS_ONE_SECOND)
        .execute();
HttpResponse httpResponse = response.returnResponse();
StatusLine statusLine = httpResponse.getStatusLine();

For older versions of java or httpcomponents, the code might look different.

tkruse
  • 10,222
  • 7
  • 53
  • 80
Aviram Segal
  • 10,962
  • 3
  • 39
  • 52
  • 3
    This works for 2xx status only, others will throw when using BasicResponseHandler, see my [answer](http://stackoverflow.com/a/26285342/300053). – eskatos Oct 09 '14 at 18:17
  • You saved my day dude. Wondering how the dev world would have looked like if there was no SO. :-). – Ajay Kumar Dec 13 '20 at 17:14
37

You can avoid the BasicResponseHandler, but use the HttpResponse itself to get both status and response as a String.

HttpResponse response = httpClient.execute(get);

// Getting the status code.
int statusCode = response.getStatusLine().getStatusCode();

// Getting the response body.
String responseBody = EntityUtils.toString(response.getEntity());
lkamal
  • 3,788
  • 1
  • 20
  • 34
15

BasicResponseHandler throws if the status is not 2xx. See its javadoc.

Here is how I would do it:

HttpResponse response = client.execute( get );
int code = response.getStatusLine().getStatusCode();
InputStream body = response.getEntity().getContent();
// Read the body stream

Or you can also write a ResponseHandler starting from BasicResponseHandler source that don't throw when the status is not 2xx.

eskatos
  • 4,174
  • 2
  • 40
  • 42
6

Fluent facade API:

Response response = Request.Get(uri)
        .connectTimeout(MILLIS_ONE_SECOND)
        .socketTimeout(MILLIS_ONE_SECOND)
        .execute();
HttpResponse httpResponse = response.returnResponse();
StatusLine statusLine = httpResponse.getStatusLine();
if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
    // 响应内容编码自适应?(好像没那么智能)
    String responseContent = EntityUtils.toString(
            httpResponse.getEntity(), StandardCharsets.UTF_8.name());
}
Edward Lee
  • 111
  • 3
  • 5
1

If you are using Spring

return new ResponseEntity<String>("your response", HttpStatus.ACCEPTED);
lkamal
  • 3,788
  • 1
  • 20
  • 34
vsingh
  • 6,365
  • 3
  • 53
  • 57