Philipp Hasenfratz: Sockets... HTTP... Proxi... ARGHHH!

Halihallo Forumer

Mein Thread ist leider bereits ins Archiv gerutscht und ist dort noch nicht auffindbar (aus bekannten Gründen), also erstmal Entschuldigung, dass ich nach so kurzer Zeit schon wieder damit anfange, aber das Problem geht mir gewaltig auf die Nerven und ich will schnellstmöglich eine Lösung finden, sonst werd ich noch wahnsinnig ;-)

Es geht um einen HTTP oder Proxi-Dienst. Ein Prog hängt sich an einen Port (80, 8080) und soll die Requests bearbeiten. Funktioniert alles toll. Nur...

while ( my $client = $sock->accept ) {
   xxx
}

bei xxx hab ich so ziemlich alles ausprobiert, was ich kenne, um den ganzen HTTP-Request einzulesen... @arr = <$client>; $t = <$client>, while ( <$client> ), ... alles, alles, sogar mit $client->eof... Ich denke, dass es noch eine möglichkeit über recv oder sysread gäbe, aber das muss doch schon einfacher gehen (d. h. beides ist gleich einfach, aber ersteres "perliger"), oder?
Irgendwie erkennt mein Perl nie, wann schluss ist. Das Programm bleibt immer stehen und versuche aus dem Socket zu lesen, obwohl der Client gar nix mehr gesendet hat... Könnte es sein, dass dies mit dem Linedeliminator zu tun hat? (benutze Win => CRLF)...

Was zum h*** ist hier los??? - Was begreife ich hier nicht? - Und warum funktioniert es nur bei HTTP so; andere Socketdiskussionen hab ich ohne Probleme machen können (gar bidirektional mit mehreren Blöcken)? - Aber diese HTTP-Requests (Header _und_ Body) kann ich einfach nicht einlesen... Natürlich könnte ich last if ($line=~/^$crlf$/); machen, aber dann schneide ich mir den Content (eg. POST Formulardaten) des Requests weg und den will ich auch.

Viele Grüsse

