summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorVarriount <Varriount@users.noreply.github.com>2014-04-26 20:44:11 -0400
committerVarriount <Varriount@users.noreply.github.com>2014-04-26 20:44:11 -0400
commit2da7ad8647afe893b7c6facf6a5c77ff7c5be124 (patch)
treed4e99ac22de91f937a180c534a93099ead2c2b2d
parent8c6b1b402ea93829596b3add4c71f2d512363484 (diff)
parent6550f96e91f30cdcfae025bab9d122abab3a3900 (diff)
downloadNim-2da7ad8647afe893b7c6facf6a5c77ff7c5be124.tar.gz
Merge pull request #1139 from bbodi/devel
fix #1065
-rw-r--r--lib/pure/parseurl.nim110
-rw-r--r--lib/pure/uri.nim37
-rw-r--r--lib/pure/url.nim213
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"