about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/client.nim2
-rw-r--r--src/html/dom.nim46
-rw-r--r--src/io/buffer.nim44
-rw-r--r--src/io/loader.nim20
4 files changed, 77 insertions, 35 deletions
diff --git a/src/client.nim b/src/client.nim
index bba2911d..dcb42c5c 100644
--- a/src/client.nim
+++ b/src/client.nim
@@ -107,7 +107,7 @@ proc gotoUrl(client: Client, url: Url, click = none(ClickAction), prevurl = none
       let page = if click.isnone:
         client.loader.getPage(url)
       else:
-        client.loader.getPage(url, click.get.smethod, click.get.mimetype, click.get.body, click.get.multipart)
+        client.loader.getPage(url, click.get.httpmethod, click.get.mimetype, click.get.body, click.get.multipart)
       if page.s != nil:
         if newbuf:
           client.addBuffer()
diff --git a/src/html/dom.nim b/src/html/dom.nim
index 51bec09a..3bbe07b7 100644
--- a/src/html/dom.nim
+++ b/src/html/dom.nim
@@ -9,6 +9,15 @@ import types/url
 import utils/twtstr
 
 type
+  FormMethod* = enum
+    FORM_METHOD_GET, FORM_METHOD_POST, FORM_METHOD_DIALOG
+
+  FormEncodingType* = enum
+    FORM_ENCODING_TYPE_URLENCODED = "application/x-www-form-urlencoded",
+    FORM_ENCODING_TYPE_MULTIPART = "multipart/form-data",
+    FORM_ENCODING_TYPE_TEXT_PLAIN = "text/plain"
+
+type
   EventTarget* = ref EventTargetObj
   EventTargetObj = object of RootObj
 
@@ -348,27 +357,48 @@ func action*(element: Element): string =
         return element.form.attr("action")
   return ""
 
-func enctype*(element: Element): string =
+func enctype*(element: Element): FormEncodingType =
   if element.isSubmitButton():
     if element.attrb("formenctype"):
-      return element.attr("formenctype")
+      return case element.attr("formenctype").tolower()
+      of "application/x-www-form-urlencoded": FORM_ENCODING_TYPE_URLENCODED
+      of "multipart/form-data": FORM_ENCODING_TYPE_MULTIPART
+      of "text/plain": FORM_ENCODING_TYPE_TEXT_PLAIN
+      else: FORM_ENCODING_TYPE_URLENCODED
+
   if element.tagType == TAG_INPUT:
     let element = HTMLInputElement(element)
     if element.form != nil:
       if element.form.attrb("enctype"):
-        return element.form.attr("enctype")
-  return "application/x-www-form-urlencoded"
+        return case element.attr("enctype").tolower()
+        of "application/x-www-form-urlencoded": FORM_ENCODING_TYPE_URLENCODED
+        of "multipart/form-data": FORM_ENCODING_TYPE_MULTIPART
+        of "text/plain": FORM_ENCODING_TYPE_TEXT_PLAIN
+        else: FORM_ENCODING_TYPE_URLENCODED
 
-func smethod*(element: Element): string =
+  return FORM_ENCODING_TYPE_URLENCODED
+
+func formmethod*(element: Element): FormMethod =
   if element.isSubmitButton():
     if element.attrb("formmethod"):
-      return element.attr("formmethod")
+      return case element.attr("formmethod").tolower()
+      of "get": FORM_METHOD_GET
+      of "post": FORM_METHOD_POST
+      of "dialog": FORM_METHOD_DIALOG
+      else: FORM_METHOD_GET
+
+  # has form (TODO not only input should be included)
   if element.tagType == TAG_INPUT:
     let element = HTMLInputElement(element)
     if element.form != nil:
       if element.form.attrb("method"):
-        return element.form.attr("method")
-  return "GET"
+        return case element.form.attr("method").tolower()
+        of "get": FORM_METHOD_GET
+        of "post": FORM_METHOD_POST
+        of "dialog": FORM_METHOD_DIALOG
+        else: FORM_METHOD_GET
+
+  return FORM_METHOD_GET
 
 func target*(element: Element): string =
   if element.attrb("target"):
diff --git a/src/io/buffer.nim b/src/io/buffer.nim
index 8140ce7b..7356b084 100644
--- a/src/io/buffer.nim
+++ b/src/io/buffer.nim
@@ -824,7 +824,7 @@ proc displayStatusMessage*(buffer: Buffer) =
 type
   ClickAction* = object
     url*: string
-    smethod*: string
+    httpmethod*: HttpMethod
     mimetype*: string
     body*: string
     multipart*: MultipartData
@@ -939,9 +939,15 @@ proc submitForm(form: HTMLFormElement, submitter: Element): Option[ClickAction]
   var parsedaction = url.get
   let scheme = parsedaction.scheme
   let enctype = submitter.enctype()
-  let smethod = submitter.smethod().toupper()
-  if smethod notin ["GET", "POST"]:
-    return none(ClickAction) #TODO this shouldn't be possible
+  let formmethod = submitter.formmethod()
+  if formmethod == FORM_METHOD_DIALOG:
+    #TODO
+    return none(ClickAction)
+  let httpmethod = if formmethod == FORM_METHOD_GET:
+    HttpGet
+  else:
+    assert formmethod == FORM_METHOD_POST
+    HttpPost
 
   let target = if submitter.isSubmitButton() and submitter.attrb("formtarget"):
     submitter.attr("formtarget")
@@ -952,41 +958,41 @@ proc submitForm(form: HTMLFormElement, submitter: Element): Option[ClickAction]
   template mutateActionUrl() =
     let query = serializeApplicationXWWFormUrlEncoded(entrylist)
     parsedaction.query = query.some
-    return ClickAction(url: $parsedaction, smethod: smethod).some
+    return ClickAction(url: $parsedaction, httpmethod: httpmethod).some
 
   template submitAsEntityBody() =
     var body: string
     var mimetype: string
     var multipart: MultipartData
     case enctype
-    of "application/x-www-form-urlencoded":
+    of FORM_ENCODING_TYPE_URLENCODED:
       body = serializeApplicationXWWFormUrlEncoded(entrylist)
-      mimeType = enctype
-    of "multipart/form-data":
+      mimeType = $enctype
+    of FORM_ENCODING_TYPE_MULTIPART:
       multipart = serializeMultipartFormData(entrylist) 
-      #mime type set by httpclient
-    of "text/plain":
+      mimetype = $enctype
+    of FORM_ENCODING_TYPE_TEXT_PLAIN:
       body = serializePlainTextFormData(entrylist)
-      mimetype = enctype
-    else:
-      return none(ClickAction) #TODO this shouldn't be possible
-    return ClickAction(url: $parsedaction, smethod: smethod, body: body, mimetype: mimetype, multipart: multipart).some
+      mimetype = $enctype
+    return ClickAction(url: $parsedaction, httpmethod: httpmethod, body: body, mimetype: mimetype, multipart: multipart).some
 
   template getActionUrl() =
     return ClickAction(url: $parsedaction).some
 
   case scheme
   of "http", "https":
-    if smethod == "GET":
+    if formmethod == FORM_METHOD_GET:
       mutateActionUrl
-    elif smethod == "POST":
+    else:
+      assert formmethod == FORM_METHOD_POST
       submitAsEntityBody
   of "ftp":
     getActionUrl
   of "data":
-    if smethod == "GET":
+    if formmethod == FORM_METHOD_GET:
       mutateActionUrl
-    elif smethod == "POST":
+    else:
+      assert formmethod == FORM_METHOD_POST
       getActionUrl
 
 proc click*(buffer: Buffer): Option[ClickAction] =
@@ -994,7 +1000,7 @@ proc click*(buffer: Buffer): Option[ClickAction] =
   if clickable != nil:
     case clickable.tagType
     of TAG_A:
-      return ClickAction(url: HTMLAnchorElement(clickable).href).some
+      return ClickAction(url: HTMLAnchorElement(clickable).href, httpmethod: HttpGet).some
     of TAG_INPUT:
       let input = HTMLInputElement(clickable)
       case input.inputType
diff --git a/src/io/loader.nim b/src/io/loader.nim
index 4bd365a8..4a10d336 100644
--- a/src/io/loader.nim
+++ b/src/io/loader.nim
@@ -14,11 +14,19 @@ type
     s*: Stream
     contenttype*: string
 
+const DefaultHeaders = {
+  "User-Agent": "chawan",
+  "Accept": "text/html", "text/*;q=0.5",
+  "Accept-Language": "en;q=1.0",
+  "Pragma": "no-cache",
+  "Cache-control": "no-cache",
+}
+
 proc newFileLoader*(): FileLoader =
   new(result)
   result.http = newHttpClient()
 
-proc getPage*(loader: FileLoader, url: Url, smethod: string = "GET", mimetype = "", body: string = "", multipart: MultipartData = nil): LoadResult =
+proc getPage*(loader: FileLoader, url: Url, smethod: HttpMethod = HttpGet, mimetype = "", body: string = "", multipart: MultipartData = nil): LoadResult =
   if url.scheme == "file":
     when defined(windows) or defined(OS2) or defined(DOS):
       let path = url.path.serialize_unicode_windows()
@@ -27,12 +35,10 @@ proc getPage*(loader: FileLoader, url: Url, smethod: string = "GET", mimetype =
     result.contenttype = guessContentType(path)
     result.s = newFileStream(path, fmRead)
   elif url.scheme == "http" or url.scheme == "https":
-    let requestheaders = newHttpHeaders({ "User-Agent": "chawan", "Content-Type": mimetype}, true)
-    let requestmethod = if smethod == "":
-      "GET"
-    else:
-      smethod
-    let resp = loader.http.request(url.serialize(true), requestmethod, body, requestheaders, multipart)
+    var requestheaders = newHttpHeaders(DefaultHeaders, true)
+    if mimetype != "":
+      requestheaders["Content-Type"] = mimetype 
+    let resp = loader.http.request(url.serialize(true), smethod, body, requestheaders, multipart)
     let ct = resp.contentType()
     if ct != "":
       result.contenttype = ct.until(';')