Squid_ The Definitive Guide - Duane Wessels [105]
For example, if a redirector writes this line on its stdout:
301:http://www.example.com/page2.html
Squid sends a response like this back to the client:
HTTP/1.0 301 Moved Permanently
Server: squid/2.5.STABLE4
Date: Mon, 29 Sep 2003 04:06:23 GMT
Content-Length: 0
Location: http://www.example.com/page2.html
X-Cache: MISS from zoidberg
Proxy-Connection: close
Some Sample Redirectors
Example 11-1 is a very simple redirector written in Perl. Its purpose is to send HTTP requests for the squid-cache.org site to a local mirror site in Australia. If the requested URI looks like it is for www.squid-cache.org or one of its mirror sites, this script outputs a new URI with the hostname set to www1.au.squid-cache.org.
A common problem first-time redirector writers encounter is buffered I/O. Note that here I make sure stdout is unbuffered.
Example 11-1. A simple redirector in Perl
#!/usr/bin/perl -wl
$|=1; # don't buffer the output
while (<>) {
($uri,$client,$ident,$method) = ( );
($uri,$client,$ident,$method) = split;
next unless ($uri =~ m,^http://.*\.squid-cache\.org(\S*),);
$uri = "http://www1.au.squid-cache.org$1";
} continue {
print "$uri";
}
Example 11-2 is another, somewhat more complicated, example. Here I make a feeble attempt to deny requests when the URI contains "bad words." This script demonstrates an alternative way to parse the input fields. If I don't get all five required fields, the redirector returns a blank line, leaving the request unchanged.
This example also gives preferential treatment to some users. If the ident string is equal to "BigBoss," or comes from the 192.168.4.0 subnet, the request is passed through. Finally, I use the 301: trick to make Squid return an HTTP redirect to the client. Note, this program is neither efficient nor smart enough to correctly deny so-called bad requests.
Example 11-2. A slightly less simple redirector in Perl
#!/usr/bin/perl -wl
$|=1; # don't buffer the output
$DENIED = "http://www.example.com/denied.html";
&load_word_list( );
while (<>) {
unless (m,(\S+) (\S+)/(\S+) (\S+) (\S+),) {
$uri = '';
next;
}
$uri = $1;
$ipaddr = $2;
#$fqdn = $3;
$ident = $4;
#$method = $5;
next if ($ident eq 'TheBoss');
next if ($ipaddr =~ /^192\.168\.4\./);
$uri = "301:$DENIED" if &word_match($uri);
} continue {
print "$uri";
}
sub load_word_list {
@words = qw(sex drugs rock roll);
}
sub word_match {
my $uri = shift;
foreach $w (@words) { return 1 if ($uri =~ /$w/); }
return 0;
}
For more ideas about writing your own redirector, I recommend reading the source code for the redirectors mentioned in Section 11.5.
The Redirector Pool
A redirector can take an arbitrarily long time to return its answer. For example, it may need to make a database query, search through long lists of regular expressions, or make some complex computations. Squid uses a pool of redirector processes so that they can all work in parallel. While one is busy, Squid hands a new request off to another.
For each new request, Squid examines the pool of redirector processes in order. It submits the request to the first idle process. If your request rate is very low, the first redirector may be able to handle all requests itself.
You can control the size of the redirector pool with the redirect_children directive. The default value is five processes. Note that Squid doesn't dynamically increase or decrease the size of the pool depending on the load. Thus, it is a good idea to be a little liberal. If all redirectors are busy, Squid queues pending requests. If the queue becomes too large (bigger than twice the pool size), Squid exits with a fatal error message:
FATAL: Too many queued redirector requests
In this case, you need to increase the size of the redirector pool or change something so that the redirectors can process requests faster. You can use the cache manager's redirector page to find out if you have too few, or too many redirectors running. For example: