# BufferedReader.readline kommt nicht zurück



## Oskar (14. Jan 2006)

Hallo

ich habe einen kleinen Http Proxy der nichts weiter machen soll als Anfragen auf Port 8080 entgegen zunehmen und dann an den Server weiterzuleiten. Und das ganze auch wieder auf dem Rückweg. 

Nun hängt die Ausführung in folgender Methode



```
private void parseURL() throws IOException {
    System.out.println("parseURL()");
    String currLine = null;
    System.out.println("Old Header: ");
    currLine = this.reader.readLine(); //der reader zeigt auf den InputStream vom Browser
    while ((currLine) != null) {
      System.out.println(currLine);
      if (currLine.indexOf("HTTP/1") != -1) {
        currLine = currLine.substring(0, currLine.indexOf("HTTP/1")-1);
        this.serverURL = new URL(currLine.substring(4));
      }
      this.header.append(currLine + "\n");
      currLine = this.reader.readLine(); // hier bleibt er hängen und kommt nicht zurück !
    }
    System.out.println("New Header: \n" + this.header);
  }
```

Das ganze macht folgendes: 
1. Lese die aktuelle Http-Requestheaderzeile aus dem Request des Browsers
2. Entferne Http1/1 aus dem Request und erstelle ein URL Objekt
3. Schreibe die (evtl. modifizierte Zeile in einen Stringbuffer (this.header))

Nun passiert beim Aufruf aber folgendes: 
Er geht in die Methode und durchläuft die while-Schleife ein paar mal und bleibt dann im reader.readline() stecken ohne eine Exception zu werfen. Er kommt einfach nicht zurück.
Noch dazu ist es sehr unterschiedlich wann das ganze auftritt, soll heißen mal klappt es bis zur 3. Zeile dann schafft er es wieder bis zur 5.

Hat jemand ne Idee wo der Hund begraben liegt?


----------



## uNiKoMpLeX (14. Jan 2006)

beim methodenaufruf xxx.readLine() wird der Inhalt einer Zeile als String ausgegeben. Zugleich setzt er den Zeiger auf die nächste Zeile... also wenn ich jez zB mach:
String zeile1,zeile2,zeile3;

zeile1=in.readLine();
zeile2=in.readLine();
zeile3=in.readLine();

In jeder Variable steht also die darauffolgende Zeile...

besser wäre es also, wenn du die readLine() Methode gleich in der Schleife einbaust...


```
private void parseURL() throws IOException
{
    System.out.println("parseURL()");
    String currLine = null;
    System.out.println("Old Header: ");
    String currLine=null;
    while ((currLine=this.header.readLine()) != null)
    {
        System.out.println(currLine);
        if (currLine.indexOf("HTTP/1") != -1)

       {
           currLine = currLine.substring(0, currLine.indexOf("HTTP/1")-1);
           this.serverURL = new URL(currLine.substring(4));
           this.header.append(currLine + "\n");
       }
    }
    System.out.println("New Header: \n" + this.header);
}
```


----------



## Oskar (14. Jan 2006)

Naja die Lösung wie du sie vorschlägst hatte ich zuvor.

Ich hab das dann extra mal aus der while-Bedingung rausgenommen um besser zu sehen wo er genau hängen bleibt.

Also daran liegt es definitiv nicht. Trotzdem danke.
Wenn der tatsächliche Grund gefunden ist wird das auch wieder in die while-Bedingung zurückwandern.

Cheers


----------



## uNiKoMpLeX (14. Jan 2006)

Ausserdem muss zuerst die Verbindung vom Client getrennt werden, ansonsten verbleibt die readLine() in einer "Warteposition". deshalb wird er auch hängen. Ich würd vorschlagen du liest lediglich die ersten paar Zeilen aus... also für dich ist eh nur die Request-Zeile interressant... müsste also die 1. Zeile sein. Probiers mal damit, dass du lediglich die  1. Zeile ausgibst ... benötigst dazu nicht einmal eine Schleife... einfach vom Stream die readLine() 1x ausführen, mal schaun obs dann besser klappt


----------



## Oskar (14. Jan 2006)

uNiKoMpLeX hat gesagt.:
			
		

> Ausserdem muss zuerst die Verbindung vom Client getrennt werden



Wie meinst du das? 

Ich dachte es wäre wie folge: in meinem BufferedReader werden die Daten vom Client gepuffert und ich lese die aus. Wenn das Ende des Puffers erreicht ist bekomm ich null zurück. Das sollte do erreicht sein wenn die letzte Headerzeile ausgelesen ist oder?
Wenn ich ein close() auf dem entsprechenden Stream mache dann schließt er die Verbindung. Hm da muss ich nochmal ran  :### 



			
				uNiKoMpLeX hat gesagt.:
			
		

> Ich würd vorschlagen du liest lediglich die ersten paar Zeilen aus... also für dich ist eh nur die Request-Zeile interressant... müsste also die 1. Zeile sein.



Ja das würde reichen. Es sollte aber doch auch möglich sein den kompletten Header zu lesen und weiter zu geben. Zumal ich nicht sicher bin, dass die URL IMMER bei JEDEM Browser in der ersten Zeile steht. (nein ich hab noch nicht in die Spec des W3C für Requestheader geschaut, ist nur so ne dumme Vermutung  :bahnhof: )


----------



## uNiKoMpLeX (14. Jan 2006)

Des ist schon richtig, dass er puffert. Aber solange die Verbindung nicht geschlossen ist, könnte es ja sein dass der Client noch eine weitere Nachricht schickt ... bzw der Client auf eine Antwort vom ProxyServer wartet... Also solange die Verbindung nicht geschlossen ist, könnte theoretisch noch was nachkommen vom Client... deshalb wird er dir solange nicht null zurückgeben, bis die Verbindung geschlossen worden ist.

Sicher kannst du die anderen Daten, die mitgeschickt werden, verwenden. Doch zuerst mal die 1. Zeile 'abarbeiten', danach kannst ja über eine Schleife die restlichen Zeilen auslesen ... Nachdem alle Header-Informationen gesendet wurden, also die readLine() "" ausgibt, die Verbindung trennen. Ich denk' so müsst es gehn =)

Über die W3C Spezifikation bin ich mir nicht im Klaren, aba ich denke schon dass jeder gängige Browser den Request in der 1. Zeile hat!


----------



## Murray (15. Jan 2006)

Ein HTTP-Request muss die Request-Line (z.B. "GET /index.html HTTP/1.0) immer in der ersten Zeile haben, danach folgen beliebig viele Header-Zeilen (ohne Leerzeilen dazwischen). Das Ende des Headers wird mit einer Leerzeile markiert, danach kommen optional Nutzdaten (nicht bei GET, wohl aber bei POST).

Wenn das Proxy nur GET unterstützen muss, dann reicht es wohl, bis zur ersten Leerzeile zu lesen. Im Falle von POST kann man im Header nach Content-Length suchen (ist für POST obligatorisch), dann weiss man, wieviele Bytes man noch lesen muss (dann nicht mit readLine, denn es ist m.E. nicht eindeutig spezifiziert, ob am Ende der Daten überhaupt ein Newline kommen muss).


----------



## Oskar (15. Jan 2006)

uNiKoMpLeX hat gesagt.:
			
		

> Nachdem alle Header-Informationen gesendet wurden, also die readLine() "" ausgibt





			
				Murray hat gesagt.:
			
		

> Das Ende des Headers wird mit einer Leerzeile markiert, danach kommen optional Nutzdaten (nicht bei GET, wohl aber bei POST).


Das ist doch mal ne Aussage    Ich hab mich schon gewundert woher ich wissen soll wann der Header zuende ist. Hab zwar im Debug den Eintrag "" schon mal gesehen, allerdings eher als Fehler denn als definierten Zustand verstanden. Na jut jetzt weiss ich wann der Header zuende ist.

Dann werde ich mich mal wieder an die Arbeit machen. Grandiose Antwort.  :applaus:


----------

