Perl (Socket): auf komplette HTTP-Request-Daten zugreifen?

  • Hallihallo,


    Zu Demo- und Testzwecken habe ich mal einen kleinen (blockenden) Webserver in Perl geschrieben. Ich verwende das Modul IO::Socket::INET, um nicht ganz von vorne anzufangen. Wenn sich der Client verbindet, bekomme ich ja mit accept() die Repräsentation des Client-Sockets. Den kann ich auf weitere Eigenschaften abfragen und Nutzen, um per print die Response zu schreiben.
    Ich habe eine kleine HTML-Seite geschrieben, die per Formular einen Request auf den Server macht. Wenn ich zu Testzwecken den reinkommenden (POST)-Request ausgebe, bekomme ich immer nur


    Code
    POST / HTTP/1.1


    zu sehen. Soweit so gut, aber wo bleiben die weiteren Daten, die der Browser mitschickt? Also Agent, Content-length, Content-type etc. und die Parameter aus dem HTML-Formular? Ich weis nicht, wie ich den Socket-Descriptor ansprechen muss, um die gesamte HTTP-Nachricht zu sehen. Leider finde ich auch in den Perl-Dokus keine genauen Beschreibungen der Attribute des Socket-Descriptors - habe mir das Meiste mühsam aus Beispielen ergoogelt ;)
    Perldoc ging nicht weiter ins Detail und verweist auf ein Beispielprogramm, welches ich nicht finde.


    Kann mir jemand einen Tipp geben (konkretes Beispiel oder Link auf das RTFM ;) )? Hier der Ausschnitt aus dem Programm:


    ...

    Code
    while (my $conn = $socket->accept()) {
    		my $request = <$conn>;
    		chomp($request);
    		print "[INFO]\t Request received from host " . $conn->peerhost .
    			" on port " . $conn->peerport . "\n";
    		print "[INFO]\t Request: $request\n";
    		#&response_simple($conn);
    		close($conn);
    	}


    ...


    Ausgabe in der Konsole (STDOUT):


    Code
    [INFO]	 Created server socket on port 6675
    [INFO]	 Request received from host 127.0.0.1 on port 37338
    [INFO]	 Request: POST / HTTP/1.1
    IO::Socket::INET=GLOB(0x817d20c)


    DANKE+Gruß,
    Timo

    yaVDR 0.4-pre1 on ASUS 1015PN -> Big Screen and XBMC remote on Android.

  • Moin!


    Ich kenn mich zwar mit Perl nicht wirklich aus, aber das klingt nach dem ganz simplen Problem, daß die Funktionen, die Du da benutzt, vom Request nur bis zum ersten Return lesen und den Rest wegschmeißen. Alternativ kanns auch sein, daß sie nur nicht weiter lesen.


    Hab gerade mal ein wenig zu Perl gelesen und wie es aussieht, werden da Sockets auch als ganz normale Files behandelt. Also lies mit einer Funktion so lange von der Socket, bis nichts mehr kommt, und Du hast Deinen ganzen Request beisammen.
    Falls Syntax vergleichbar mit C ist, könnte es aber auch so aussehen:


    Code
    $request = "";
    
    
    while( $socket -> recv( $daten, 4096))
    {
    	$request = $request + $daten;
    	// oder wie auch immer das in Perl aussehen mag :)
    }

    Das funktioniert allerdings nur, wenn die Socket nicht blockiert. Theoretisch kann man der Funktion "recv()" auch noch "MSG_PEEK" übergeben um zu schauen, ob was zu lesen da ist und man nicht ins Blocken kommt. Wie das in Perl funktioniert, kann ich Dir aber leider nicht sagen.


    Hoffe, das hilft Dir trotzdem irgendwie.


    --
    Chris

    Software OS: Debian Lenny, Kernel: 2.6.24, VDR: 1.7.0 +ext60 +h.264
    Hardware CPU: Sempron64 1.8GHz (C&Q), MB: Foxconn 760GXK8MC, RAM: 512MB, HDD: ST 160GB, DVB: TT C2300 / KNC1v1, DVD: Pioneer DVR-106D, LCD: 4x20 (blau), IR: LIRC

  • Hallo Chris,


    erstmal sorry für meine späte Antwort, habe erst heute die Muße gefunden, mich wieder um diese Sache zu kümmern.


    Kurzum: Du hattest Recht! Mit der Zeile


    Code
    my $request = <$conn>;


    hole ich wirklich nur die erste Zeile in einen Skalar (String quasi) und nicht in einen Array. Ich habe also direkt eine foreach-Schleife auf den Socket-Descriptor gemacht und siehe da, in der STDOUT sehe ich die vermissten Daten:


    Code
    while (my $conn = $socket->accept()) {
    		while (my $line = <$conn>) {
    			print $line;
    		}
    		close($conn);
    	}


    Ausgabe:


    Code
    GET / HTTP/1.1
    Host: localhost:6675
    User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.6) Gecko/20061201 Firefox/2.0.0.6 (Ubuntu-feisty)
    Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 300
    Connection: keep-alive


    Ich wollte nicht weiter in die Socket-Programmierung rein (daher hier kein Multithreading-Server etc.), da es mir nur um eine Demo ging. Ich war vor 8 jahren mal wirklich tief in der Socket-Enwicklung drin (allerdings mit C) und auch Perl mache ich schon seit 5 Jahren nicht mehr, daher vergebe man mir ;)


    VIELEN DANK!


    Gruß,
    Timo

    yaVDR 0.4-pre1 on ASUS 1015PN -> Big Screen and XBMC remote on Android.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!