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
open Brr
open Brr_io
let log fmt =
Printf.ksprintf (fun s -> Console.(log [ Jstr.v ("[api] " ^ s) ])) fmt
type api_error =
| Fetch_error of Jv.Error.t
| Http_error of Fetch.Response.t
| Json_parse_error of string
| Invalid_response of string * Jv.t option
type 'a response = ('a, api_error) Fut.result
let string_of_api_error = function
| Fetch_error e -> Jstr.to_string (Jv.Error.message e)
| Http_error r ->
Printf.sprintf "HTTP error: %d %s" (Fetch.Response.status r)
(Jstr.to_string (Fetch.Response.status_text r))
| Json_parse_error e -> e
| Invalid_response (msg, json_opt) -> (
match json_opt with
| Some json ->
Printf.sprintf "%s - Response: %s" msg
(Json.encode json |> Jstr.to_string)
| None -> msg)
let map_fut_error f fut = Fut.map (fun res -> Result.map_error f res) fut
let fetch_response_json response =
Fetch.Body.json (Fetch.Response.as_body response)
|> map_fut_error (fun e ->
let msg = Jv.Error.message e |> Jstr.to_string in
Json_parse_error msg)
let execute_code (code : string) : Quill_api.code_execution_result response =
let open Fut.Result_syntax in
log "Sending execution request";
let url = Jstr.v "/api/execute" in
let =
Fetch.Headers.of_assoc
[ (Jstr.v "Content-Type", Jstr.v "application/json") ]
in
let body =
Quill_api.code_execution_request_to_yojson { code }
|> Yojson.Safe.to_string |> Jstr.v |> Fetch.Body.of_jstr
in
let method' = Jstr.v "POST" in
let init = Fetch.Request.init ~headers ~body ~method' () in
let request = Fetch.Request.v ~init url in
let* response =
Fut.map
(fun res -> Result.map_error (fun e -> Fetch_error e) res)
(Fetch.request request)
in
if not (Fetch.Response.ok response) then Fut.error (Http_error response)
else
let* json_jv = fetch_response_json response in
let json_str = Jstr.to_string (Json.encode json_jv) in
let json = Yojson.Safe.from_string json_str in
let result = Quill_api.code_execution_result_of_yojson json in
match result with
| Error err -> Fut.error (Json_parse_error err)
| Ok response -> Fut.ok response
let fetch_document (path : string) : string response =
let open Fut.Result_syntax in
let api_url_str =
if path = "/" || path = "" then "/api/doc"
else "/api/doc/" ^ String.sub path 1 (String.length path - 1)
in
let api_url = Jstr.v api_url_str in
log "Fetching document from %s" api_url_str;
let* response = map_fut_error (fun e -> Fetch_error e) (Fetch.url api_url) in
if not (Fetch.Response.ok response) then Fut.error (Http_error response)
else
let* text =
map_fut_error
(fun e -> Fetch_error e)
(Fetch.Body.text (Fetch.Response.as_body response))
in
Fut.ok (Jstr.to_string text)