¿Cómo puedo obtener un cuerpo de respuesta http como una cadena en Java?

155

Sé que solía haber una manera de obtenerlo con apache commons como se documenta aquí: http://hc.apache.org/httpclient-legacy/apidocs/org/apache/commons/httpclient/HttpMethod.html y un ejemplo aquí:

http://www.kodejava.org/examples/416.html

Pero creo que esto está en desuso. ¿Hay alguna otra forma de hacer una solicitud de obtención de http en java y obtener el cuerpo de respuesta como una cadena y no como una secuencia?

Danés94
fuente
1
Dado que la pregunta y todas las respuestas parecen ser sobre bibliotecas apache, esto debe etiquetarse como tal. No veo nada sin usar libs de terceros.
Eis

Respuestas:

104

Cada biblioteca que se me ocurre devuelve una secuencia. Se podría utilizar IOUtils.toString()de Apache Commons IO para leer una InputStreamen una Stringen una llamada al método. P.ej:

URL url = new URL("http://www.example.com/");
URLConnection con = url.openConnection();
InputStream in = con.getInputStream();
String encoding = con.getContentEncoding();
encoding = encoding == null ? "UTF-8" : encoding;
String body = IOUtils.toString(in, encoding);
System.out.println(body);

Actualización: cambié el ejemplo anterior para usar la codificación de contenido de la respuesta si está disponible. De lo contrario, su valor predeterminado será UTF-8 como una mejor suposición, en lugar de usar el valor predeterminado del sistema local.

WhiteFang34
fuente
44
esto corromperá el texto en muchos casos ya que el método usa la codificación de texto predeterminada del sistema que varía según el sistema operativo y la configuración del usuario.
McDowell el
1
@McDowell: ¡Uy, gracias, vinculé el javadoc para el método con la codificación pero olvidé usarlo en el ejemplo. Agregué UTF-8 al ejemplo por ahora, aunque técnicamente debería usar el Content-Encodingencabezado de la respuesta si está disponible.
WhiteFang34
Gran uso de IOUtils. Buen enfoque práctico.
Spidey
8
En realidad, charset se especifica en contentType como "charset = ...", pero no en contentEncoding, que contiene algo como 'gzip'
Timur Yusupov
1
Esta función hace que el flujo de entrada a ser cerrada, hay una manera @ WhiteFang34 puedo imprimir mi respuesta y seguir utilizando la entidad http
Amit
275

Aquí hay dos ejemplos de mi proyecto de trabajo.

  1. Usando EntityUtilsyHttpEntity

    HttpResponse response = httpClient.execute(new HttpGet(URL));
    HttpEntity entity = response.getEntity();
    String responseString = EntityUtils.toString(entity, "UTF-8");
    System.out.println(responseString);
  2. Utilizando BasicResponseHandler

    HttpResponse response = httpClient.execute(new HttpGet(URL));
    String responseString = new BasicResponseHandler().handleResponse(response);
    System.out.println(responseString);
telaraña
fuente
10
El único problema que enfrenté con el método 1 es que el objeto de entidad se consume cuando lo haces response.getEntity()y ahora está disponible como responseString. Si intenta hacer una respuesta.getEntity () nuevamente, volverá IllegalStateException.
Tirtha
Funcionó en mi caso, obteniendo el cuerpo de la respuesta CloseableHttpClient.
Jaroslav Štreit
1
¿Qué es httpClient?
Andreas L.
1
@AndreasL. httpClient es de tipo HttpClient (org.apache.commons.httpclient package)
spideringweb
Es muy común obtener el contenido de la respuesta como una cadena o matriz de bytes o algo así. Sería bueno con una API directamente en la entidad para darle eso. Tener que buscar esto para encontrar esta clase de utilidad.
Claus Ibsen
52

Aquí hay un ejemplo de otro proyecto simple en el que estaba trabajando usando la biblioteca httpclient de Apache:

String response = new String();
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("j", request));
HttpEntity requestEntity = new UrlEncodedFormEntity(nameValuePairs);

HttpPost httpPost = new HttpPost(mURI);
httpPost.setEntity(requestEntity);
HttpResponse httpResponse = mHttpClient.execute(httpPost);
HttpEntity responseEntity = httpResponse.getEntity();
if(responseEntity!=null) {
    response = EntityUtils.toString(responseEntity);
}

solo use EntityUtils para tomar el cuerpo de la respuesta como una Cadena. muy simple.

queso claro de luna
fuente
28

Esto es relativamente simple en el caso específico, pero bastante complicado en el caso general.

HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet("http://stackoverflow.com/");
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
System.out.println(EntityUtils.getContentMimeType(entity));
System.out.println(EntityUtils.getContentCharSet(entity));

La respuesta depende del Content-Type encabezado de respuesta HTTP .

Este encabezado contiene información sobre la carga útil y puede definir la codificación de datos textuales. Incluso si asume tipos de texto , es posible que deba inspeccionar el contenido en sí mismo para determinar la codificación de caracteres correcta. Por ejemplo, consulte la especificación HTML 4 para obtener detalles sobre cómo hacer eso para ese formato en particular.

