mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-31 18:32:11 +00:00
better docs: uri (#10373)
This commit is contained in:
147
lib/pure/uri.nim
147
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
|
||||
@@ -24,11 +53,18 @@ proc encodeUrl*(s: string, usePlus=true): string =
|
||||
## 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:
|
||||
@@ -43,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'))
|
||||
@@ -123,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: "")
|
||||
|
||||
@@ -136,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
|
||||
@@ -174,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)
|
||||
|
||||
@@ -224,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.
|
||||
## This means that the slashes inside the base URIs path as well as reference
|
||||
## URIs 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"
|
||||
##
|
||||
## 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
|
||||
@@ -275,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:
|
||||
@@ -321,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)
|
||||
|
||||
Reference in New Issue
Block a user