1

When using Cohttp_async to perform a request, I'm handling an HTTP response code of 302 (Temporary Redirect) in the following manner:

let rec download uri =
  Cohttp_async.Client.get uri
  >>= fun (response, body) ->
  let http_code = Cohttp.Code.code_of_status (Cohttp.Response.status response) in
  if Cohttp.Code.is_redirection http_code then
    (* Code to handle the redirect *)
  else Cohttp_async.Body.to_string body

This seems to work alright (at least in the simple cases I'm using it). I'm mainly curious to see if there's a better way of doing this. I think there might be a better way to handle this, like by matching on Cohttp.Code.status. Something like:

match http_code with
  | Ok -> Cohttp_async.Body.to_string body
  | Temporary_redirect -> (* Code to handle the redirect *)
  | _ -> (* Failure here, possibly *)

So far, I haven't had much luck with this, as it seems like I'm not matching the right constructors.

As a second side question, does Cohttp have a better way to handle with HTTP redirects are given back as part of the response? Maybe the way I'm going about this is wrong, and there's a simpler way.

pseudoramble
  • 2,541
  • 22
  • 28
  • 1
    You should add, at least, back-ticks to your constructor names, since they are polymorphic variants – ivg Jul 08 '14 at 04:54
  • I have some learning to do, as I'm not really sure what polymorphic variant is. I think you're referring to the pattern I was trying to match - `Ok` and `Temporary_redirect` as far as I can tell are types defined in cohttp's `Code` module: https://github.com/avsm/ocaml-cohttp/blob/master/cohttp/code.mli. I guess my question if and how I can use the status type in this code. – pseudoramble Jul 09 '14 at 00:05
  • 1
    Polymorphic variants can be distinguished from the ordinary ones by a preceding backtick, I won't provide an example, since I assume that the backtick will be eaten by SO. Polymorphic variants shouldn't be qualified with a module name, so that they all live in a global namespace. They have other features, but for the case that will be enough. – ivg Jul 09 '14 at 21:29
  • Thanks for the help again @ivg. It turns out I was just spelling `OK` wrong. It helped to go and read more about variant and polymorphic variants though. – pseudoramble Jul 15 '14 at 01:39

1 Answers1

1

I believe the short answer to my question is that I was referring to the wrong type when trying to match on response. There are two polymorphic types that exist - Okand OK, where the latter is the Cohttp type for an HTTP 200 response code. In my situation, I also had to handle a few kinds of redirects, which I added in.

So, the code ends up looking something like this:

let rec download uri =
  Cohttp_async.Client.get uri
  >>= fun (response, body) ->
  let http_code = Cohttp.Response.status response in
  match http_code with
    | `OK -> Cohttp_async.Body.to_string body (* If we get a status of OK *)
    | `Temporary_redirect | `Found -> (* Handle redirection *)
    | _ -> return "" (* Catch-all for other scenarios. Not great. *)

Omitting the last case will make the compiler complain about non-exhaustive checks.

pseudoramble
  • 2,541
  • 22
  • 28