Client HTTP in java

java
Un semplice client HTTP scritto in java che consente di visualizzare i messaggi a livello HTTP sia in fase di invio che le risposte del server.
E' possibile settare il metodo della richiesta (GET o POST), impostare manualmente gli headers e scrivere un eventuale body da mandare al server (utile usando il metodo POST).
Il file dispone di un interfaccia grafica ma è possibile utilizzare solamente il file HTTPClient in un progetto esterno.

Mi limiterò a commentare la classe HTTPClient, l'interfaccia grafica è velocemente realizzabile con un qualsiasi IDE come Netbeans.
Per aver maggior flessibilità e poter analizzare i messaggi a livello HTTP non utilizzerò classi come UrlConnection o HTTPUrlConnection ma implementerò un client che lavora a livello di stream su socket.

Il metodo principale è send, iniziando dalla parte di networking:
// NETWORK STUFFS
Socket socket = new Socket(host,port);
PrintWriter out = new PrintWriter(socket.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Creo il socket e i canali per comunicare con il server.

Prima di mandare qualsiasi messaggio al server, devo costruire la richiesta partendo dal metodo seguito dal path della risorsa richiesta e dal protocollo:
// crea la request
request += method + " /" + " HTTP/1.0\r\n";
NOTA SULLA STRINGA NULLA IN HTTP/1.0:
Impostando HTTP/1.1, il server non chiude il flusso dati del socket, lasciando il client in attesa del fine flusso che non arriva, per questo imposto HTTP/1.0 così che il server a fine pagina chiuda il socket.

Ora aggiungiamo gli HTTP headers presenti in una hashtable contenenti il nome dell' header e il valore. Mi assicuro anche di aggiungere l' header "Content-Length" indispensabile nel caso di metodo POST:
// aggiungi headers
Enumeration keys = headers.keys(); 
while(keys.hasMoreElements()){ 
    String key = (String) keys.nextElement(); 
    String value = (String) headers.get(key);
    request += key + ": " + value + "\r\n"; 
} // controllo content-length, indispensabile per il POST 
if(headers.get("Content-Length:") == null ) 
    request += "Content-Length: " + body.getBytes().length + "\r\n";

Concludo la scrittura degli header lasciando una riga vuota e aggiungo il body della richiesta:
// linea di fine headers 
request += "\r\n"; 
// aggiungo il body 
request += body;

A questo punto posso spedire la richiesta sul socket:
// invio 
System.out.println(request+"\n"); 
out.print(request); 
out.flush();

Leggiamo ora la risposta del server:
String s;
while ( (s = in.readLine()) != null ){
    response += s + "\n";
    System.out.println(s);
}

Infine non resta che chiudere gli stream usati e i socket aperti.
in.close(); 
out.close(); 
socket.close(); 

Ecco tutto il codice completo di HTTPClient.java:

package httpclient;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Enumeration;
import java.util.Hashtable;

/**
*
* @author Giacomo Petronio
*/
public class HTTPClient {

    private String host = "";
    private int port = 80;
    private String path = "";
    private String method = "GET";
    private String body = "";
    private Hashtable headers = new Hashtable();


    /** Creates a new instance of HTTPClient */
    public HTTPClient() {
    }

    public void setHost(String host, int port, String path) {
        this.host = host;
    }

    public void setMethod(String method) {
        this.method = method;
    }

    public void setBody(String body) {

        this.body = body;
    }

    public void addRequestHeader(String key, String value){
        headers.put(key, value);
    }

    /**
    * returns 2 strings
    * String[0] is the request
    * String[1] is the response
    */
    public String[] send() throws IOException{

        String response = "";
        String request = "";

        // NETWORK STUFFS
        Socket socket = new Socket(host,port);
        PrintWriter out = new PrintWriter(socket.getOutputStream());
        BufferedReader in =  new BufferedReader(new InputStreamReader(socket.getInputStream()));


        // crea la request
        request += method + " /" + " HTTP/1.0\r\n";

        // aggiungi headers
        Enumeration keys = headers.keys();
        while(keys.hasMoreElements()){
            String key = (String) keys.nextElement();
            String value = (String) headers.get(key);
            request += key + ": " + value + "\r\n";
        }
        // controllo content-length, indispensabile per il POST
        if(headers.get("Content-Length:") == null )
            request += "Content-Length: " + body.getBytes().length + "\r\n";

        // linea di fine headers
        request += "\r\n";

        // aggiungo il body
        request += body;

        // invio

        System.out.println(request+"\n");
        out.print(request);
        out.flush();


        String s;
        while ( (s = in.readLine()) != null ){
            response += s + "\n";
            System.out.println(s);
        }

        in.close();
        out.close();
        socket.close();

        String[] result = new String[2];
        result[0] = request;
        result[1] = response;

        return result;
    }
}


In allegato trovate uno zip con tutti i sorgenti e il client grafico
AttachmentSize
httpclient.zip70.7 KB

Comments

http get response

it is very interesting... but...
if i try to obtain something from the get
the cycle while (....!=-1) {} does not stop until the time out.
it seems that doesn't appear the EndOfFile in the response..
Why?????? I don't understand.. :-(