Fixes parsing of URIs that begin with '//'.

This commit is contained in:
Dominik Picheta 2015-08-23 18:22:37 +01:00
commit 193f248ea0

View file

@ -14,7 +14,7 @@ type
Url* = distinct string Url* = distinct string
Uri* = object Uri* = object
scheme*, username*, password*: string scheme*, username*, password*: string
hostname*, port*, path*, query*, anchor*: string hostname*, port*, path*, query*, anchor*: string
opaque*: bool opaque*: bool
@ -69,7 +69,7 @@ proc parseAuthority(authority: string, result: var Uri) =
i.inc i.inc
proc parsePath(uri: string, i: var int, result: var Uri) = proc parsePath(uri: string, i: var int, result: var Uri) =
i.inc parseUntil(uri, result.path, {'?', '#'}, i) i.inc parseUntil(uri, result.path, {'?', '#'}, i)
# The 'mailto' scheme's PATH actually contains the hostname/username # The 'mailto' scheme's PATH actually contains the hostname/username
@ -104,19 +104,23 @@ proc parseUri*(uri: string, result: var Uri) =
var i = 0 var i = 0
# Check if this is a reference URI (relative URI) # Check if this is a reference URI (relative URI)
let doubleSlash = uri.len > 1 and uri[1] == '/'
if uri[i] == '/': if uri[i] == '/':
parsePath(uri, i, result) # Make sure ``uri`` doesn't begin with '//'.
return if not doubleSlash:
parsePath(uri, i, result)
return
# Scheme # Scheme
i.inc parseWhile(uri, result.scheme, Letters + Digits + {'+', '-', '.'}, i) i.inc parseWhile(uri, result.scheme, Letters + Digits + {'+', '-', '.'}, i)
if uri[i] != ':': if uri[i] != ':' and not doubleSlash:
# Assume this is a reference URI (relative URI) # Assume this is a reference URI (relative URI)
i = 0 i = 0
result.scheme.setLen(0) result.scheme.setLen(0)
parsePath(uri, i, result) parsePath(uri, i, result)
return return
i.inc # Skip ':' if not doubleSlash:
i.inc # Skip ':'
# Authority # Authority
if uri[i] == '/' and uri[i+1] == '/': if uri[i] == '/' and uri[i+1] == '/':
@ -201,7 +205,7 @@ proc combine*(base: Uri, reference: Uri): Uri =
## ##
## let bar = combine(parseUri("http://example.com/foo/bar/"), parseUri("baz")) ## let bar = combine(parseUri("http://example.com/foo/bar/"), parseUri("baz"))
## assert bar.path == "/foo/bar/baz" ## assert bar.path == "/foo/bar/baz"
template setAuthority(dest, src: expr): stmt = template setAuthority(dest, src: expr): stmt =
dest.hostname = src.hostname dest.hostname = src.hostname
dest.username = src.username dest.username = src.username
@ -369,6 +373,15 @@ when isMainModule:
doAssert test.path == "test/no/slash" doAssert test.path == "test/no/slash"
doAssert($test == str) doAssert($test == str)
block:
let str = "//git@github.com:dom96/packages"
let test = parseUri(str)
doAssert test.scheme == ""
doAssert test.username == "git"
doAssert test.hostname == "github.com"
doAssert test.port == "dom96"
doAssert test.path == "/packages"
# Remove dot segments tests # Remove dot segments tests
block: block:
doAssert removeDotSegments("/foo/bar/baz") == "/foo/bar/baz" doAssert removeDotSegments("/foo/bar/baz") == "/foo/bar/baz"