Philpp
   --> der auf das Ende seiner Qualen hofft ;-)

  1. Hallo,

    Natürlich könnte ich last if ($line=~/^$crlf$/); machen, aber dann schneide ich mir den Content (eg. POST Formulardaten) des Requests weg und den will ich auch.

    die entspr. RFC's sehen auch nichts anderes vor. Dein Request endet mit dem Header-End. Wenn es noch Daten gibt, dann gibt es auch ein Content-Length. Du mußt bei HTTP den Header parsen, ob Du willst oder nicht. Wenn ich mich nicht irre, so schickst Du bei HTTP/1.0 den Header an den Server und dieser antwortet dann mit dem Status 100, wenn er den Rest haben will.

    micha

    1. Halihallo micha

      Natürlich könnte ich last if ($line=~/^$crlf$/); machen, aber dann schneide ich mir den Content (eg. POST Formulardaten) des Requests weg und den will ich auch.

      die entspr. RFC's sehen auch nichts anderes vor. Dein Request endet mit dem Header-End. Wenn es noch Daten gibt, dann gibt es auch ein Content-Length. Du mußt bei HTTP den Header parsen, ob Du willst oder nicht. Wenn ich mich nicht irre, so schickst Du bei HTTP/1.0 den Header an den Server und dieser antwortet dann mit dem Status 100, wenn er den Rest haben will.

      OK. Danke für den Tipp bezüglich Content-Length; ich dachte, dass dies auch anders funktioniert. Aber nun denn...
      Was hier Status 100??? - Der Content wird einfach mit \015\012\015\012 an den Header gehängt.

      Viele Grüsse

      Philipp

      1. Hallo,

        Was hier Status 100???

        100 Continue, wobei ich jetzt wirklich nicht weiß, ob das nun bei HTTP/1.0 oder 1.1 reinkommt und ob es wichtig ist.

        • Der Content wird einfach mit \015\012\015\012 an den Header gehängt.

        Der Header wird damit abgeschlossen. Es muß keinen Body geben aber wenn, dann komm er gleich danach. Weiterhin reicht es schon aus auf \012 zu prüfen:

        (19.3 Tolerant Applications)

        The line terminator for message-header fields is the sequence CRLF.
           However, we recommend that applications, when parsing such headers,
           recognize a single LF as a line terminator and ignore the leading CR.
        <

        micha

  2. Hallo Philipp,

    while ( my $client = $sock->accept ) {
       xxx
    }

    bei xxx hab ich so ziemlich alles ausprobiert, was ich kenne, um den ganzen
    HTTP-Request einzulesen... @arr = <$client>; $t = <$client>,
    while ( <$client> ), ... alles, alles, sogar mit $client->eof...

    Das funktioniert so nicht :)
    Du musst das anders machen. Du musst den Header zeilenweise einlesen und
    verarbeiten, z. B. so:

    my %headers;
    $headers{_firstline} = <$sock>;

    while(<$sock>) {
      last if m/^\s*$/;
      if(m/^(\S+): (.*)$/) {
        $headers{$1} = $2;
      }
    }

    my $data;
    if($headers{_firstline} =~ /^POST/) {
      read $sock, $data, $headers{Content-Length};
    }

    my $ssock = new IO::Socket::INET(
      PeerPort => 80,
      PeerAddr => adresse
    );

    delete $headers{Connection} if exists $headers{Connection};

    print delete $headers{_firstline},"\015\012";

    print $ssock $_,": ",$headers{$_},"\015\012" foreach keys %headers;
    print $ssock "Connection: close\015\012\015\012";

    Und dann die Daten vom Server abholen und an den Client schicken. Hier kannst
    du recht einfach mit @lines = <$ssock> arbeiten, weil du dem Server ja gesagt
    hast, 'du, ich will, dass die Verbindung geschlossen wird!'.

    Beim einlesen vom Client funktioniert das deshalb nicht, weil der Socket ja
    die ganze Zeit offen bleibt. Der <>-Operator blockt dann, wenn der Client
    nichts mehr schickt, weil er auf weitere Daten wartet.

    Gruesse,
     CK

    1. Halihallo Christian

      Das funktioniert so nicht :)

      Das musste ich schmerzlich auch feststellen :-)

      Du musst das anders machen.

      und das die logische Folge ;)

      Du musst den Header zeilenweise einlesen und
      verarbeiten, z. B. so:

      my %headers;
      $headers{_firstline} = <$sock>;

      while(<$sock>) {
        last if m/^\s*$/;
        if(m/^(\S+): (.*)$/) {
          $headers{$1} = $2;
        }
      }

      soweit war ich schon mal...

      my $data;
      if($headers{_firstline} =~ /^POST/) {
        read $sock, $data, $headers{Content-Length};
      }

      OK. Also, dann muss ich das so machen, wie ihr (micha hat das ja ebenfalls genannt).

      Beim einlesen vom Client funktioniert das deshalb nicht, weil der Socket ja
      die ganze Zeit offen bleibt. Der <>-Operator blockt dann, wenn der Client
      nichts mehr schickt, weil er auf weitere Daten wartet.

      Das verwirrt mich jetzt etwas. Bei anderen Scripts hat das bei mir bestens funktioniert, oder irre ich mich? (also: ist es normalerweise nicht so, dass Perl merkt, wann keine Daten mehr gesendet wurden? - Und ich spreche von Sockets, die nicht geschlossen wurden)...

      Also sowas:

      Server:

      print $client 'hello world'
      my @answer = <$sock>;
      print $client join("\n", @answer);

      Client:

      @server = <$sock>;
      print $sock 'Re: hello world';
      print 'I wrote: '.join('', <$sock>);

      ich glaube, dass ich sowas in der Art schon realisieren konnte, also mit offenen Sockets dennoch den <>-Operator verwenden.

      Besten dank euch beiden. Hat mir sehr geholfen

      Viele Grüsse

      Philipp

      1. Hallo Philipp,

        my $data;
        if($headers{_firstline} =~ /^POST/) {
          read $sock, $data, $headers{Content-Length};
        }

        OK. Also, dann muss ich das so machen, wie ihr (micha hat
        das ja ebenfalls genannt).

        Micha hat etwas anderes gesagt, aber gut.

        Das verwirrt mich jetzt etwas. Bei anderen Scripts hat das
        bei mir bestens funktioniert, oder irre ich mich? (also:
        ist es normalerweise nicht so, dass Perl merkt, wann keine
        Daten mehr gesendet wurden? - Und ich spreche von Sockets,
        die nicht geschlossen wurden)...

        Nein. Definitiv nicht -- wie soll Perl das auch merken? Die
        TCP-Verbindung muss ja nicht zwangslaeufig auf demselben
        Rechner sein, sondern kann einmal um die ganze Welt gehen
        oder in ein Netzwerk, wo gerade heftigst Probleme sind.

        Gruesse,
         CK

        1. Halihallo Christian

          Das verwirrt mich jetzt etwas. Bei anderen Scripts hat das
          bei mir bestens funktioniert, oder irre ich mich? (also:
          ist es normalerweise nicht so, dass Perl merkt, wann keine
          Daten mehr gesendet wurden? - Und ich spreche von Sockets,
          die nicht geschlossen wurden)...

          Nein. Definitiv nicht -- wie soll Perl das auch merken? Die
          TCP-Verbindung muss ja nicht zwangslaeufig auf demselben
          Rechner sein, sondern kann einmal um die ganze Welt gehen
          oder in ein Netzwerk, wo gerade heftigst Probleme sind.

          Ja. Da hast'e recht. Scheint, als ob ich da ein kleineres Verständnisproblem hatte. Ich hätte mir gut vorstellen können, dass über das Socket eine Art EOF-Command gesendet wird, sodass das API weiss, wann Schluss ist. Aber danke für die "Auffrischung".

          Viele Grüsse und Danke an dich/euch

          Philipp

  3. Halihallo Forumer

    so. Jetzt hatte ich endlich Zeit das ganze auch auszuprobieren und es funktioniert perfekt, naja, fast, sonst müsste ich hier nicht schreiben ;)... Danke nochmals für deine Beispiele, Christian; ich hoffe du erlaubst, dass ich diese gleich verwendet habe (ging einfach schneller, als alles nochmal selber zu programmieren).

    Alles, bis auf google.ch funktioniert. GET/POST Daten, Cookies, ... einfach alles, bis auf diesen Google... Wenn ich nämlich diese Seite lade, dann geht der Browser in eine Endlosschlaufe und lädt die Page immer neu. Ich glaube, dass es an dem Status 302 hängt bzw. an Proxy-Connection: Keep-Alive??? - Mal schaun, was ihr dazu meint:

    Viele Grüsse

    Philipp

    PS: Ganz unten noch der momentane Code...

    Request on http://www.google.ch/
       Request-Header:
          Proxy-Connection: Keep-Alive
          Host: www.google.ch
          Cookie: PREF=ID=2ee932854a6b966a:LD=de:TM=1029179593:LM=1029179593:S=yXSkNolyuIg
          User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
          Accept-Language: de
          Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
       Request-Content: (Length: )
       Request answer from http://www.google.ch/
          HTTP/1.0 302 Found
          Content-Length: 151
          Connection: Close
          Server: GWS/2.0
          Content-Type: text/html
          Date: Sat, 17 Aug 2002 12:39:38 GMT
          Location: http://www.google.ch/
          Set-Cookie: PREF=ID=1a0d0e7e7e467b7d:TM=1029587978:LM=1029587978:S=oKKDkzioSrA; domain=.google.com; path=/; expires=Sun, 17-Jan-2038 19:14:07 GMT

    ----

    proxi.pl

    #!/usr/bin/perl

    use IO::Socket::INET;
    use LWP::Simple;

    my $socket = new IO::Socket::INET( LocalAddr => 'localhost',
         LocalPort => 8080,
         Listen  => 5,
         Reuse  => 1,
         Proto  => 'tcp' )
      or die 'cannot initialise listener';

    my %hosts = ( 'http://www.thedorcx.ch/' => 'http://127.0.0.1/www.thedorcx.ch/',
      'http://www.kodex.ch/'  => 'http://127.0.0.1/www.kodex.ch/',
      'http://www.test.ch/'  => 'http://127.0.0.1/www.test.ch/' );

    einige Domain-Referer, genau das, wozu ich den Proxi verwende...

    also die Ursache, warum ich erst angefangen habe zu programmieren.

    open( LOG, '>>./log.txt' );

    while ( my $sock = $socket->accept ) {

    my %headers; my %_headers;
       $headers{_firstline} = <$sock>;

    while(<$sock>) {
         last if m/^\s*$/;
         if(m/^(\S+): (.*)$/) {
           my $n = $1; my $v = $2;
           $n =~ s/\015|\012//g;
           $v =~ s/\015|\012//g;
           $headers{$n} = $v;
           $_headers{lc $n} = $v;
         }
       }

    my $data='';
       if($headers{_firstline} =~ /^POST/) {
         read $sock, $data, $_headers{'content-length'};
       }

    $request = $headers{_firstline};
       $request =~ /^(.*?) (.*) HTTP/(.*?)$/i;
       my $url  = $2;
       my $method = $1;
       my $vers = $3;

    while ( my ($host, $vd_refer) = each %hosts ) {
          $url =~ s/$host/$vd_refer/ig;
       }
       my $server = (split ///, $url)[2];
       delete $headers{_firstline};

    print LOG 'Request on '.$url."\n";
       print 'Request on '.substr($url,0,64)."...\n";
       print LOG '   Request-Header:'."\n";
       while ( my ($n,$v) = each %headers ) {
          print LOG ' ' x 6 . $n . ': ' . $v . "\n";
       }
       print LOG '   Request-Content: (Length: '.$_headers{'content-length'}.')'."\n";
       if (length $data) {
          print LOG $data . "\n";
       }

    my $ssock = new IO::Socket::INET(
         PeerAddr => $server,
         PeerPort => 80,
         Type     => SOCK_STREAM,
         Timeout  => 120
       ) or next;

    delete $headers{Connection} if exists $headers{Connection};

    print $ssock "$method $url HTTP/$vers\015\012";

    foreach (keys %headers) {
          print $ssock $_.": ".$headers{$_}."\015\012";
       }

    print $ssock "Connection: close\015\012\015\012";
       print $ssock $data;

    print LOG '   Request answer from '.$url."\n";
       my $log = 1;
       while ( <$ssock> ) {
          if ($_ =~ /^\s*$/) { $log = 0; }
          print LOG ' ' x 6 . $_ if $log;
          print $sock $_;
       }
    }

    close LOG;

    1. Halihallo Forumer

      Ich liebe es, wenn ein Plan funktioniert... Ach, wenn einer mal seine Mitarbeiter/Chefs/I-NetCaffee überpfüfen möchte, wo und was sie im INet surfen, nur den Proxi auf das Script setzen und...

      auszug aus'm proxi-log für den Request - fo_posting des letzten Postings... Big Brother is watching you!...

      Viele Grüsse

      Philipp

      Request on http://forum.de.selfhtml.org/cgi-bin/fo_posting.pl
         Request-Header:
            Pragma: no-cache
            Proxy-Connection: Keep-Alive
            Content-Type: application/x-www-form-urlencoded
            Host: forum.de.selfhtml.org
            Content-Length: 6116
            Referer: http://forum.de.selfhtml.org/?m=114967&t=20533
            Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
            Accept-Language: de
            User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
         Request-Content: (Length: 6116)
      fup=20533%3B114967&unid=Yx9pHc1FdcUF_LcCyLGeg_&qchar=%FF%BB%BB+&name=Philipp+Hasenfratz&email=philipp.hasenfratz@gmx.net&body=Halihallo+Forumer%0D%0A%0D%0Aso.+Jetzt+hatte+ich+endlich+Zeit+das+ganze+auch+auszuprobieren+und+es+funktioniert+perfekt%2C+naja%2C+fast%2C+sonst+m%FCsste+ich+hier+nicht+schreiben+%3B%29...+Danke+nochmals+f%FCr+deine+Beispiele%2C+Christian%3B+ich+hoffe+du+erlaubst%2C+dass+ich+diese+gleich+verwendet+habe+%28ging+einfach+schneller%2C+als+alles+nochmal+selber+zu+programmieren%29.%0D%0A%0D%0AAlles%2C+bis+auf+google.ch+funktioniert.+GET%2FPOST+Daten%2C+Cookies%2C+...+einfach+alles%2C+bis+auf+diesen+Google...+Wenn+ich+n%E4mlich+diese+Seite+lade%2C+dann+geht+der+Browser+in+eine+Endlosschlaufe+und+l%E4dt+die+Page+immer+neu.+Ich+glaube%2C+dass+es+an+dem+Status+302+h%E4ngt+bzw.+an+Proxy-Connection%3A+Keep-Alive%3F%3F%3F+-+Mal+schaun%2C+was+ihr+dazu+meint%3A%0D%0A%0D%0AViele+Gr%FCsse%0D%0A%0D%0APhilipp%0D%0A%0D%0APS%3A+Ganz+unten+noch+der+momentane+Code...%0D%0A%0D%0ARequest+on+http%3A%2F%2Fwww.google.ch%2F%0D%0A+++Request-Header%3A%0D%0A++++++Proxy-Connection%3A+Keep-Alive%0D%0A++++++Host%3A+www.google.ch%0D%0A++++++Cookie%3A+PREF%3DID%3D2ee932854a6b966a%3ALD%3Dde%3ATM%3D1029179593%3ALM%3D1029179593%3AS%3DyXSkNolyuIg%0D%0A++++++User-Agent%3A+Mozilla%2F4.0+%28compatible%3B+MSIE+6.0%3B+Windows+NT+5.1%29%0D%0A++++++Accept-Language%3A+de%0D%0A++++++Accept%3A+image%2Fgif%2C+image%2Fx-xbitmap%2C+image%2Fjpeg%2C+image%2Fpjpeg%2C+application%2Fvnd.ms-excel%2C+application%2Fvnd.ms-powerpoint%2C+application%2Fmsword%2C+*%2F*%0D%0A+++Request-Content%3A+%28Length%3A+%29%0D%0A+++Request+answer+from+http%3A%2F%2Fwww.google.ch%2F%0D%0A++++++HTTP%2F1.0+302+Found%0D%0A++++++Content-Length%3A+151%0D%0A++++++Connection%3A+Close%0D%0A++++++Server%3A+GWS%2F2.0%0D%0A++++++Content-Type%3A+text%2Fhtml%0D%0A++++++Date%3A+Sat%2C+17+Aug+2002+12%3A39%3A38+GMT%0D%0A++++++Location%3A+http%3A%2F%2Fwww.google.ch%2F%0D%0A++++++Set-Cookie%3A+PREF%3DID%3D1a0d0e7e7e467b7d%3ATM%3D1029587978%3ALM%3D1029587978%3AS%3DoKKDkzioSrA%3B+domain%3D.google.com%3B+path%3D%2F%3B+expires%3DSun%2C+17-Jan-2038+19%3A14%3A07+GMT%0D%0A%0D%0A----%0D%0A%0D%0Aproxi.pl%0D%0A%3D%3D%3D%3D%3D%3D%3D%3D%0D%0A%0D%0A%23%21%2Fusr%2Fbin%2Fperl%0D%0A%0D%0Ause+IO%3A%3ASocket%3A%3AINET%3B%0D%0Ause+LWP%3A%3ASimple%3B%0D%0A%0D%0Amy+%24socket+%3D+new+IO%3A%3ASocket%3A%3AINET%28%09LocalAddr%09%3D%3E+%27localhost%27%2C%0D%0A%09%09%09%09%09LocalPort%09%3D%3E+8080%2C%0D%0A%09%09%09%09%09Listen%09%09%3D%3E+5%2C%0D%0A%09%09%09%09%09Reuse%09%09%3D%3E+1%2C%0D%0A%09%09%09%09%09Proto%09%09%3D%3E+%27tcp%27+%29%0D%0A%09%09or+die+%27cannot+initialise+listener%27%3B%0D%0A%0D%0Amy+%25hosts+%3D+%28%09%27http%3A%2F%2Fwww.thedorcx.ch%2F%27%09%3D%3E+%27http%3A%2F%2F127.0.0.1%2Fwww.thedorcx.ch%2F%27%2C%0D%0A%09%09%27http%3A%2F%2Fwww.kodex.ch%2F%27%09%09%3D%3E+%27http%3A%2F%2F127.0.0.1%2Fwww.kodex.ch%2F%27%2C%0D%0A%09%09%27http%3A%2F%2Fwww.test.ch%2F%27%09%09%3D%3E+%27http%3A%2F%2F127.0.0.1%2Fwww.test.ch%2F%27+%29%3B%0D%0A%0D%0A%23+einige+Domain-Referer%2C+genau+das%2C+wozu+ich+den+Proxi+verwende...%0D%0A%23+also+die+Ursache%2C+warum+ich+erst+angefangen+habe+zu+programmieren.%0D%0A%0D%0Aopen%28+LOG%2C+%27%3E%3E.%2Flog.txt%27+%29%3B%0D%0A%0D%0Awhile+%28+my+%24sock+%3D+%24socket-%3Eaccept+%29+%7B%0D%0A%0D%0A+++my+%25headers%3B+my+%25_headers%3B%0D%0A+++%24headers%7B_firstline%7D+%3D+%3C%24sock%3E%3B%0D%0A%0D%0A+++while%28%3C%24sock%3E%29+%7B%0D%0A+++++last+if+m%2F%5E%5Cs*%24%2F%3B%0D%0A+++++if%28m%2F%5E%28%5CS%2B%29%3A+%28.*%29%24%2F%29+%7B%0D%0A+++++++my+%24n+%3D+%241%3B+my+%24v+%3D+%242%3B%0D%0A+++++++%24n+%3D%7E+s%2F%5C015%7C%5C012%2F%2Fg%3B%0D%0A+++++++%24v+%3D%7E+s%2F%5C015%7C%5C012%2F%2Fg%3B%0D%0A+++++++%24headers%7B%24n%7D+%3D+%24v%3B%0D%0A+++++++%24_headers%7Blc+%24n%7D+%3D+%24v%3B%0D%0A+++++%7D%0D%0A+++%7D%0D%0A%0D%0A+++my+%24data%3D%27%27%3B%0D%0A+++if%28%24headers%7B_firstline%7D+%3D%7E+%2F%5EPOST%2F%29+%7B%0D%0A+++++read+%24sock%2C+%24data%2C+%24_headers%7B%27content-length%27%7D%3B%0D%0A+++%7D%0D%0A%0D%0A+++%24request+%3D+%24headers%7B_firstline%7D%3B%0D%0A+++%24request+%3D%7E+%2F%5E%28.*%3F%29+%28.*%29+HTTP%5C%2F%28.*%3F%29%24%2Fi%3B%0D%0A+++my+%24url++%3D+%242%3B%0D%0A+++my+%24method+%3D+%241%3B%0D%0A+++my+%24vers+%3D+%243%3B%0D%0A%0D%0A+++while+%28+my+%28%24host%2C+%24vd_refer%29+%3D+each+%25hosts+%29+%7B%0D%0A++++++%24url+%3D%7E+s%2F%24host%2F%24vd_refer%2Fig%3B%0D%0A+++%7D%0D%0A+++my+%24server+%3D+%28split+%2F%5C%2F%2F%2C+%24url%29%5B2%5D%3B%0D%0A+++delete+%24headers%7B_firstline%7D%3B%0D%0A%0D%0A+++print+LOG+%27Request+on+%27.%24url.%22%5Cn%22%3B%0D%0A+++print+%27Request+on+%27.substr%28%24url%2C0%2C64%29.%22...%5Cn%22%3B%0D%0A+++print+LOG+%27+++Request-Header%3A%27.%22%5Cn%22%3B%0D%0A+++while+%28+my+%28%24n%2C%24v%29+%3D+each+%25headers+%29+%7B%0D%0A++++++print+LOG+%27+%27+x+6+.+%24n+.+%27%3A+%27+.+%24v+.+%22%5Cn%22%3B%0D%0A+++%7D%0D%0A+++print+LOG+%27+++Request-Content%3A+%28Length%3A+%27.%24_headers%7B%27content-length%27%7D.%27%29%27.%22%5Cn%22%3B%0D%0A+++if+%28length+%24data%29+%7B%0D%0A++++++print+LOG+%24data+.+%22%5Cn%22%3B%0D%0A+++%7D%0D%0A%0D%0A+++my+%24ssock+%3D+new+IO%3A%3ASocket%3A%3AINET%28%0D%0A+++++PeerAddr+%3D%3E+%24server%2C%0D%0A+++++PeerPort+%3D%3E+80%2C%0D%0A+++++Type+++++%3D%3E+SOCK_STREAM%2C%0D%0A+++++Timeout++%3D%3E+120%0D%0A+++%29+or+next%3B%0D%0A%0D%0A+++delete+%24headers%7BConnection%7D+if+exists+%24headers%7BConnection%7D%3B%0D%0A%0D%0A+++print+%24ssock+%22%24method+%24url+HTTP%2F%24vers%5C015%5C012%22%3B%0D%0A%0D%0A+++foreach+%28keys+%25headers%29+%7B%0D%0A++++++print+%24ssock+%24_.%22%3A+%22.%24headers%7B%24_%7D.%22%5C015%5C012%22%3B%0D%0A+++%7D%0D%0A%0D%0A+++print+%24ssock+%22Connection%3A+close%5C015%5C012%5C015%5C012%22%3B%0D%0A+++print+%24ssock+%24data%3B%0D%0A%0D%0A+++print+LOG+%27+++Request+answer+from+%27.%24url.%22%5Cn%22%3B%0D%0A+++my+%24log+%3D+1%3B%0D%0A+++while+%28+%3C%24ssock%3E+%29+%7B%0D%0A++++++if+%28%24_+%3D%7E+%2F%5E%5Cs*%24%2F%29+%7B+%24log+%3D+0%3B+%7D%0D%0A++++++print+LOG+%27+%27+x+6+.+%24_+if+%24log%3B%0D%0A++++++print+%24sock+%24_%3B%0D%0A+++%7D%0D%0A%7D%0D%0A%0D%0Aclose+LOG%3B&url=http%3A%2F%2F&image=http%3A%2F%2F
         Request answer from http://forum.de.selfhtml.org/cgi-bin/fo_posting.pl
            HTTP/1.1 200 OK
            Date: Sat, 17 Aug 2002 12:45:13 GMT
            Server: Apache/1.3.26 (Unix) PHP/4.2.1 mod_gzip/1.3.19.1a
            Connection: close
            Content-Type: text/html; charset=ISO-8859-1

    2. Hallo,

      also in Perl kenne ich mich nicht aus, hätte aber wahrscheinlich den einen oder anderen reg. Ausdruck anders geschrieben. Beispielsweise

      $n =~ s/\015|\012//g;
             $v =~ s/\015|\012//g;

      Da wäre ein
                $n =~ s/\015?\012//g;
                $v =~ s/\015?\012//g;

      näher an den Specs, weil es da heißt, dass nicht auf CR geprüft werden muss (tolerante Apps). Bei deinem reg. Ausdruck wäre es egal was da am Ende steht. Ein kleiner aber feiner Unterschied.

      Aber eigentlich wollte ich nur fragen wo dein $header geleert wird, damit nicht alte Werte drinstehen?

      Ich glaube, dass es an dem Status 302 hängt bzw. an Proxy-Connection: Keep-Alive??? - Mal schaun, was ihr dazu meint:

      302 steht doch normalerweise für "Moved Temporarily". Warum steht in deinem Log "302 Found"? Was das Keep-Alive betrifft, ist es so, sofern ich die Specs richtig verstanden habe, dass bei HTTP/1.0 explizit  erklärt werden muss, dass eine Verbindung persistent ist (keep-alive, aufrecht erhalten) und bei HTTP/1.1 ist es genau umgekehrt. Es wird stets davon ausgegangen, dass eine Verbindung persistent ist, und durch ein "Connection: close" wird mitgeteilt, dass sie geschlossen wird.

      Könntest du die entspr. Headers (Request, Response) komplett posten? Denn da wäre es für mich als Perl-Unwissender einfacher einen Fehler zu erkennen.

      micha

      1. Halihallo

        also in Perl kenne ich mich nicht aus, hätte aber wahrscheinlich den einen oder anderen reg. Ausdruck anders geschrieben. Beispielsweise

        $n =~ s/\015|\012//g;
               $v =~ s/\015|\012//g;

        Da wäre ein
                  $n =~ s/\015?\012//g;
                  $v =~ s/\015?\012//g;

        ich glaube, dass beide RegExp genau das selbe machen ;)
        wegen dem g, da werden bei mir _alle_ \015 und _alle_ \012 gelöscht, bei dir macht es genau das selbe

        näher an den Specs, weil es da heißt, dass nicht auf CR geprüft werden muss (tolerante Apps). Bei deinem reg. Ausdruck wäre es egal was da am Ende steht. Ein kleiner aber feiner Unterschied.

        ich sehe keinen Unterschied...

        Aber eigentlich wollte ich nur fragen wo dein $header geleert wird, damit nicht alte Werte drinstehen?

        Ich habe in etwa das übernommen, was Christian gepostet hat. Dort wird eigentlich nur das Connection: Feld gelöscht und durch Connection: close ersetzt. Dann wird die ganze Page eingelesen und an den Client ungeändert zurückgesendet...

        Ich glaube, dass es an dem Status 302 hängt bzw. an Proxy-Connection: Keep-Alive??? - Mal schaun, was ihr dazu meint:

        302 steht doch normalerweise für "Moved Temporarily". Warum steht in deinem Log "302 Found"?

        Ja, s. unten.

        Was das Keep-Alive betrifft, ist es so, sofern ich die Specs richtig verstanden habe, dass bei HTTP/1.0 explizit  erklärt werden muss, dass eine Verbindung persistent ist (keep-alive, aufrecht erhalten) und bei HTTP/1.1 ist es genau umgekehrt. Es wird stets davon ausgegangen, dass eine Verbindung persistent ist, und durch ein "Connection: close" wird mitgeteilt, dass sie geschlossen wird.

        Ist mir klar. Ich kann mir nur nicht erklären, warum der Browser in eine Endlosschleife kommt, wenn ich www.google.ch aufrufe. 302 => Temporarely Moved => denkt da der Browser, dass er es einfach solange versuchen soll, bis er eine gültige 200-er als Antwort bekommt?

        Könntest du die entspr. Headers (Request, Response) komplett posten? Denn da wäre es für mich als Perl-Unwissender einfacher einen Fehler zu erkennen.

        Her der Auszug. Ich poste hier zwei Requests. Wenn ich google.ch aufrufe, geht er wie gesagt in einen Endlosrequest über und versucht immer wieder von neuem google.ch zu öffnen. "Request-Header" und "Request-Content" sind die Daten, die der Browser an den Proxi sendet. "Request answer" ist dann die Antwort von google.ch (den Content lass ich lieber nicht loggen, sonst ist meine HD ziemlich schnell voll ;))

        Viele Grüsse und Danke

        Philipp

        --- LOG ---

        Request on http://www.google.ch/
           Request-Header:
              Proxy-Connection: Keep-Alive
              Host: www.google.ch
              Cookie: PREF=ID=2ee932854a6b966a:LD=de:TM=1029179593:LM=1029179593:S=yXSkNolyuIg
              Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
              User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
              Accept-Language: de
           Request-Content: (Length: )
           Request answer from http://www.google.ch/
              HTTP/1.0 302 Found
              Content-Length: 151
              Connection: Close
              Server: GWS/2.0
              Content-Type: text/html
              Date: Mon, 19 Aug 2002 09:07:49 GMT
              Location: http://www.google.ch/
              Set-Cookie: PREF=ID=1f1fd7ba1fe8791b:TM=1029748069:LM=1029748069:S=IT0SXd9GVIY; domain=.google.com; path=/; expires=Sun, 17-Jan-2038 19:14:07 GMT

        Request on http://www.google.ch/
           Request-Header:
              Proxy-Connection: Keep-Alive
              Host: www.google.ch
              Cookie: PREF=ID=2ee932854a6b966a:LD=de:TM=1029179593:LM=1029179593:S=yXSkNolyuIg
              Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
              User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
              Accept-Language: de
           Request-Content: (Length: )
           Request answer from http://www.google.ch/
              HTTP/1.0 302 Found
              Content-Length: 151
              Connection: Close
              Server: GWS/2.0
              Content-Type: text/html
              Date: Mon, 19 Aug 2002 09:07:50 GMT
              Location: http://www.google.ch/
              Set-Cookie: PREF=ID=44111b0c6b28a7b8:TM=1029748070:LM=1029748070:S=ZUCAc68Nae4; domain=.google.com; path=/; expires=Sun, 17-Jan-2038 19:14:07 GMT