2010-06-13 10 views
5

provo a scrivere l'app server più semplice possibile in Java, visualizzando il modulo html con input textarea, che dopo l'invio mi dà la possibilità di analizzare xml digitato in quella textarea. Per ora mi costruisco semplice server basato ServerSocket così:Lettura dei dati POST dal modulo html inviato ai server

import java.io.BufferedReader; 
import java.io.InputStreamReader; 
import java.io.PrintWriter; 
import java.net.ServerSocket; 
import java.net.Socket; 

public class WebServer { 

    protected void start() { 
    ServerSocket s; 
    String gets = ""; 
    System.out.println("Start on port 80"); 
    try { 
     // create the main server socket 
     s = new ServerSocket(80); 
    } catch (Exception e) { 
     System.out.println("Error: " + e); 
     return; 
    } 

    System.out.println("Waiting for connection"); 
    for (;;) { 
     try { 
     // wait for a connection 
     Socket remote = s.accept(); 
     // remote is now the connected socket 
     System.out.println("Connection, sending data."); 
     BufferedReader in = new BufferedReader(new InputStreamReader(
      remote.getInputStream())); 
     PrintWriter out = new PrintWriter(remote.getOutputStream()); 

     String str = "."; 

     while (!str.equals("")) { 
      str = in.readLine(); 
      if (str.contains("GET")){ 
      gets = str; 
      break; 
      } 
     } 

     out.println("HTTP/1.0 200 OK"); 
     out.println("Content-Type: text/html"); 
     out.println(""); 
     // Send the HTML page 
     String method = "get"; 
     out.print("<html><form method="+method+">"); 
     out.print("<textarea name=we></textarea></br>"); 
     out.print("<input type=text name=a><input type=submit></form></html>"); 
     out.println(gets); 
     out.flush(); 

     remote.close(); 
     } catch (Exception e) { 
     System.out.println("Error: " + e); 
     } 
    } 
    } 

    public static void main(String args[]) { 
    WebServer ws = new WebServer(); 
    ws.start(); 
    } 
} 

Dopo modulo (textarea con XML e un ingresso testo aggiuntivo) è presentata in 'ottiene' di tipo stringa variabile ho urlencoded valori delle variabili my (visualizzato anche sullo schermo, sembra che:

gets = GET /?we=%3Cnetwork+ip_addr%3D%2210.0.0.0%2F8%22+save_ip%3D%22true%22%3E%0D%0A%3Csubnet+interf_used%3D%22200%22+name%3D%22lan1%22+%2F%3E%0D%0A%3Csubnet+interf_used%3D%22254%22+name%3D%22lan2%22+%2F%3E%0D%0A%3C%2Fnetwork%3E&a=fooBar HTTP/1.1 

Cosa posso fare per cambiare arrivare a metodo POST (se ho semplicemente cambiare in forma e poi messo "se (str.contains (" POST ")) { "mi dà una stringa come

gets = POST/HTTP/1.1 

senza variabili. E dopo, come posso usare xml dal mio campo textarea (chiamato 'noi')?

+0

Ciao qqryq. Ho lo stesso codice. Hai capito come leggere il corpo POST?Ho provato a eseguire il secondo mentre andavo in ciclo, come dice cygri, ma i metodi inputStream.read o bufferedReader.readline bloccano la mia discussione. Come leggi il corpo del POST? – Alexmelyon

+1

Oh, ho capito! Ho bisogno di leggere l'intestazione "Content-Length:" e fare for-cycle fino a questa lunghezza. – Alexmelyon

risposta

3

I dati POST non sono nella prima riga. Stampa tutte le linee e vedrai. In realtà è immediatamente dopo una riga vuota.

+3

ok, ma come posso eseguire il pront tutto se ho l'istruzione while (! Str.equals ("")) {'? Ignora la prima riga vuota e fermati su un'altra? – qqryq

5

Una tipica richiesta HTTP POST assomiglia a questo:

POST/HTTP/1.1 
Host: www.example.com 
Accept: text/html,*/*;q=0.5 
User-Agent: BrowserName/1.0 
Referer: http://www.example.com/ 
Content-type: application/x-www-form-urlencoded; charset=utf-8 

foo=1&bar=2 

La prima riga contiene il metodo (tipicamente GET o POST, ma c'è di più, come la testa, PUT, DELETE), l'URI della richiesta, e la versione del protocollo. Poi ci sono un certo numero di intestazioni delle richieste, che potrebbero non essere così importanti per un semplice server. Se il metodo è uno che accetta un corpo di richiesta (POST e PUT), quindi dopo le intestazioni c'è una riga vuota seguita dal corpo della richiesta. Nel caso di un POST da un modulo HTML, il corpo sarà composto da coppie key=value per tutti gli elementi del modulo, uniti da &. I valori saranno% -encoded.

Hai solo bisogno di prendersi cura di analizzare correttamente l'intera richiesta.

È necessario tenere presente che le terminazioni di riga in HTTP devono essere in stile Windows (\r\n). Il metodo readline() potrebbe interpretare questo come due interruzioni di riga, quindi potrebbe sembrare che ci sia una linea vuota tra ciascuna delle linee reali.

+3

ok, ma come arrivare a quei dati quando il mio mentre si ferma sulla prima linea vuota? – qqryq

+0

Riscrivi il tuo ciclo while in modo che non si fermi sulla prima riga. Hai bisogno di aiuto con quello? – cygri

8

Questa è la mia implementazione per il corpo lettura POST:

try { 
    Socket socket = params[0]; 
    BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
    BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); 
    // read request 
    String line; 
    line = in.readLine(); 
    StringBuilder raw = new StringBuilder(); 
    raw.append("" + line); 
    boolean isPost = line.startsWith("POST"); 
    int contentLength = 0; 
    while (!(line = in.readLine()).equals("")) { 
     raw.append('\n' + line); 
     if (isPost) { 
      final String contentHeader = "Content-Length: "; 
      if (line.startsWith(contentHeader)) { 
       contentLength = Integer.parseInt(line.substring(contentHeader.length())); 
      } 
     } 
    } 
    StringBuilder body = new StringBuilder(); 
    if (isPost) { 
     int c = 0; 
     for (int i = 0; i < contentLength; i++) { 
      c = in.read(); 
      body.append((char) c); 
      Log.d("JCD", "POST: " + ((char) c) + " " + c); 
     } 
    } 
    raw.append(body.toString()); 
    publishProgress(raw.toString()); 
    // send response 
    out.write("HTTP/1.1 200 OK\r\n"); 
    out.write("Content-Type: text/html\r\n"); 
    out.write("\r\n"); 
    out.write(new Date().toString()); 
    if (isPost) { 
     out.write("<br><u>" + body.toString() + "</u>"); 
    } else { 
     out.write("<form method='POST'>"); 
     out.write("<input name='name' type='text'/>"); 
     out.write("<input type='submit'/>"); 
     out.write("</form>"); 
    } 
    // 
    // do not in.close(); 
    out.flush(); 
    out.close(); 
    socket.close(); 
    // 
} catch (Exception e) { 
    e.printStackTrace(); 
    StringWriter sw = new StringWriter(); 
    e.printStackTrace(new PrintWriter(sw)); 
    publishProgress('\n' + sw.toString()); 
} 

lo faccio per Android e publishProgres nel mio caso significa:

protected void onProgressUpdate(String... values) { 
     super.onProgressUpdate(values); 
     instance.logTextView.append(values[0]); 
    } 
+2

Fondamentalmente, la prima lettura dovrebbe raccogliere tutte le linee di intestazione. Dopo che l'intestazione Content-Length dovrebbe essere usata per sapere in anticipo quanti caratteri dovrebbero essere letti e poi semplicemente andare avanti per un'ulteriore elaborazione – prash

4

Poiché non esiste una riga vuota dopo le intestazioni, qui è il mio modo relativamente semplice di ottenere i dati di payload post, dopo aver letto le informazioni dell'intestazione utilizzando il metodo readLine() di BufferedReader.

//socket is an instance of Socket 
InputStream is = socket.getInputStream(); 
InputStreamReader isReader = new InputStreamReader(is); 
BufferedReader br = new BufferedReader(isReader); 

//code to read and print headers 
String headerLine = null; 
    while((headerLine = br.readLine()).length() != 0){ 
     System.out.println(headerLine); 
    } 

//code to read the post payload data 
StringBuilder payload = new StringBuilder(); 
     while(br.ready()){ 
      payload.append((char) br.read()); 
      } 
System.out.println("Payload data is: "+payload.toString()) 
1

Da this -

abbiamo bisogno di leggere prima le intestazioni e poi leggere di nuovo dalla stessa BufferedReader utilizzando effettiva lunghezza contenuti forniti nella sezione di intestazione: -

BufferedReader in = new BufferedReader(new InputStreamReader(is)); 
String line; 
line = in.readLine(); 
while ((line = in.readLine()) != null && (line.length() != 0)) { 
    System.out.println("HTTP-HEADER: " + line); 
    if (line.indexOf("Content-Length:") > -1) { 
    postDataI = new Integer(
     line.substring(
      line.indexOf("Content-Length:") + 16, 
      line.length())).intValue(); 
    } 
} 
String postData = ""; 
// read the post data 
if (postDataI > 0) { 
    char[] charArray = new char[postDataI]; 
    in.read(charArray, 0, postDataI); 
    postData = new String(charArray); 
} 

HTH

Problemi correlati