I think I worked this out. I found in some WWW::Mechanize docs that the proper way to query the redirect is using
$response->redirects(). It seems that t.co does not return this header (anyone know why?) so you have to get it with the refresh parameter. But all the other shorteners (at least a slew of them I tested) do. So this code should work for most purposes.
use strict;
use feature ':5.10';
use LWP::UserAgent;
our $ua = LWP::UserAgent->new;
$ua->max_redirect(10);
my @links = qw(
https://tinyurl.com/69rmnakp
https://t.co/NqACDPYdD9
https://bit.ly/3eikm4z
http://apne.ws/HGpbLTW
);
foreach my $link (@links) {
say "$link > ".expand($link);
}
sub expand {
my ($short) = @_;
my $long;
my $response = $ua->get($short);
if ($response->is_success) {
my @redirects = $response->redirects();
if (@redirects) {
$long = $redirects[0]->header('location');
}
elsif ($response->header('refresh')) {
$long = $response->header('refresh');
$long =~ s/0\;URL\=//;
}
return $long;
}
else {
return $short;
}
}