28. Oktober 2005

Protokoll bluehands Seminar 28.10.2005

Thema: Firefox XMLDoc braucht Content-Length

Auch wir machen natütlich AJAX. Wir machen das schon seit 4 Jahren, also schon lang bevor es einen berühmten Namen hatte. Klar, die Leserin hat nichts anderes von bluehands erwartet. AJAX heisst im Browser mit einem HTTP-Request im Hintergrund Daten vom Server zu erfragen, die dann in Javascript ausgewertet werden. Dazu verwende an das in moderne Browswr eingebaute XMLDocument Objekt. Das heisst natürlich verschieden bei IE und FF, aber der Code fängt typisherweise so an:

var oXmlDoc = null;
if (document.implementation)
oXmlDoc = document.implementation.createDocument("", "", null);
else
oXmlDoc = new ActiveXObject("Microsoft.XMLDOM");


Dann setzt man einen Callback:

oXmlDoc.onload = OnLoaded;

und lädt eine Datai vom Server, die typischerweise dynamisch erzeugt wird:

oXmlDoc.load(sUri);

Soweit so gut, aber...

Manchmal geht es nicht bei FF. Das heisst er macht den Request, liesst die Daten, erkennt sogat das character encoding aus dem XML header, aber die Tags kommen nicht im DOM an. Bei manchen Anwendungen geht es.

Es stellt sich nach viel probieren heraus, dass es genau dann nicht geht, wenn der Server kein Content-Length HTTP-Headerfield schickt. Bei Servern, die Content-Length setzen, geht es. Das ist [seltsamwitziginteressant], weil es
1. dem IE nichts ausmacht
2. die HTTP-Spec sagt, dass Content-Length nicht notwendig ist, wenn die TCP Verbindung beednet. Dann ist die Content-Length nämlich genau die Daten, die bis zum Ender der verbindung kamen
3. Selbst wenn es dem FF unmöglich wäre die Content-Length herauszufinden,der XML Parser im FF aus dem Schliessen des auessersten XML-Tags erkennen könnte, dass das XML fertig ist. Danach darf sowieso nichts mehr kommen
4. PHP normalerweise keine Content-Length schickt, weil die noch nicht bekannt ist, wenn nach dem HTTP Header die ersten Daten geschickt werden und man.

Ergebnis: AJAX/PHP/Firefox geht nicht, denn das findet der normale PHP Programmierer nie heraus. Aber wenn er googelt und das hier findet sei ihm gesagt: Man muss alle Daten in einer Variable speichern und die Content-Length setzen mit:

header("Content-Length: " . strlen($data);

oder PHP output buffering einschalten, dann geht es möglicherweise auch (nicht getestet). Das hätte den Vorteil, dass der Code nicht umgeschrieben werden muss, um überall einzufügen:

$data .= DasWasVorherImEchoStand;

Das ganze hängt vermutlich nur an einem Detail. Ich nehme an, dass der TCPStream im FF beim XML Parser das "final" flag nicht setzt wenn die TCP Verbindung beendet und so dem Parser nicht signalisiert, dass die Daten fertig sind. Wahrscheinlich parst der Parser das XML korrekt (darauf deutet das character encoding hin), aber das DOM wird nicht fuer den externen Zugriff bereitgestellt, weil "final" fehlt.

Fazit: Noch ein Indiz, dass AJAX noch nicht erwachsen ist. Nicht das einzige. Aber dank des Überhypes darf man hoffen, dass sich Entwicklungsanstrengungen darauf konzentrieren und es das bald wird.

_happy_coding()

Keine Kommentare: