#!/usr/bin/perl -W # TP proxy HTTP # # Question 5 # # réponse basée sur celle de la question 2 (pas de prise en compte du keep-alive) # # Antoine Miné # 15/05/2007 use IO::Socket::INET; # on utilise l'interface orientée-objet # cache %cache = (); # création de la socket d'écoute $listen = new IO::Socket::INET(LocalPort => '8080', Proto => 'tcp', Listen => 5, ReuseAddr => 1, ) or die "échec de création de la socket d'écoute: $!"; # boucle de traitement des connections while ($client = $listen->accept()) { # lit la requête $req = <$client>; ($url) = $req =~ m!GET (\S*) HTTP/1.?! or die "requête non reconnue: $_"; print "requête entrante: $url\n"; # lit et filtre les en-têtes @headers = (); # accumulateur d'en-têtes $host = undef; while ($l = <$client>) { last if $l =~ /^\r\n$/; # récupère le contenu de l'en-tête host $host = $1 if $l =~ /^host:\s*(\S+)/i; # le client nous force à ignorer le cache et à recharger la page $cache{$url} = undef if $l =~ /^cache-control:.*max-age=0/i; $cache{$url} = undef if $l =~ /^cache-control:.*no-cache/i; # ignore les en-têtes (Proxy-)Connection next if $l =~ /^proxy-connection:/i; next if $l =~ /^connection:/i; push @headers, $l; } if (defined $cache{$url}) { # envoie la page en cache print $client "$cache{$url}"; print "en cache\n"; } else { $should_cache = 1; # envoie la requête au vrai serveur unless (defined($host) && ($serv = new IO::Socket::INET(PeerAddr => $host, PeerPort => '80', Proto => 'tcp', ))) { # si on échoue à contacter le serveur print $client "HTTP/1.1 502 Bad Gateway\r\n"; print $client "Connection: close\r\n"; print $client "Content-type: text/html\r\n"; print $client "\r\n"; print $client "Erreur!\r\n"; print $client "

Je n'ai pas trouvé $host.\r\n"; next; } print $serv "$req"; print $serv "Connection: close\r\n"; foreach $k (@headers) { print $serv "$k"; } print $serv "\r\n"; # lit la réponse (statu + en-têtes) du serveur $page = <$serv>; $should_cache = 0 if $page !~ /200/; # pas de cache en cas d'erreur while ($l = <$serv>) { $page = "$page$l"; $should_cache = 0 if $page =~ /^cache-control:.*no-cache/i; $should_cache = 0 if $page =~ /^cache-control:.*no-store/i; $should_cache = 0 if $page =~ /^cache-control:.*must-revalidate/i; last if $l =~ /^\r\n$/; } # lit le cors de la réponse while (<$serv>) { $page = "$page$_"; } # envoie le tout au client print $client "$page"; if ($should_cache) { # stocke la page $cache{$url} = "$page"; } close $serv; } close $client; }