diff --git a/lib/URI/_server.pm b/lib/URI/_server.pm index b58bfc1..1056152 100644 --- a/lib/URI/_server.pm +++ b/lib/URI/_server.pm @@ -156,10 +156,14 @@ sub canonical my $uc_host = $host =~ /[A-Z]/; my $def_port = defined($port) && ($port eq "" || $port == $self->default_port); - if ($uc_host || $def_port) { + # Normalize port by stripping leading zeros (but not if it's a default port that will be removed) + # Only normalize if port starts with 0 followed by another digit (e.g., 08080, 080, 00443) + my $norm_port = !$def_port && defined($port) && $port ne "" && $port =~ /^0\d/; + if ($uc_host || $def_port || $norm_port) { $other = $other->clone if $other == $self; $other->host(lc $host) if $uc_host; $other->port(undef) if $def_port; + $other->_port(int($port)) if $norm_port; } $other; } diff --git a/t/port-leading-zeros.t b/t/port-leading-zeros.t new file mode 100644 index 0000000..b27fc01 --- /dev/null +++ b/t/port-leading-zeros.t @@ -0,0 +1,45 @@ +use strict; +use warnings; + +use Test::More tests => 15; + +use URI (); + +# Test leading zeros in non-default ports are stripped in canonical form +my $u = URI->new('http://xyz:08080'); +is($u->canonical->port, 8080, 'Leading zero stripped from port 08080'); +is($u->canonical, 'http://xyz:8080/', 'Canonical URI has normalized port 8080'); + +# Test leading zeros in default HTTP port (80) +$u = URI->new('http://xyz:080'); +is($u->canonical->port, 80, 'Default port 080 normalized to 80'); +is($u->canonical, 'http://xyz/', 'Default port 80 removed from canonical URI'); + +# Test leading zeros in default HTTPS port (443) +$u = URI->new('https://xyz:0443'); +is($u->canonical->port, 443, 'Default port 0443 normalized to 443'); +is($u->canonical, 'https://xyz/', 'Default port 443 removed from canonical URI'); + +# Test multiple leading zeros +$u = URI->new('http://xyz:00443'); +is($u->canonical->port, 443, 'Multiple leading zeros stripped from port 00443'); +is($u->canonical, 'http://xyz:443/', 'Canonical URI has normalized port 443'); + +# Test port with single leading zero +$u = URI->new('http://xyz:01234'); +is($u->canonical->port, 1234, 'Single leading zero stripped from port 01234'); +is($u->canonical, 'http://xyz:1234/', 'Canonical URI has normalized port 1234'); + +# Test that regular ports without leading zeros are unchanged +$u = URI->new('http://xyz:8080'); +is($u->canonical->port, 8080, 'Port 8080 without leading zeros unchanged'); +is($u->canonical, 'http://xyz:8080/', 'Canonical URI with port 8080 unchanged'); + +# Test port 0 (edge case) +$u = URI->new('http://xyz:0'); +is($u->canonical->port, 0, 'Port 0 normalized correctly'); + +# Test FTP with leading zeros on default port +$u = URI->new('ftp://xyz:021'); +is($u->canonical->port, 21, 'FTP default port 021 normalized to 21'); +is($u->canonical, 'ftp://xyz', 'FTP default port 21 removed from canonical URI');