diff --git a/changelog.md b/changelog.md index 1bc1d7303a..bd56746107 100644 --- a/changelog.md +++ b/changelog.md @@ -197,6 +197,8 @@ """ ``` +- Add `initUri(isIpv6: bool)` to `uri` module, now `uri` supports parsing ipv6 hostname. + ## Language changes - The `=destroy` hook no longer has to reset its target, as the compiler now automatically inserts diff --git a/lib/pure/uri.nim b/lib/pure/uri.nim index 04a9d97bd7..4b84a89021 100644 --- a/lib/pure/uri.nim +++ b/lib/pure/uri.nim @@ -49,6 +49,7 @@ import std/private/since import strutils, parseutils, base64 include includes/decode_helpers + type Url* = distinct string @@ -56,6 +57,7 @@ type scheme*, username*, password*: string hostname*, port*, path*, query*, anchor*: string opaque*: bool + isIpv6: bool # not expose it for compatibility. proc encodeUrl*(s: string, usePlus = true): string = ## Encodes a URL according to RFC3986. @@ -170,6 +172,7 @@ proc parseAuthority(authority: string, result: var Uri) = inPort = true of '[': inIPv6 = true + result.isIpv6 = true of ']': inIPv6 = false else: @@ -208,6 +211,21 @@ proc initUri*(): Uri = result = Uri(scheme: "", username: "", password: "", hostname: "", port: "", path: "", query: "", anchor: "") +proc initUri*(isIpv6: bool): Uri {.since: (1, 3, 5).} = + ## Initializes a URI with ``scheme``, ``username``, ``password``, + ## ``hostname``, ``port``, ``path``, ``query``, ``anchor`` and ``isIpv6``. + ## + ## **See also:** + ## * `Uri type <#Uri>`_ for available fields in the URI type + runnableExamples: + var uri2 = initUri(isIpv6 = true) + uri2.scheme = "tcp" + uri2.hostname = "2001:0db8:85a3:0000:0000:8a2e:0370:7334" + uri2.port = "8080" + assert $uri2 == "tcp://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8080" + result = Uri(scheme: "", username: "", password: "", hostname: "", port: "", + path: "", query: "", anchor: "", isIpv6: isIpv6) + proc resetUri(uri: var Uri) = for f in uri.fields: when f is string: @@ -452,9 +470,15 @@ proc `$`*(u: Uri): string = result.add(u.password) result.add("@") if u.hostname.endsWith('/'): - result.add(u.hostname[0..^2]) + if u.isIpv6: + result.add("[" & u.hostname[0 .. ^2] & "]") + else: + result.add(u.hostname[0 .. ^2]) else: - result.add(u.hostname) + if u.isIpv6: + result.add("[" & u.hostname & "]") + else: + result.add(u.hostname) if u.port.len > 0: result.add(":") result.add(u.port) diff --git a/tests/stdlib/turi.nim b/tests/stdlib/turi.nim new file mode 100644 index 0000000000..9fb349e88b --- /dev/null +++ b/tests/stdlib/turi.nim @@ -0,0 +1,17 @@ +discard """ + cmd: "nim c -r --styleCheck:hint --panics:on $options $file" + targets: "c" + nimout: "" + action: "run" + exitcode: 0 + timeout: 60.0 +""" +import uri + + +block: + let org = "udp://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8080" + let url = parseUri(org) + doAssert url.hostname == "2001:0db8:85a3:0000:0000:8a2e:0370:7334" # true + let newUrl = parseUri($url) + doAssert newUrl.hostname == "2001:0db8:85a3:0000:0000:8a2e:0370:7334" # true