aboutsummaryrefslogtreecommitdiff
path: root/lib/cohttp_handler/cohttp_handler.ml
blob: 3842e7cd20bcdfff7b423c6fe4ecab854682337e (plain)
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
open Cohttp_lwt_unix
open Lwt.Syntax

let url_of_string : V_string.t -> string = Obj.magic

let code_of_response : Response.t -> (int, string) Result.t =
 fun resp ->
  let code = resp |> Response.status |> Cohttp.Code.code_of_status in
  match Cohttp.Code.is_success code with
  | true -> Ok 200
  | false -> Error (string_of_int code)

let get_method : type a b. (a, b) Services.method_ -> Http.Method.t = function
  | POST -> `POST
  | GET -> `GET
  | PUT -> `PUT
  | DELETE -> `DELETE
  | PATCH -> `PATCH
  | HEAD -> `HEAD
  | CONNECT -> `CONNECT
  | OPTIONS -> `OPTIONS
  | TRACE -> `TRACE

(** Encodde the response given by cohttp for the service *)
let map_response :
    (module Services.JsonClientHandler
       with type request = 'request
        and type response = 'response
        and type placeholders = 'placeholders) ->
    Cohttp_lwt.Body.t ->
    'response Lwt.t =
 fun (type request response placeholders)
     (module S : Services.JsonClientHandler
       with type request = request
        and type response = response
        and type placeholders = placeholders) body ->
  match S.method_ with
  | GET | POST | PUT | DELETE | PATCH | CONNECT | OPTIONS | TRACE ->
      let* body_content = Cohttp_lwt.Body.to_string body in
      let json = Ppx_yojson_conv_lib.Yojson.Safe.from_string body_content in
      Lwt.return (S.response_of_yojson json)
  | HEAD -> Lwt.return_unit

let request :
    root:string ->
    (module Services.JsonClientHandler
       with type request = 'request
        and type response = 'response
        and type placeholders = 'placeholders) ->
    'placeholders ->
    'request ->
    ('response, string) result Lwt.t =
 fun (type request response placeholders) ~root
     (module S : Services.JsonClientHandler
       with type request = request
        and type response = response
        and type placeholders = placeholders) parameters request ->
  let uri =
    V_string.concat ~sep:(V_string.v "/")
      [ V_string.v root; Path.build parameters S.path ]
  in

  (* There is no body for GET or HEAD method *)
  let request_body =
    match S.method_ with
    | Services.GET | Services.HEAD -> None
    | _ ->
        Some
          (request |> S.yojson_of_request
         |> Ppx_yojson_conv_lib.Yojson.Safe.to_string
         |> Cohttp_lwt.Body.of_string)
  in

  let uri = Uri.of_string (url_of_string uri) in
  let* response, body =
    Client.call ?headers:None ?body:request_body (get_method S.method_) uri
  in

  match code_of_response response with
  | Error _ as e -> Lwt.return e
  | Ok _ ->
      let* response_body = map_response (module S) body in
      Lwt.return_ok response_body