Una vez que se conoce la codificación, se puede usar un InputStreamReader para decodificar los datos.

Esta respuesta depende de que el servidor haga lo correcto: si desea manejar casos en los que los encabezados de respuesta no coinciden con el documento, o las declaraciones del documento no coinciden con la codificación utilizada, esa es otra fuente de información.

McDowell
fuente
¿Cómo obtenerlo como HashMap? Recibo respuesta como Json, ¿cómo leer eso?
user1735921
10

A continuación se muestra una forma sencilla de acceder a la respuesta como una cadena utilizando la biblioteca del cliente HTTP Apache.

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;

//... 

HttpGet get;
HttpClient httpClient;

// initialize variables above

ResponseHandler<String> responseHandler = new BasicResponseHandler();
String responseBody = httpClient.execute(get, responseHandler);
lkamal
fuente
9

¿Qué tal solo esto?

org.apache.commons.io.IOUtils.toString(new URL("http://www.someurl.com/"));
Eric Schlenz
fuente
9

La respuesta de McDowell es correcta. Sin embargo, si intentas otra sugerencia en algunas de las publicaciones anteriores.

HttpEntity responseEntity = httpResponse.getEntity();
if(responseEntity!=null) {
   response = EntityUtils.toString(responseEntity);
   S.O.P (response);
}

Entonces le dará ilegalStateException indicando que el contenido ya está consumido.

Akshay
fuente
3

Podemos usar el siguiente código también para obtener la respuesta HTML en Java

import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.HttpResponse;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import org.apache.log4j.Logger;

public static void main(String[] args) throws Exception {
    HttpClient client = new DefaultHttpClient();
    //  args[0] :-  http://hostname:8080/abc/xyz/CheckResponse
    HttpGet request1 = new HttpGet(args[0]);
    HttpResponse response1 = client.execute(request1);
    int code = response1.getStatusLine().getStatusCode();

    try (BufferedReader br = new BufferedReader(new InputStreamReader((response1.getEntity().getContent())));) {
        // Read in all of the post results into a String.
        String output = "";
        Boolean keepGoing = true;
        while (keepGoing) {
            String currentLine = br.readLine();

            if (currentLine == null) {
                keepGoing = false;
            } else {
                output += currentLine;
            }
        }

        System.out.println("Response-->" + output);
    } catch (Exception e) {
        System.out.println("Exception" + e);

    }
}
Subhasish Sahu
fuente
Esta es una muy buena respuesta, esto es lo que necesito mostrar, la respuesta después de publicar datos en el servidor. Bien hecho.
SlimenTN
0

Aquí hay una forma ligera de hacerlo:

String responseString = "";
for (int i = 0; i < response.getEntity().getContentLength(); i++) { 
    responseString +=
    Character.toString((char)response.getEntity().getContent().read()); 
}

Por supuesto, responseStringcon la respuesta del sitio web y la respuesta del tipo de respuesta HttpResponse, devuelta porHttpClient.execute(request)

Marko Zajc
fuente
0

El siguiente es el fragmento de código que muestra una mejor manera de manejar el cuerpo de la respuesta como una Cadena, ya sea una respuesta válida o una respuesta de error para la solicitud HTTP POST:

BufferedReader reader = null;
OutputStream os = null;
String payload = "";
try {
    URL url1 = new URL("YOUR_URL");
    HttpURLConnection postConnection = (HttpURLConnection) url1.openConnection();
    postConnection.setRequestMethod("POST");
    postConnection.setRequestProperty("Content-Type", "application/json");
    postConnection.setDoOutput(true);
    os = postConnection.getOutputStream();
    os.write(eventContext.getMessage().getPayloadAsString().getBytes());
    os.flush();

    String line;
    try{
        reader = new BufferedReader(new InputStreamReader(postConnection.getInputStream()));
    }
    catch(IOException e){
        if(reader == null)
            reader = new BufferedReader(new InputStreamReader(postConnection.getErrorStream()));
    }
    while ((line = reader.readLine()) != null)
        payload += line.toString();
}       
catch (Exception ex) {
            log.error("Post request Failed with message: " + ex.getMessage(), ex);
} finally {
    try {
        reader.close();
        os.close();
    } catch (IOException e) {
        log.error(e.getMessage(), e);
        return null;
    }
}
Krutik
fuente
0

Puede usar una biblioteca de fiestas en 3-d que envía una solicitud Http y maneja la respuesta. Uno de los productos conocidos sería HTTPClient de Apache commons: HttpClient javadoc , artefacto HttpClient Maven . Existe un HTTPClient mucho menos conocido pero mucho más simple (parte de una biblioteca de MgntUtils de código abierto escrita por mí): MgntUtils HttpClient javadoc , artefacto de MgntUtils maven , MgntUtils Github . Con cualquiera de esas bibliotecas, puede enviar su solicitud REST y recibir una respuesta independiente de Spring como parte de su lógica empresarial

Michael Gantman
fuente
0

Si está utilizando Jackson para deserializar el cuerpo de respuesta, una solución muy simple es usar en request.getResponseBodyAsStream()lugar derequest.getResponseBodyAsString()

Vic Seedoubleyew
fuente