summary refs log tree commit diff stats
path: root/.gitignore
diff options
context:
space:
mode:
authorhut <hut@lepus.uberspace.de>2015-02-07 14:05:56 +0100
committerhut <hut@lepus.uberspace.de>2015-02-07 14:05:56 +0100
commit38d7f50ca759ba81a75ffee9132693e5d9e1340f (patch)
tree1ba998052bcf06dde900ffeba5c5001fc018c779 /.gitignore
parentc8e0e81aed76b8a1441c2fd18f7e24dad23d71fd (diff)
downloadranger-38d7f50ca759ba81a75ffee9132693e5d9e1340f.tar.gz
core.loader: fix copy&pasting directory links
Diffstat (limited to '.gitignore')
0 files changed, 0 insertions, 0 deletions
o <nincsnevem662@gmail.com> 2023-09-17 13:36:38 +0200 response: add blob() function' href='/ahoang/chawan/commit/src/loader/response.nim?id=84a7c65b62e5ff322a23b91c2e80d517d41ed504'>84a7c65b ^
36390a56 ^

6b0b7ccf ^
14baa050 ^

6b0b7ccf ^
36390a56 ^
204ec2eb ^















36390a56 ^
204ec2eb ^
251b9469 ^
36390a56 ^
8e6783a4 ^
36390a56 ^
ac3e7378 ^
251b9469 ^
36390a56 ^
204ec2eb ^
36390a56 ^



d526deb9 ^
dab0d1cd ^
36390a56 ^
2b10a9b7 ^

8e6783a4 ^

36390a56 ^







fe2d01b8 ^
204ec2eb ^









251b9469 ^



204ec2eb ^

251b9469 ^

36390a56 ^







1422f339 ^
204ec2eb ^




9026c578 ^

a8f218df ^




9026c578 ^
7724082d ^




14baa050 ^


14baa050 ^



36390a56 ^
14baa050 ^
84a7c65b ^









ac3e7378 ^
84a7c65b ^


ac3e7378 ^
84a7c65b ^

1422f339 ^
a8f218df ^
9026c578 ^
a8f218df ^


36390a56 ^


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

                  


                       
                      
               
                    

                     
                 

                
                      

                            
 
    















                                             
                        
                                                 
             
            
                       
                             
                        
                             
                               
                              



                                      
                     
                                                           
 

                      

                                                      







                                
                                                                   









                                 



                                                         

                                         

                      







                                            
                                                                      




                                          

                                          




                                                          
                                                          




                                                      


                                 



                                                  
 
                                                                    









                                                          
                                                           


                             
                                                                                

             
                                                                     
                
                                                                        


                                                                 


                                         
import std/streams
import std/unicode

import bindings/quickjs
import io/promise
import io/socketstream
import js/error
import js/javascript
import loader/headers
import loader/request
import types/blob
import types/url

import chakasu/charset
import chakasu/decoderstream
import chakasu/encoderstream

type
  ResponseType* = enum
    TYPE_DEFAULT = "default"
    TYPE_BASIC = "basic"
    TYPE_CORS = "cors"
    TYPE_ERROR = "error"
    TYPE_OPAQUE = "opaque"
    TYPE_OPAQUEREDIRECT = "opaqueredirect"

  #TODO fully implement headers guards
  HeadersGuard* = enum
    GUARD_IMMUTABLE = "immutable"
    GUARD_REQUEST = "request"
    GUARD_REQUEST_NO_CORS = "request-no-cors"
    GUARD_RESPONSE = "response"
    GUARD_NONE = "none"

  Response* = ref object
    responseType* {.jsget: "type".}: ResponseType
    res*: int
    fd*: int
    body*: SocketStream
    bodyUsed* {.jsget.}: bool
    contentType*: string
    status* {.jsget.}: uint16
    headers* {.jsget.}: Headers
    headersGuard: HeadersGuard
    redirect*: Request
    url*: URL #TODO should be urllist?
    unregisterFun*: proc()
    bodyRead*: Promise[string]
    charset*: Charset
    internalMessage*: string # should NOT be exposed to JS!

jsDestructor(Response)

proc newResponse*(res: int, request: Request, fd = -1,
    stream: SocketStream = nil): Response =
  return Response(
    res: res,
    url: request.url,
    body: stream,
    bodyRead: Promise[string](),
    fd: fd
  )

func makeNetworkError*(): Response {.jsstfunc: "Response:error".} =
  #TODO use "create" function
  #TODO headers immutable
  return Response(
    res: 0,
    responseType: TYPE_ERROR,
    status: 0,
    headers: newHeaders(),
    headersGuard: GUARD_IMMUTABLE
  )

func sok(response: Response): bool {.jsfget: "ok".} =
  return response.status in 200u16 .. 299u16

func surl(response: Response): string {.jsfget: "url".} =
  if response.responseType == TYPE_ERROR:
    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()
  if response.body != nil:
    response.body.close()

proc text*(response: Response): Promise[JSResult[string]] {.jsfunc.} =
  if response.body == nil:
    let p = newPromise[JSResult[string]]()
    p.resolve(JSResult[string].ok(""))
    return p
  if response.bodyUsed:
    let p = newPromise[JSResult[string]]()
    let err = JSResult[string]
      .err(newTypeError("Body has already been consumed"))
    p.resolve(err)
    return p
  let bodyRead = response.bodyRead
  response.bodyRead = nil
  return bodyRead.then(proc(s: string): JSResult[string] =
    let cs = if response.charset == CHARSET_UNKNOWN:
      CHARSET_UTF_8
    else:
      response.charset
    if cs == CHARSET_UTF_8 and s.validateUtf8() == -1:
      ok(s)
    else:
      let ss = newStringStream(s)
      let ds = newDecoderStream(ss, cs)
      let es = newEncoderStream(ds, CHARSET_UTF_8)
      return ok(es.readAll())
  )

proc blob*(response: Response): Promise[JSResult[Blob]] {.jsfunc.} =
  if response.bodyRead == nil:
    let p = newPromise[JSResult[Blob]]()
    let err = JSResult[Blob]
      .err(newTypeError("Body has already been consumed"))
    p.resolve(err)
    return p
  let bodyRead = response.bodyRead
  response.bodyRead = nil
  return bodyRead.then(proc(s: string): JSResult[Blob] =
    if s.len == 0:
      return ok(newBlob(nil, 0, response.contentType, nil))
    GC_ref(s)
    let deallocFun = proc() =
      GC_unref(s)
    let blob = newBlob(unsafeAddr s[0], s.len, response.contentType, deallocFun)
    ok(blob))

proc json(ctx: JSContext, this: Response): Promise[JSResult[JSValue]]
    {.jsfunc.} =
  return this.text().then(proc(s: JSResult[string]): JSResult[JSValue] =
    let s = ?s
    return ok(JS_ParseJSON(ctx, cstring(s), cast[csize_t](s.len),
      cstring"<input>")))

proc addResponseModule*(ctx: JSContext) =
  ctx.registerType(Response)