diff options
author | Varriount <Varriount@users.noreply.github.com> | 2014-04-26 20:44:11 -0400 |
---|---|---|
committer | Varriount <Varriount@users.noreply.github.com> | 2014-04-26 20:44:11 -0400 |
commit | 2da7ad8647afe893b7c6facf6a5c77ff7c5be124 (patch) | |
tree | d4e99ac22de91f937a180c534a93099ead2c2b2d | |
parent | 8c6b1b402ea93829596b3add4c71f2d512363484 (diff) | |
parent | 6550f96e91f30cdcfae025bab9d122abab3a3900 (diff) | |
download | Nim-2da7ad8647afe893b7c6facf6a5c77ff7c5be124.tar.gz |
Merge pull request #1139 from bbodi/devel
fix #1065
-rw-r--r-- | lib/pure/parseurl.nim | 110 | ||||
-rw-r--r-- | lib/pure/uri.nim | 37 | ||||
-rw-r--r-- | lib/pure/url.nim | 213 |
3 files changed, 213 insertions, 147 deletions
diff --git a/lib/pure/parseurl.nim b/lib/pure/parseurl.nim deleted file mode 100644 index 357d1df0f..000000000 --- a/lib/pure/parseurl.nim +++ /dev/null @@ -1,110 +0,0 @@ -# -# -# Nimrod's Runtime Library -# (c) Copyright 2014 Dominik Picheta -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -## Parses & constructs URLs. -## -## **Note**: This module will be deprecated in the future and merged into a -## new ``url`` module. - -import strutils - -type - TUrl* = tuple[ ## represents a *Uniform Resource Locator* (URL) - ## any optional component is "" if it does not exist - scheme, username, password, - hostname, port, path, query, anchor: string] - -proc parseUrl*(url: string): TUrl = - var i = 0 - - var scheme, username, password: string = "" - var hostname, port, path, query, anchor: string = "" - - var temp = "" - - if url[i] != '/': # url isn't a relative path - while True: - # Scheme - if url[i] == ':': - if url[i+1] == '/' and url[i+2] == '/': - scheme = temp - temp.setlen(0) - inc(i, 3) # Skip the // - # Authority(username, password) - if url[i] == '@': - username = temp - let colon = username.find(':') - if colon >= 0: - password = username.substr(colon+1) - username = username.substr(0, colon-1) - temp.setlen(0) - inc(i) #Skip the @ - # hostname(subdomain, domain, port) - if url[i] == '/' or url[i] == '\0': - hostname = temp - let colon = hostname.find(':') - if colon >= 0: - port = hostname.substr(colon+1) - hostname = hostname.substr(0, colon-1) - - temp.setlen(0) - break - - temp.add(url[i]) - inc(i) - - if url[i] == '/': inc(i) # Skip the '/' - # Path - while True: - if url[i] == '?': - path = temp - temp.setlen(0) - if url[i] == '#': - if temp[0] == '?': - query = temp - else: - path = temp - temp.setlen(0) - - if url[i] == '\0': - if temp[0] == '?': - query = temp - elif temp[0] == '#': - anchor = temp - else: - path = temp - break - - temp.add(url[i]) - inc(i) - - return (scheme, username, password, hostname, port, path, query, anchor) - -proc `$`*(u: TUrl): string = - ## turns the URL `u` into its string representation. - result = "" - if u.scheme.len > 0: - result.add(u.scheme) - result.add("://") - if u.username.len > 0: - result.add(u.username) - if u.password.len > 0: - result.add(":") - result.add(u.password) - result.add("@") - result.add(u.hostname) - if u.port.len > 0: - result.add(":") - result.add(u.port) - if u.path.len > 0: - result.add("/") - result.add(u.path) - result.add(u.query) - result.add(u.anchor) - diff --git a/lib/pure/uri.nim b/lib/pure/uri.nim deleted file mode 100644 index ee1226a35..000000000 --- a/lib/pure/uri.nim +++ /dev/null @@ -1,37 +0,0 @@ -# -# -# Nimrod's Runtime Library -# (c) Copyright 2014 Dominik Picheta -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -## **Note**: This module will be deprecated in the future and merged into a -## new ``url`` module. - -import strutils -type - TUrl* = distinct string - -proc `$`*(url: TUrl): string = return string(url) - -proc `/`*(a, b: TUrl): TUrl = - ## Joins two URLs together, separating them with / if needed. - 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 = TUrl(urlS) - -proc add*(url: var TUrl, a: TUrl) = - ## Appends url to url. - url = url / a - -when isMainModule: - assert($("http://".TUrl / "localhost:5000".TUrl) == "http://localhost:5000") diff --git a/lib/pure/url.nim b/lib/pure/url.nim new file mode 100644 index 000000000..fa7533886 --- /dev/null +++ b/lib/pure/url.nim @@ -0,0 +1,213 @@ +# +# +# Nimrod's Runtime Library +# (c) Copyright 2014 Dominik Picheta +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## Parses & constructs URLs. + +import strutils + +type + TUrl* = tuple[ ## represents a *Uniform Resource Locator* (URL) + ## any optional component is "" if it does not exist + scheme, username, password, + hostname, port, path, query, anchor: string] + + +proc skip(i: var int, skippedChars: string) = + inc(i, skippedChars.len) + +proc readScheme(url: var TUrl, temp: string) = + url.scheme = temp + +proc readAuthority(url: var TUrl, temp: string) = + let colon = temp.find(':') + if colon >= 0: + url.password = temp.substr(colon+1) + url.username = temp.substr(0, colon-1) + +proc readHostAndPort(url: var TUrl, temp: string) = + let colon = temp.find(':') + if colon >= 0: + url.port = temp.substr(colon+1) + url.hostname = temp.substr(0, colon-1) + +proc readUntilPath(self: var TUrl, url: string): int = + var temp = "" + var i = 0 + let relative = url[i] == '/' + if not relative: + while True: + if url[i] == ':': + if url[i+1] == '/' and url[i+2] == '/': + self.readScheme(temp) + i.skip("://") + temp.setlen(0) + if url[i] == '@': + self.readAuthority(temp) + i.skip("@") + temp.setlen(0) + + if url[i] == '/' or url[i] == '\0': + self.readHostAndPort(temp) + temp.setlen(0) + break + + temp.add(url[i]) + inc(i) + + if url[i] == '/': + i.skip("/") + return i + +proc readPath(url: var TUrl, path: string) = + var temp = "" + var i = 0 + while True: + if path[i] == '?': + url.path = temp + temp.setlen(0) + if path[i] == '#': + if temp[0] == '?': + url.query = temp + else: + url.path = temp + temp.setlen(0) + + if path[i] == '\0': + if temp[0] == '?': + url.query = temp + elif temp[0] == '#': + url.anchor = temp + else: + url.path = temp + break + temp.add(path[i]) + inc(i) + +proc parseUrl*(url: string): TUrl = + result.scheme = "" + result.username = "" + result.password = "" + result.hostname = "" + result.port = "" + result.path = "" + result.query = "" + result.anchor = "" + + let lastIndex = result.readUntilPath(url) + let path = url[lastIndex..url.len] + result.readPath(path) + + +proc `$`*(u: TUrl): string = + ## turns the URL `u` into its string representation. + result = "" + if u.scheme.len > 0: + result.add(u.scheme) + result.add("://") + if u.username.len > 0: + result.add(u.username) + if u.password.len > 0: + result.add(":") + result.add(u.password) + result.add("@") + result.add(u.hostname) + if u.port.len > 0: + result.add(":") + result.add(u.port) + if u.path.len > 0: + result.add("/") + result.add(u.path) + result.add(u.query) + result.add(u.anchor) + +proc nvl(a: string, b: string): string = + if a == "": + return b + return a + +proc `/`*(a, b: TUrl): TUrl = + result.scheme = nvl(a.scheme, b.scheme) + result.username = nvl(a.username, b.username) + result.password = nvl(a.password, b.password) + result.hostname = nvl(a.hostname, b.hostname) + result.port = nvl(a.port, b.port) + result.path = nvl(a.path, b.path) + result.query = nvl(a.query, b.query) + result.anchor = nvl(a.anchor, b.anchor) + +when isMainModule: + import unittest + + test "parse full URL": + let url = parseUrl("http://localhost:5000/path?message1=Nimrod&message2=+is+cool!#anchor") + check url.username == "" + check url.password == "" + check url.scheme == "http" + check url.hostname == "localhost" + check url.port == "5000" + check url.path == "path" + check url.query == "?message1=Nimrod&message2=+is+cool!" + check url.anchor == "#anchor" + + test "parse full URL with username and password": + let url = parseUrl("http://username:password@localhost:5000/path?message1=Nimrod&message2=+is+cool!#anchor") + check url.username == "username" + check url.password == "password" + check url.scheme == "http" + check url.hostname == "localhost" + check url.port == "5000" + check url.path == "path" + check url.query == "?message1=Nimrod&message2=+is+cool!" + check url.anchor == "#anchor" + + test "parse URL fragment localhost:5000": + let url = parseUrl("localhost:5000") + check url.username == "" + check url.password == "" + check url.scheme == "" + check url.hostname == "localhost" + check url.port == "5000" + check url.path == "" + check url.query == "" + check url.anchor == "" + + test "parse URL fragment: /path?message1=Nimrod&message2=+is+cool!#anchor": + let url = parseUrl("/path?message1=Nimrod&message2=+is+cool!#anchor") + check url.username == "" + check url.password == "" + check url.scheme == "" + check url.hostname == "" + check url.port == "" + check url.path == "path" + check url.query == "?message1=Nimrod&message2=+is+cool!" + check url.anchor == "#anchor" + + test "parse URL fragment: http://": + let url = parseUrl("http://") + check url.scheme == "http" + check url.username == "" + check url.password == "" + check url.hostname == "" + check url.port == "" + check url.path == "" + check url.query == "" + check url.anchor == "" + + test "url concatenation": + let url1 = parseUrl("http://localhost:5000") + let url2 = parseUrl("/path?message1=Nimrod&message2=+is+cool!#anchor") + let url = url1 / url2 + check url.username == "" + check url.password == "" + check url.scheme == "http" + check url.hostname == "localhost" + check url.port == "5000" + check url.path == "path" + check url.query == "?message1=Nimrod&message2=+is+cool!" + check url.anchor == "#anchor" |