diff options
-rw-r--r-- | src/client.nim | 2 | ||||
-rw-r--r-- | src/html/dom.nim | 46 | ||||
-rw-r--r-- | src/io/buffer.nim | 44 | ||||
-rw-r--r-- | src/io/loader.nim | 20 |
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(';') |