Formatted url
Switch branches/tags
Nothing to show
Clone or download
Drup Merge pull request #13 from j0sh/tyre
Update to latest tyre API.
Latest commit 970430f Dec 1, 2016
Permalink
Failed to load latest commit information.
src Fix to last tyre. Sep 14, 2016
test Update to latest tyre API. Dec 1, 2016
.gitignore Init. Apr 21, 2015
.merlin fix merlin file. Jul 4, 2016
LICENSE.md License file. Apr 27, 2015
Makefile Init. Apr 21, 2015
Readme.md Re 1.4 is out! Add an opam file and update the Readme. May 12, 2015
_oasis Use tyre and remove converters. May 30, 2016
_tags Add more tags. Apr 28, 2015
configure Init. Apr 21, 2015
opam Add dependency "gen" to opam May 19, 2015
setup.ml Init. Apr 21, 2015

Readme.md

Formatted Url

This library allows to create type-safe formatted urls in the spirit of the format type from the standard library. It is backed by re and uri

This is work in progress, if you have any remarks or proposition, please open an issue. The API will be changed until I'm happy with it. Contributions are welcome. Also, it may still be buggy.

To use this library, you can pin it:

opam pin add furl https://github.com/Drup/furl.git

Quick look

Let's imagine we want to build a REST service indexing Camelidaes.

let camlidae () = Furl.host "www.camlidae.ml"

We can query a Camelidae by name:

let by_name () =
  Furl.(~$camlidae / "name" /% String /? nil)
val by_name : unit -> (string -> 'a, 'a) Furl.furl

Notice how the type of the value describes the contained parameters.

Let's consider the type ('f,'r) Furl.furl. 'f is the type of a function corresponding to the parameters of the url. 'r is the return type, which could be anything at this point.

We can also query a list of camelidae by humps:

let by_humps () =
  Furl.(~$camlidae / "humps" /% Int /? nil)
val by_humps : unit -> (int -> 'a, 'a) Furl.furl

This is nice, but we want to refine the list by humps to only show non extinct camelidaes:

let by_humps () =
  Furl.(~$camlidae / "humps" /% Int /? ("extinct",Opt Bool) ** nil)
val by_humps : unit -> (int -> bool option -> 'a, 'a) Furl.furl

We can now build a handler answering to these endpoints:

let handle_camlidaes =
  Furl.match_url [
    Furl.(route ~$by_name) (fun n ->
      List.filter (fun c -> c.name = n) list_camlidaes
    ) ;
    Furl.(route ~$by_humps) (fun humps -> function
      | None ->
        List.filter (fun c -> c.humps = humps) list_camlidaes
      | Some b ->
        List.filter (fun c -> c.humps = humps && c.extinct = b) list_camlidaes
    );
  ]
    ~default:(fun _uri -> failwith "This is not a camlidae.")
val handle_camlidaes : Uri.t -> camlidae list

You can then give this handler to your favorite web server and Tada, a camelidae web API.

You can also expose the formatted urls for clients:

let query_by_humps = Furl.eval @@ by_humps ()
val query_by_humps : int -> bool option -> Uri.t

Then you can use your favorite http client to get the answer we all want:

fetch_http @@ query_by_hump 2 (Some false) ;;
["Bactrian camel"; "Wild camel"]

See camlidae.ml for the complete working example.

Principles

furl uses GADT in a similar manner than format in the standard library, but specialized for urls and regexps. The matching against multiple uris is done with re.

urls are separated into Furl.url which are not yet finalized and Furl.furl which are finalized. This separation is done to make Furl.url a pure datastructure that can be serialized, moved around (and sent to the client in the context of eliom). Furl.furl contains an url and the list of converters.