better docs: uri (#10373)
This commit is contained in:
parent
4a04470450
commit
bfeade9791
1 changed files with 112 additions and 35 deletions
147
lib/pure/uri.nim
147
lib/pure/uri.nim
|
|
@ -8,6 +8,35 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
## This module implements URI parsing as specified by RFC 3986.
|
## 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
|
import strutils, parseutils
|
||||||
type
|
type
|
||||||
|
|
@ -24,11 +53,18 @@ proc encodeUrl*(s: string, usePlus=true): string =
|
||||||
## This means that characters in the set
|
## This means that characters in the set
|
||||||
## ``{'a'..'z', 'A'..'Z', '0'..'9', '-', '.', '_', '~'}`` are
|
## ``{'a'..'z', 'A'..'Z', '0'..'9', '-', '.', '_', '~'}`` are
|
||||||
## carried over to the result.
|
## 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.
|
## denotes its hexadecimal value.
|
||||||
##
|
##
|
||||||
## As a special rule, when the value of ``usePlus`` is true,
|
## 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
|
result = newStringOfCap(s.len + s.len shr 2) # assume 12% non-alnum-chars
|
||||||
let fromSpace = if usePlus: "+" else: "%20"
|
let fromSpace = if usePlus: "+" else: "%20"
|
||||||
for c in s:
|
for c in s:
|
||||||
|
|
@ -43,12 +79,19 @@ proc encodeUrl*(s: string, usePlus=true): string =
|
||||||
proc decodeUrl*(s: string, decodePlus=true): string =
|
proc decodeUrl*(s: string, decodePlus=true): string =
|
||||||
## Decodes a URL according to RFC3986.
|
## 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``,
|
## value) are converted to the character with ordinal number ``xx``,
|
||||||
## and every other character is carried over.
|
## 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.
|
## 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.} =
|
proc handleHexChar(c: char, x: var int) {.inline.} =
|
||||||
case c
|
case c
|
||||||
of '0'..'9': x = (x shl 4) or (ord(c) - ord('0'))
|
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)
|
i.inc parseUntil(uri, result.anchor, {}, i)
|
||||||
|
|
||||||
proc initUri*(): Uri =
|
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: "",
|
result = Uri(scheme: "", username: "", password: "", hostname: "", port: "",
|
||||||
path: "", query: "", anchor: "")
|
path: "", query: "", anchor: "")
|
||||||
|
|
||||||
|
|
@ -136,6 +186,16 @@ proc resetUri(uri: var Uri) =
|
||||||
|
|
||||||
proc parseUri*(uri: string, result: var Uri) =
|
proc parseUri*(uri: string, result: var Uri) =
|
||||||
## Parses a URI. The `result` variable will be cleared before.
|
## 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)
|
resetUri(result)
|
||||||
|
|
||||||
var i = 0
|
var i = 0
|
||||||
|
|
@ -174,6 +234,14 @@ proc parseUri*(uri: string, result: var Uri) =
|
||||||
|
|
||||||
proc parseUri*(uri: string): Uri =
|
proc parseUri*(uri: string): Uri =
|
||||||
## Parses a URI and returns it.
|
## 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()
|
result = initUri()
|
||||||
parseUri(uri, result)
|
parseUri(uri, result)
|
||||||
|
|
||||||
|
|
@ -224,22 +292,18 @@ proc combine*(base: Uri, reference: Uri): Uri =
|
||||||
## This uses the algorithm specified in
|
## This uses the algorithm specified in
|
||||||
## `section 5.2.2 of RFC 3986 <http://tools.ietf.org/html/rfc3986#section-5.2.2>`_.
|
## `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
|
## This means that the slashes inside the base URIs path as well as reference
|
||||||
## URI's path affect the resulting URI.
|
## URIs path affect the resulting URI.
|
||||||
##
|
##
|
||||||
## For building URIs you may wish to use \`/\` instead.
|
## **See also:**
|
||||||
##
|
## * `/ proc <#/,Uri,string>`_ for building URIs
|
||||||
## Examples:
|
runnableExamples:
|
||||||
##
|
let foo = combine(parseUri("https://nim-lang.org/foo/bar"), parseUri("/baz"))
|
||||||
## .. code-block::
|
assert foo.path == "/baz"
|
||||||
## let foo = combine(parseUri("http://example.com/foo/bar"), parseUri("/baz"))
|
let bar = combine(parseUri("https://nim-lang.org/foo/bar"), parseUri("baz"))
|
||||||
## assert foo.path == "/baz"
|
assert bar.path == "/foo/baz"
|
||||||
##
|
let qux = combine(parseUri("https://nim-lang.org/foo/bar/"), parseUri("baz"))
|
||||||
## let bar = combine(parseUri("http://example.com/foo/bar"), parseUri("baz"))
|
assert qux.path == "/foo/bar/baz"
|
||||||
## assert bar.path == "/foo/baz"
|
|
||||||
##
|
|
||||||
## let bar = combine(parseUri("http://example.com/foo/bar/"), parseUri("baz"))
|
|
||||||
## assert bar.path == "/foo/bar/baz"
|
|
||||||
|
|
||||||
template setAuthority(dest, src): untyped =
|
template setAuthority(dest, src): untyped =
|
||||||
dest.hostname = src.hostname
|
dest.hostname = src.hostname
|
||||||
|
|
@ -275,32 +339,42 @@ proc combine*(base: Uri, reference: Uri): Uri =
|
||||||
|
|
||||||
proc combine*(uris: varargs[Uri]): Uri =
|
proc combine*(uris: varargs[Uri]): Uri =
|
||||||
## Combines multiple URIs together.
|
## 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]
|
result = uris[0]
|
||||||
for i in 1 ..< uris.len:
|
for i in 1 ..< uris.len:
|
||||||
result = combine(result, uris[i])
|
result = combine(result, uris[i])
|
||||||
|
|
||||||
proc isAbsolute*(uri: Uri): bool =
|
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 != "")
|
return uri.scheme != "" and (uri.hostname != "" or uri.path != "")
|
||||||
|
|
||||||
proc `/`*(x: Uri, path: string): Uri =
|
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
|
## 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 URI's path
|
## the slashes at the beginning and end of the path and URIs path
|
||||||
## respectively.
|
## respectively.
|
||||||
##
|
##
|
||||||
## Examples:
|
## **See also:**
|
||||||
##
|
## * `combine proc <#combine,Uri,Uri>`_
|
||||||
## .. code-block::
|
runnableExamples:
|
||||||
## let foo = parseUri("http://example.com/foo/bar") / "/baz"
|
let foo = parseUri("https://nim-lang.org/foo/bar") / "/baz"
|
||||||
## assert foo.path == "/foo/bar/baz"
|
assert foo.path == "/foo/bar/baz"
|
||||||
##
|
let bar = parseUri("https://nim-lang.org/foo/bar") / "baz"
|
||||||
## let bar = parseUri("http://example.com/foo/bar") / "baz"
|
assert bar.path == "/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"
|
||||||
## let bar = parseUri("http://example.com/foo/bar/") / "baz"
|
|
||||||
## assert bar.path == "/foo/bar/baz"
|
|
||||||
result = x
|
result = x
|
||||||
|
|
||||||
if result.path.len == 0:
|
if result.path.len == 0:
|
||||||
|
|
@ -321,6 +395,9 @@ proc `/`*(x: Uri, path: string): Uri =
|
||||||
|
|
||||||
proc `$`*(u: Uri): string =
|
proc `$`*(u: Uri): string =
|
||||||
## Returns the string representation of the specified URI object.
|
## Returns the string representation of the specified URI object.
|
||||||
|
runnableExamples:
|
||||||
|
let foo = parseUri("https://nim-lang.org")
|
||||||
|
assert $foo == "https://nim-lang.org"
|
||||||
result = ""
|
result = ""
|
||||||
if u.scheme.len > 0:
|
if u.scheme.len > 0:
|
||||||
result.add(u.scheme)
|
result.add(u.scheme)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue