From 6a990cef8eac9bf11d785d942873f9a5fa614585 Mon Sep 17 00:00:00 2001 From: bptato Date: Thu, 18 Aug 2022 21:08:29 +0200 Subject: Fix request error handling --- src/client.nim | 51 ++++++++++++++++++++++++--------------------------- src/io/buffer.nim | 5 +++-- src/io/http.nim | 17 +++++++++++------ src/io/loader.nim | 19 ++++++++----------- src/io/request.nim | 1 + 5 files changed, 47 insertions(+), 46 deletions(-) diff --git a/src/client.nim b/src/client.nim index 202090ca..561e821c 100644 --- a/src/client.nim +++ b/src/client.nim @@ -175,33 +175,30 @@ var g_client: Client proc gotoUrl(client: Client, request: Request, prevurl = none(Url), force = false, ctype = "") = setControlCHook(proc() {.noconv.} = raise newException(InterruptError, "Interrupted")) - if force or prevurl.isnone or not prevurl.get.equals(request.url, true): - try: - let page = client.loader.getPage(request) - client.needsauth = page.status == 401 # Unauthorized - client.redirecturl = page.redirect - var buf: string - page.s.sread(buf) - if buf != "": #TODO what about pages with an empty body? - client.addBuffer() - g_client = client - setControlCHook(proc() {.noconv.} = - if g_client.buffer.prev != nil or g_client.buffer.next != nil: - g_client.discardBuffer() - interruptError()) - client.buffer.contenttype = if ctype != "": ctype else: page.contenttype - client.buffer.istream = newStringStream() - while true: - client.buffer.istream.write(buf) - page.s.sread(buf) - if buf == "": break - client.buffer.istream.setPosition(0) - client.buffer.location = request.url - client.setupBuffer() - else: - loadError("Couldn't load " & $request.url) - except IOError, OSError: - loadError("Couldn't load " & $request.url) + if force or prevurl.isnone or not prevurl.get.equals(request.url, true) or + prevurl.get.equals(request.url) or request.httpmethod != HTTP_GET: + let page = client.loader.doRequest(request) + client.needsauth = page.status == 401 # Unauthorized + client.redirecturl = page.redirect + if page.s != nil: + client.addBuffer() + g_client = client + setControlCHook(proc() {.noconv.} = + if g_client.buffer.prev != nil or g_client.buffer.next != nil: + g_client.discardBuffer() + interruptError()) + client.buffer.contenttype = if ctype != "": ctype else: page.contenttype + client.buffer.istream = newStringStream() + while true: + var buf: string + page.s.sread(buf) + if buf == "": break + client.buffer.istream.write(buf) + client.buffer.istream.setPosition(0) + client.buffer.location = request.url + client.setupBuffer() + else: + loadError("Couldn't load " & $request.url & " (" & $page.res & ")") elif client.buffer != nil and prevurl.issome and prevurl.get.equals(request.url, true): if client.buffer.hasAnchor(request.url.anchor): client.dupeBuffer(request.url.some) diff --git a/src/io/buffer.nim b/src/io/buffer.nim index 13add309..bcbaef2d 100644 --- a/src/io/buffer.nim +++ b/src/io/buffer.nim @@ -846,14 +846,15 @@ proc loadResources(buffer: Buffer, document: Document) = if url.issome: let url = url.get if url.scheme == buffer.location.scheme: - let fs = buffer.loader.getPage(newRequest(url)) + let fs = buffer.loader.doRequest(newRequest(url)) if fs.s != nil and fs.contenttype == "text/css": var res = newStringStream() while true: var s: string - buffer.istream.sread(s) + fs.s.sread(s) if s == "": break res.write(s) + res.setPosition(0) let sheet = parseStylesheet(res) elem.sheet = sheet diff --git a/src/io/http.nim b/src/io/http.nim index 221648f3..cda70bf1 100644 --- a/src/io/http.nim +++ b/src/io/http.nim @@ -1,6 +1,7 @@ import options import streams import strutils +import tables import bindings/curl import io/request @@ -33,6 +34,7 @@ proc curlWriteHeader(p: cstring, size: csize_t, nitems: csize_t, userdata: point let headers = cast[HeaderResult](userdata) if not headers.statusline: headers.statusline = true + headers.ostream.swrite(int(CURLE_OK)) var status: int headers.curl.getinfo(CURLINFO_RESPONSE_CODE, addr status) headers.ostream.swrite(status) @@ -45,8 +47,9 @@ proc curlWriteHeader(p: cstring, size: csize_t, nitems: csize_t, userdata: point headers.ostream.swrite(headers.headers.getOrDefault("Content-Type").until(';')) var urlp: cstring headers.curl.getinfo(CURLINFO_REDIRECT_URL, addr urlp) - if urlp != nil: - headers.ostream.swrite(parseUrl($urlp, some(headers.request.url))) + if "Location" in headers.headers.table: + let location = headers.headers.table["Location"][0] + headers.ostream.swrite(parseUrl(location, some(headers.request.url))) else: headers.ostream.swrite(none(Url)) return nitems @@ -117,10 +120,12 @@ proc loadHttp*(request: Request, ostream: Stream) = curl.setopt(CURLOPT_HTTPHEADER, slist) let res = curl_easy_perform(curl) - if res == CURLE_OK: # TODO handle errors - discard - ostream.swrite("") - ostream.flush() + if res == CURLE_OK: + ostream.swrite("") + ostream.flush() + else: + ostream.swrite(int(res)) + ostream.flush() curl_easy_cleanup(curl) if mime != nil: diff --git a/src/io/loader.nim b/src/io/loader.nim index 1fb6e7b7..4adf64bc 100644 --- a/src/io/loader.nim +++ b/src/io/loader.nim @@ -41,12 +41,10 @@ proc loadFile(url: Url, ostream: Stream) = let path = url.path.serialize_unicode() let istream = newFileStream(path, fmRead) if istream == nil: - ostream.swrite(404) # file not found - ostream.swrite("") - ostream.swrite(none(Url)) - ostream.swrite("") + ostream.swrite(1) ostream.flush() else: + ostream.swrite(0) ostream.swrite(200) # ok ostream.swrite(guessContentType(path)) ostream.swrite(none(Url)) @@ -98,10 +96,12 @@ proc doRequest*(loader: FileLoader, request: Request): LoadResult = if loader.istream != nil: loader.istream.swrite(request) loader.istream.flush() - loader.ostream.sread(result.status) - loader.ostream.sread(result.contenttype) - loader.ostream.sread(result.redirect) - result.s = loader.ostream + loader.ostream.sread(result.res) + if result.res == 0: + loader.ostream.sread(result.status) + loader.ostream.sread(result.contenttype) + loader.ostream.sread(result.redirect) + result.s = loader.ostream else: eprint "Error: no loader process" quit(1) @@ -147,6 +147,3 @@ proc newFileLoader*(defaultHeaders: HeaderList): FileLoader = proc newFileLoader*(): FileLoader = newFileLoader(DefaultHeaders) - -proc getPage*(loader: FileLoader, request: Request): LoadResult = - loader.doRequest(request) diff --git a/src/io/request.nim b/src/io/request.nim index 68706c49..5e62dbc4 100644 --- a/src/io/request.nim +++ b/src/io/request.nim @@ -26,6 +26,7 @@ type LoadResult* = object s*: Stream + res*: int contenttype*: string status*: int headers*: HeaderList -- cgit 1.4.1-2-gfad0