diff options
Diffstat (limited to 'lib/pure/uri.nim')
-rw-r--r-- | lib/pure/uri.nim | 174 |
1 files changed, 112 insertions, 62 deletions
diff --git a/lib/pure/uri.nim b/lib/pure/uri.nim index d296017dd..bfb411fc8 100644 --- a/lib/pure/uri.nim +++ b/lib/pure/uri.nim @@ -8,6 +8,35 @@ # ## This module implements URI parsing as specified by RFC 3986. +## +## A Uniform Resource Identifier (URI) provides a simple and extensible +## means for identifying a resource. A URI can be further classified +## as a locator, a name, or both. The term “Uniform Resource Locator” +## (URL) refers to the subset of URIs. +## +## Basic usage +## =========== +## +## Combine URIs +## ------------- +## .. code-block:: +## import uri +## let host = parseUri("https://nim-lang.org") +## let blog = "/blog.html" +## let bloguri = host / blog +## assert $host == "https://nim-lang.org" +## assert $bloguri == "https://nim-lang.org/blog.html" +## +## Access URI item +## --------------- +## .. code-block:: +## import uri +## let res = parseUri("sftp://127.0.0.1:4343") +## if isAbsolute(res): +## echo "Connect to port: " & res.port +## # --> Connect to port: 4343 +## else: +## echo "Wrong format" import strutils, parseutils type @@ -18,44 +47,24 @@ type hostname*, port*, path*, query*, anchor*: string opaque*: bool -{.push warning[deprecated]: off.} -proc `$`*(url: Url): string {.deprecated: "use Uri instead".} = - ## **Deprecated since 0.9.6**: Use ``Uri`` instead. - return string(url) - -proc `/`*(a, b: Url): Url {.deprecated: "use Uri instead".} = - ## Joins two URLs together, separating them with / if needed. - ## - ## **Deprecated since 0.9.6**: Use ``Uri`` instead. - var urlS = $a - var bS = $b - if urlS == "": return b - if urlS[urlS.len-1] != '/': - urlS.add('/') - if bS[0] == '/': - urlS.add(bS.substr(1)) - else: - urlS.add(bs) - result = Url(urlS) - -proc add*(url: var Url, a: Url) {.deprecated: "use Uri instead".} = - ## Appends url to url. - ## - ## **Deprecated since 0.9.6**: Use ``Uri`` instead. - url = url / a -{.pop.} - proc encodeUrl*(s: string, usePlus=true): string = ## Encodes a URL according to RFC3986. ## ## This means that characters in the set ## ``{'a'..'z', 'A'..'Z', '0'..'9', '-', '.', '_', '~'}`` are ## carried over to the result. - ## All other characters are encoded as ``''%xx'`` where ``xx`` + ## All other characters are encoded as ``%xx`` where ``xx`` ## denotes its hexadecimal value. ## ## As a special rule, when the value of ``usePlus`` is true, - ## spaces are encoded as ``'+'`` instead of ``'%20'``. + ## spaces are encoded as ``+`` instead of ``%20``. + ## + ## **See also:** + ## * `decodeUrl proc<#decodeUrl,string>`_ + runnableExamples: + assert encodeUrl("https://nim-lang.org") == "https%3A%2F%2Fnim-lang.org" + assert encodeUrl("https://nim-lang.org/this is a test") == "https%3A%2F%2Fnim-lang.org%2Fthis+is+a+test" + assert encodeUrl("https://nim-lang.org/this is a test", false) == "https%3A%2F%2Fnim-lang.org%2Fthis%20is%20a%20test" result = newStringOfCap(s.len + s.len shr 2) # assume 12% non-alnum-chars let fromSpace = if usePlus: "+" else: "%20" for c in s: @@ -70,12 +79,19 @@ proc encodeUrl*(s: string, usePlus=true): string = proc decodeUrl*(s: string, decodePlus=true): string = ## Decodes a URL according to RFC3986. ## - ## This means that any ``'%xx'`` (where ``xx`` denotes a hexadecimal + ## This means that any ``%xx`` (where ``xx`` denotes a hexadecimal ## value) are converted to the character with ordinal number ``xx``, ## and every other character is carried over. ## - ## As a special rule, when the value of ``decodePlus`` is true, ``'+'`` + ## As a special rule, when the value of ``decodePlus`` is true, ``+`` ## characters are converted to a space. + ## + ## **See also:** + ## * `encodeUrl proc<#encodeUrl,string>`_ + runnableExamples: + assert decodeUrl("https%3A%2F%2Fnim-lang.org") == "https://nim-lang.org" + assert decodeUrl("https%3A%2F%2Fnim-lang.org%2Fthis+is+a+test") == "https://nim-lang.org/this is a test" + assert decodeUrl("https%3A%2F%2Fnim-lang.org%2Fthis%20is%20a%20test", false) == "https://nim-lang.org/this is a test" proc handleHexChar(c: char, x: var int) {.inline.} = case c of '0'..'9': x = (x shl 4) or (ord(c) - ord('0')) @@ -150,7 +166,14 @@ proc parsePath(uri: string, i: var int, result: var Uri) = i.inc parseUntil(uri, result.anchor, {}, i) proc initUri*(): Uri = - ## Initializes a URI. + ## Initializes a URI with ``scheme``, ``username``, ``password``, + ## ``hostname``, ``port``, ``path``, ``query`` and ``anchor``. + ## + ## **See also:** + ## * `Uri type <#Uri>`_ for available fields in the URI type + runnableExamples: + var uri: Uri + assert initUri() == uri result = Uri(scheme: "", username: "", password: "", hostname: "", port: "", path: "", query: "", anchor: "") @@ -163,6 +186,16 @@ proc resetUri(uri: var Uri) = proc parseUri*(uri: string, result: var Uri) = ## Parses a URI. The `result` variable will be cleared before. + ## + ## **See also:** + ## * `Uri type <#Uri>`_ for available fields in the URI type + ## * `initUri proc <#initUri,>`_ for initializing a URI + runnableExamples: + var res = initUri() + parseUri("https://nim-lang.org/docs/manual.html", res) + assert res.scheme == "https" + assert res.hostname == "nim-lang.org" + assert res.path == "/docs/manual.html" resetUri(result) var i = 0 @@ -201,6 +234,14 @@ proc parseUri*(uri: string, result: var Uri) = proc parseUri*(uri: string): Uri = ## Parses a URI and returns it. + ## + ## **See also:** + ## * `Uri type <#Uri>`_ for available fields in the URI type + runnableExamples: + let res = parseUri("ftp://Username:Password@Hostname") + assert res.username == "Username" + assert res.password == "Password" + assert res.scheme == "ftp" result = initUri() parseUri(uri, result) @@ -251,22 +292,18 @@ proc combine*(base: Uri, reference: Uri): Uri = ## This uses the algorithm specified in ## `section 5.2.2 of RFC 3986 <http://tools.ietf.org/html/rfc3986#section-5.2.2>`_. ## - ## This means that the slashes inside the base URI's path as well as reference - ## URI's path affect the resulting URI. - ## - ## For building URIs you may wish to use \`/\` instead. - ## - ## Examples: - ## - ## .. code-block:: - ## let foo = combine(parseUri("http://example.com/foo/bar"), parseUri("/baz")) - ## assert foo.path == "/baz" - ## - ## let bar = combine(parseUri("http://example.com/foo/bar"), parseUri("baz")) - ## assert bar.path == "/foo/baz" + ## This means that the slashes inside the base URIs path as well as reference + ## URIs path affect the resulting URI. ## - ## let bar = combine(parseUri("http://example.com/foo/bar/"), parseUri("baz")) - ## assert bar.path == "/foo/bar/baz" + ## **See also:** + ## * `/ proc <#/,Uri,string>`_ for building URIs + runnableExamples: + let foo = combine(parseUri("https://nim-lang.org/foo/bar"), parseUri("/baz")) + assert foo.path == "/baz" + let bar = combine(parseUri("https://nim-lang.org/foo/bar"), parseUri("baz")) + assert bar.path == "/foo/baz" + let qux = combine(parseUri("https://nim-lang.org/foo/bar/"), parseUri("baz")) + assert qux.path == "/foo/bar/baz" template setAuthority(dest, src): untyped = dest.hostname = src.hostname @@ -302,32 +339,42 @@ proc combine*(base: Uri, reference: Uri): Uri = proc combine*(uris: varargs[Uri]): Uri = ## Combines multiple URIs together. + ## + ## **See also:** + ## * `/ proc <#/,Uri,string>`_ for building URIs + runnableExamples: + let foo = combine(parseUri("https://nim-lang.org/blog.html"), parseUri("/install.html")) + assert foo.hostname == "nim-lang.org" + assert foo.path == "/install.html" result = uris[0] for i in 1 ..< uris.len: result = combine(result, uris[i]) proc isAbsolute*(uri: Uri): bool = - ## returns true if URI is absolute, false otherwise + ## Returns true if URI is absolute, false otherwise. + runnableExamples: + let foo = parseUri("https://nim-lang.org") + assert isAbsolute(foo) == true + let bar = parseUri("nim-lang") + assert isAbsolute(bar) == false return uri.scheme != "" and (uri.hostname != "" or uri.path != "") proc `/`*(x: Uri, path: string): Uri = - ## Concatenates the path specified to the specified URI's path. + ## Concatenates the path specified to the specified URIs path. ## - ## Contrary to the ``combine`` procedure you do not have to worry about - ## the slashes at the beginning and end of the path and URI's path + ## Contrary to the `combine proc <#combine,Uri,Uri>`_ you do not have to worry about + ## the slashes at the beginning and end of the path and URIs path ## respectively. ## - ## Examples: - ## - ## .. code-block:: - ## let foo = parseUri("http://example.com/foo/bar") / "/baz" - ## assert foo.path == "/foo/bar/baz" - ## - ## let bar = parseUri("http://example.com/foo/bar") / "baz" - ## assert bar.path == "/foo/bar/baz" - ## - ## let bar = parseUri("http://example.com/foo/bar/") / "baz" - ## assert bar.path == "/foo/bar/baz" + ## **See also:** + ## * `combine proc <#combine,Uri,Uri>`_ + runnableExamples: + let foo = parseUri("https://nim-lang.org/foo/bar") / "/baz" + assert foo.path == "/foo/bar/baz" + let bar = parseUri("https://nim-lang.org/foo/bar") / "baz" + assert bar.path == "/foo/bar/baz" + let qux = parseUri("https://nim-lang.org/foo/bar/") / "baz" + assert qux.path == "/foo/bar/baz" result = x if result.path.len == 0: @@ -348,6 +395,9 @@ proc `/`*(x: Uri, path: string): Uri = proc `$`*(u: Uri): string = ## Returns the string representation of the specified URI object. + runnableExamples: + let foo = parseUri("https://nim-lang.org") + assert $foo == "https://nim-lang.org" result = "" if u.scheme.len > 0: result.add(u.scheme) |