A large amount of my support work is helping people set up web sites. It's time-consuming because we often have to co-ordinate between three or more groups: typically University IT (me and colleagues), the non-technical owner of the web site, and some commercial web consultancy. And there are often problems, so the co-ordination overhead makes them even slower to fix.
When moving an existing web site, I check that the new web server will work before I update the DNS - it's embarrassing if they have an outage because of an easy-to-avoid cockup, and it's good if we can avoid a panic.
I use a little wrapper around curl --resolve
for testing. This makes
curl
ignore the DNS and talk to the web server I tell it to, but it
still uses the new host name when sending the Host: header and TLS SNI
and doing certificate verification.
You use the script like:
curlto <target server> [curl options] <url>
e.g.
curlto ucam-ac-uk.csi.cam.ac.uk -LI http://some.random.name
This needs a bit of scripting because the curl --resolve
option is a
faff: you need to explicitly map the URL hostname to all the target IP
addresses, and you need to repeat the mapping for both http and https.
Here's the script:
#!/usr/bin/perl
use warnings;
use strict;
use Net::DNS;
my $dns = new Net::DNS::Resolver;
sub addrs {
my $dn = shift;
my @a;
for my $t (qw(A AAAA)) {
my $r = $dns->query($dn, $t) or next;
push @a, map $_->address, grep { $_->type eq $t } $r->answer;
}
die "curlto: could not resolve $dn\n" unless @a;
return @a;
}
unless (@ARGV > 1) {
die "usage: curlto <target server> [curl options] <url>\n";
}
my $url = $ARGV[-1];
$url =~ m{^(https?://)?([a-z0-9.-]+)}
or die "curlto: could not parse hostname in '$url'\n";
my $name = $2;
my @addr = shift;
@addr = addrs @addr unless $addr[0] =~ m{^([0-9.]+|[0-9a-f:]+)$};
for my $addr (@addr) {
unshift @ARGV, '--resolv', "$name:80:$addr";
unshift @ARGV, '--resolv', "$name:443:$addr";
}
print "curl @ARGV\n";
exec 'curl', @ARGV;