mw.uri: Support IP-Literal syntax

RFC 3986 allows IPv6 literals (and future IP versions) by having the
"host" enclosed in brackets, like `http://[2001:db8::]`. mw.uri should
handle these appropriately.

Bug: T223267
Change-Id: I6f712b87bc376cf606c6c2ebbe80176037d6dddb
This commit is contained in:
Brad Jorsch 2019-05-14 08:48:39 -04:00 committed by jenkins-bot
parent 158a8c8efa
commit 2e79d0a719
2 changed files with 35 additions and 9 deletions

View file

@ -191,7 +191,12 @@ function uri.validate( obj )
if obj.host then
if type( obj.host ) ~= 'string' then
err[#err+1] = '.host must be a string, not ' .. type( obj.host )
elseif not string.match( obj.host, '^[^:/?#]*$' ) then
elseif not (
-- Normal syntax
string.match( obj.host, '^[^:/?#]*$' ) or
-- IP-literal syntax
string.match( obj.host, '^%[[^/?#%[%]@]+%]$' )
) then
err[#err+1] = 'invalid .host'
end
end
@ -450,15 +455,27 @@ function urimt:__newindex( key, value )
local host, port = nil, nil
if value then
checkTypeForIndex( key, value, 'string' )
local i = string.find( value, ':', 1, true )
if i then
host = string.sub( value, 1, i - 1 )
port = tonumber( string.sub( value, i + 1 ) )
if not port then
error( string.format( "Invalid port in '%s'", value ), 2 )
-- IP-literal syntax, with and without a port
host, port = string.match( value, '^(%[[^/?#%[%]@]+%]):(%d+)$' )
if port then
port = tonumber( port )
end
if not host then
host = string.match( value, '^(%[[^/?#%[%]@]+%])$' )
end
-- Normal syntax
if not host then
local i = string.find( value, ':', 1, true )
if i then
host = string.sub( value, 1, i - 1 )
port = tonumber( string.sub( value, i + 1 ) )
if not port then
error( string.format( "Invalid port in '%s'", value ), 2 )
end
else
host = value
end
else
host = value
end
end
rawset( self, 'host', host )

View file

@ -126,6 +126,15 @@ local tests = {
args = { 'http://wiki.local/w/index.php#' },
expect = { 'http://wiki.local/w/index.php#' },
},
{ name = 'uri.new with IPv6', func = mw.uri.new, type = 'ToString',
args = { 'http://[2001:db8::]' },
expect = { 'http://[2001:db8::]' },
},
{ name = 'uri.new with IPv6 and port', func = mw.uri.new, type = 'ToString',
args = { 'http://[2001:db8::]:80' },
expect = { 'http://[2001:db8::]:80' },
},
}
-- Add tests to test round-tripping for every combination of parameters