about summary refs log tree commit diff stats
path: root/src/loader/response.nim
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-11-24 17:24:00 +0100
committerbptato <nincsnevem662@gmail.com>2024-11-24 17:24:00 +0100
commite10fab72faa22b1eb17206bc13cc518f9fde7c26 (patch)
tree079ef7ea9abe4b01e25be9f662f07ca884c6642f /src/loader/response.nim
parent104569343acf8922751578ab4ff41bf003ad1147 (diff)
downloadchawan-e10fab72faa22b1eb17206bc13cc518f9fde7c26.tar.gz
loader/* -> server
one less mystery
Diffstat (limited to 'src/loader/response.nim')
-rw-r--r--src/loader/response.nim237
1 files changed, 0 insertions, 237 deletions
diff --git a/src/loader/response.nim b/src/loader/response.nim
deleted file mode 100644
index bdf81a10..00000000
--- a/src/loader/response.nim
+++ /dev/null
@@ -1,237 +0,0 @@
-import std/strutils
-import std/tables
-
-import chagashi/charset
-import chagashi/decoder
-import io/dynstream
-import io/promise
-import loader/headers
-import loader/request
-import monoucha/javascript
-import monoucha/jserror
-import monoucha/quickjs
-import monoucha/tojs
-import types/blob
-import types/opt
-import types/referrer
-import types/url
-import utils/mimeguess
-import utils/twtstr
-
-type
-  ResponseType* = enum
-    rtDefault = "default"
-    rtBasic = "basic"
-    rtCors = "cors"
-    rtError = "error"
-    rtOpaque = "opaque"
-    rtOpaquedirect = "opaqueredirect"
-
-  ResponseFlag* = enum
-    rfAborted
-
-  Response* = ref object
-    responseType* {.jsget: "type".}: ResponseType
-    res*: int
-    body*: SocketStream
-    bodyUsed* {.jsget.}: bool
-    status* {.jsget.}: uint16
-    headers* {.jsget.}: Headers
-    url*: URL #TODO should be urllist?
-    unregisterFun*: proc()
-    resumeFun*: proc(outputId: int)
-    internalMessage*: string # should NOT be exposed to JS!
-    outputId*: int
-    onRead*: proc(response: Response) {.nimcall.}
-    onFinish*: proc(response: Response; success: bool) {.nimcall.}
-    opaque*: RootRef
-    flags*: set[ResponseFlag]
-
-  FetchPromise* = Promise[JSResult[Response]]
-
-jsDestructor(Response)
-
-proc newResponse*(res: int; request: Request; stream: SocketStream;
-    outputId: int; status: uint16): Response =
-  return Response(
-    res: res,
-    url: request.url,
-    body: stream,
-    outputId: outputId,
-    status: status
-  )
-
-func makeNetworkError*(): Response {.jsstfunc: "Response.error".} =
-  #TODO use "create" function
-  return Response(
-    res: 0,
-    responseType: rtError,
-    status: 0,
-    headers: newHeaders(hgImmutable),
-    bodyUsed: true
-  )
-
-proc newFetchTypeError*(): JSError =
-  return newTypeError("NetworkError when attempting to fetch resource")
-
-func sok(response: Response): bool {.jsfget: "ok".} =
-  return response.status in 200u16 .. 299u16
-
-func surl*(response: Response): string {.jsfget: "url".} =
-  if response.responseType == rtError or response.url == nil:
-    return ""
-  return $response.url
-
-#TODO: this should be a property of body
-proc close*(response: Response) {.jsfunc.} =
-  response.bodyUsed = true
-  if response.unregisterFun != nil:
-    response.unregisterFun()
-    response.unregisterFun = nil
-  if response.body != nil:
-    response.body.sclose()
-    response.body = nil
-
-func getCharset*(this: Response; fallback: Charset): Charset =
-  this.headers.table.withValue("Content-Type", p):
-    let header = p[][0].toLowerAscii()
-    let cs = header.getContentTypeAttr("charset").getCharset()
-    if cs != CHARSET_UNKNOWN:
-      return cs
-  return fallback
-
-func getContentType*(this: Response; fallback = "application/octet-stream"):
-    string =
-  this.headers.table.withValue("Content-Type", p):
-    return p[][0].untilLower(';').strip()
-  # also use DefaultGuess for container, so that local mime.types cannot
-  # override buffer mime.types
-  return DefaultGuess.guessContentType(this.url.pathname, fallback)
-
-func getContentLength*(this: Response): int64 =
-  this.headers.table.withValue("Content-Length", p):
-    for x in p[]:
-      let u = parseUInt64(x.strip(), allowSign = false)
-      if u.isSome and u.get <= uint64(int64.high):
-        return int64(u.get)
-  return -1
-
-func getReferrerPolicy*(this: Response): Option[ReferrerPolicy] =
-  this.headers.table.withValue("Referrer-Policy", p):
-    return strictParseEnum[ReferrerPolicy](p[][0])
-
-proc resume*(response: Response) =
-  response.resumeFun(response.outputId)
-  response.resumeFun = nil
-
-type TextOpaque = ref object of RootObj
-  buf: string
-  bodyRead: Promise[JSResult[string]]
-
-const BufferSize = 4096
-
-proc onReadText(response: Response) =
-  let opaque = TextOpaque(response.opaque)
-  while true:
-    let olen = opaque.buf.len
-    try:
-      opaque.buf.setLen(olen + BufferSize)
-      let n = response.body.recvData(addr opaque.buf[olen], BufferSize)
-      opaque.buf.setLen(olen + n)
-      if n == 0:
-        break
-    except ErrorAgain:
-      opaque.buf.setLen(olen)
-      break
-
-proc onFinishText(response: Response; success: bool) =
-  let opaque = TextOpaque(response.opaque)
-  let bodyRead = opaque.bodyRead
-  if success:
-    let charset = response.getCharset(CHARSET_UTF_8)
-    bodyRead.resolve(JSResult[string].ok(opaque.buf.decodeAll(charset)))
-  else:
-    bodyRead.resolve(JSResult[string].err(newFetchTypeError()))
-
-proc text*(response: Response): Promise[JSResult[string]] {.jsfunc.} =
-  if response.body == nil:
-    return newResolvedPromise(JSResult[string].ok(""))
-  if response.bodyUsed:
-    let err = newTypeError("Body has already been consumed")
-    return newResolvedPromise(JSResult[string].err(err))
-  let opaque = TextOpaque(bodyRead: Promise[JSResult[string]]())
-  response.opaque = opaque
-  response.onRead = onReadText
-  response.onFinish = onFinishText
-  response.bodyUsed = true
-  response.resume()
-  return opaque.bodyRead
-
-type BlobOpaque = ref object of RootObj
-  p: pointer
-  len: int
-  size: int
-  bodyRead: Promise[JSResult[Blob]]
-  contentType: string
-
-proc onReadBlob(response: Response) =
-  let opaque = BlobOpaque(response.opaque)
-  while true:
-    try:
-      if opaque.len + BufferSize > opaque.size:
-        opaque.size *= 2
-        opaque.p = realloc(opaque.p, opaque.size)
-      let p = cast[ptr UncheckedArray[uint8]](opaque.p)
-      let diff = opaque.size - opaque.len
-      let n = response.body.recvData(addr p[opaque.len], diff)
-      opaque.len += n
-      if n == 0:
-        break
-    except ErrorAgain:
-      break
-
-proc onFinishBlob(response: Response; success: bool) =
-  let opaque = BlobOpaque(response.opaque)
-  let bodyRead = opaque.bodyRead
-  if success:
-    let p = realloc(opaque.p, opaque.len)
-    opaque.p = nil
-    let blob = if p == nil:
-      newBlob(nil, 0, opaque.contentType, nil)
-    else:
-      newBlob(p, opaque.len, opaque.contentType, deallocBlob)
-    bodyRead.resolve(JSResult[Blob].ok(blob))
-  else:
-    if opaque.p != nil:
-      dealloc(opaque.p)
-      opaque.p = nil
-    let res = newTypeError("Error reading response")
-    bodyRead.resolve(JSResult[Blob].err(res))
-
-proc blob*(response: Response): Promise[JSResult[Blob]] {.jsfunc.} =
-  if response.bodyUsed:
-    let err = JSResult[Blob].err(newTypeError("Body has already been consumed"))
-    return newResolvedPromise(err)
-  let opaque = BlobOpaque(
-    bodyRead: Promise[JSResult[Blob]](),
-    contentType: response.getContentType(),
-    p: alloc(BufferSize),
-    size: BufferSize
-  )
-  response.opaque = opaque
-  response.onRead = onReadBlob
-  response.onFinish = onFinishBlob
-  response.bodyUsed = true
-  response.resume()
-  return opaque.bodyRead
-
-proc json(ctx: JSContext; this: Response): Promise[JSValue] {.jsfunc.} =
-  return this.text().then(proc(s: JSResult[string]): JSValue =
-    if s.isNone:
-      return ctx.toJS(s.error)
-    return JS_ParseJSON(ctx, cstring(s.get), csize_t(s.get.len),
-      cstring"<input>")
-  )
-
-proc addResponseModule*(ctx: JSContext) =
-  ctx.registerType(Response)