diff options
| author | Adelyn Breelove <[email protected]> | 2018-12-13 14:11:23 -0700 |
|---|---|---|
| committer | Adelyn Breelove <[email protected]> | 2018-12-13 14:11:23 -0700 |
| commit | c848b9cc265f5ac2bcc70bd73e1cc8945d512e34 (patch) | |
| tree | 4334a7749f7d0bb379690cfdcdd866689c2fb1e0 /lib/http.ml | |
| parent | Update my name in disml.opam (diff) | |
| download | disml-c848b9cc265f5ac2bcc70bd73e1cc8945d512e34.tar.xz disml-c848b9cc265f5ac2bcc70bd73e1cc8945d512e34.zip | |
Add rate limit handling
Diffstat (limited to 'lib/http.ml')
| -rw-r--r-- | lib/http.ml | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/lib/http.ml b/lib/http.ml index 3e10eb8..d2dff65 100644 --- a/lib/http.ml +++ b/lib/http.ml @@ -5,6 +5,9 @@ module Make(T : S.Token) = struct module Base = struct exception Invalid_Method + exception Bad_response_headers + + let rl = ref Rl.empty let base_url = "https://discordapp.com/api/v7" @@ -24,22 +27,35 @@ module Make(T : S.Token) = struct "Content-Type", "application/json"; ] - (* TODO Finish processor *) - let process_response ((_resp:Response.t), body) = + let process_response path ((resp:Response.t), body) = + (match Response.headers resp + |> Rl.rl_of_header with + | Some r -> Mvar.put (Rl.find_exn !rl path) r + | None -> raise Bad_response_headers) + >>= fun () -> body |> Cohttp_async.Body.to_string >>| Yojson.Safe.from_string let request ?(body=`Null) m path = - let uri = process_url path in - let headers = process_request_headers () in - let body = process_request_body body in - (match m with - | `DELETE -> Cohttp_async.Client.delete ~headers ~body uri - | `GET -> Cohttp_async.Client.get ~headers uri - | `PATCH -> Cohttp_async.Client.patch ~headers ~body uri - | `POST -> Cohttp_async.Client.post ~headers ~body uri - | `PUT -> Cohttp_async.Client.put ~headers ~body uri - | _ -> raise Invalid_Method) - >>= process_response + rl := Rl.update ~f:(function + | None -> Mvar.create () + | Some r -> r + ) !rl path; + let limit = Rl.find_exn !rl path in + Mvar.take limit >>= fun limit -> + let process () = + let uri = process_url path in + let headers = process_request_headers () in + let body = process_request_body body in + (match m with + | `DELETE -> Cohttp_async.Client.delete ~headers ~body uri + | `GET -> Cohttp_async.Client.get ~headers uri + | `PATCH -> Cohttp_async.Client.patch ~headers ~body uri + | `POST -> Cohttp_async.Client.post ~headers ~body uri + | `PUT -> Cohttp_async.Client.put ~headers ~body uri + | _ -> raise Invalid_Method) + >>= process_response path + in if limit.remaining > 0 then process () + else Clock.at (Core.Time.(Span.of_int_sec limit.reset |> of_span_since_epoch)) >>= process end let get_gateway () = |