#!/usr/bin/perl -W

# TP proxy HTTP
#
# Question 2
#
# Antoine Miné
# 15/05/2007

use IO::Socket::INET;  # on utilise l'interface orientée-objet

# 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;

	# ignore les en-têtes (Proxy-)Connection
	next if $l =~ /^proxy-connection:/i;
	next if $l =~ /^connection:/i;

	push @headers, $l;
    }

    # 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 "<html><head><title>Erreur!</title></head>\r\n";
	print $client "<body><p>Je n'ai pas trouvé $host.</body></html>\r\n";
	next;
    }

    print $serv "$req";
    print $serv "Connection: close\r\n";
    foreach $k (@headers) { print $serv "$k"; }
    print $serv "\r\n";

    # renvoie la réponse (statu + en-têtes + corps)
    while ($l = <$serv>) {
	print $client $l;
    }

    close $client;
    close $serv;
}
