{"id":16718034,"url":"https://github.com/drup/furl","last_synced_at":"2025-10-01T07:31:46.037Z","repository":{"id":31088052,"uuid":"34647115","full_name":"Drup/furl","owner":"Drup","description":"Formatted url","archived":false,"fork":false,"pushed_at":"2025-01-20T14:14:53.000Z","size":84,"stargazers_count":49,"open_issues_count":12,"forks_count":3,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-01-20T15:26:43.821Z","etag":null,"topics":["format","gadt","ocaml","uri"],"latest_commit_sha":null,"homepage":"","language":"OCaml","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Drup.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-04-27T05:06:56.000Z","updated_at":"2025-01-20T14:14:54.000Z","dependencies_parsed_at":"2022-09-08T20:51:59.011Z","dependency_job_id":null,"html_url":"https://github.com/Drup/furl","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Drup%2Ffurl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Drup%2Ffurl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Drup%2Ffurl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Drup%2Ffurl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Drup","download_url":"https://codeload.github.com/Drup/furl/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234841979,"owners_count":18895142,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["format","gadt","ocaml","uri"],"created_at":"2024-10-12T21:34:45.975Z","updated_at":"2025-10-01T07:31:40.728Z","avatar_url":"https://github.com/Drup.png","language":"OCaml","readme":"# Formatted Url\n\nThis library allows to create type-safe formatted urls in the spirit of the\n`format` type from the standard library. It is backed by [re][re] and [uri][uri]\n\n[re]: https://github.com/ocaml/ocaml-re\n[uri]: https://github.com/mirage/ocaml-uri\n\n**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.**\n\nTo use this library, you can pin it:\n```\nopam pin add furl https://github.com/Drup/furl.git\n```\n\n## Quick look\n\nLet's imagine we want to build a REST service indexing [Camelidaes](https://species.wikimedia.org/wiki/Camelidae).\n\n```ocaml\nlet camlidae () = Furl.host \"www.camlidae.ml\"\n```\n\nWe can query a Camelidae by name:\n```ocaml\nlet by_name () =\n  Furl.(~$camlidae / \"name\" /% String /? nil)\nval by_name : unit -\u003e (string -\u003e 'a, 'a) Furl.furl\n```\n\nNotice how the type of the value describes the contained parameters.\n\nLet's consider the type `('f,'r) Furl.furl`. `'f` is the type of a function\ncorresponding to the parameters of the url. `'r` is the return type, which could be anything at this point.\n\nWe can also query a list of camelidae by humps:\n```ocaml\nlet by_humps () =\n  Furl.(~$camlidae / \"humps\" /% Int /? nil)\nval by_humps : unit -\u003e (int -\u003e 'a, 'a) Furl.furl\n```\n\nThis is nice, but we want to refine the list by humps to only show non extinct camelidaes:\n```ocaml\nlet by_humps () =\n  Furl.(~$camlidae / \"humps\" /% Int /? (\"extinct\",Opt Bool) ** nil)\nval by_humps : unit -\u003e (int -\u003e bool option -\u003e 'a, 'a) Furl.furl\n```\n\nWe can now build a handler answering to these endpoints:\n\n```ocaml\nlet handle_camlidaes =\n  Furl.match_url [\n    Furl.(route ~$by_name) (fun n -\u003e\n      List.filter (fun c -\u003e c.name = n) list_camlidaes\n    ) ;\n    Furl.(route ~$by_humps) (fun humps -\u003e function\n      | None -\u003e\n        List.filter (fun c -\u003e c.humps = humps) list_camlidaes\n      | Some b -\u003e\n        List.filter (fun c -\u003e c.humps = humps \u0026\u0026 c.extinct = b) list_camlidaes\n    );\n  ]\n    ~default:(fun _uri -\u003e failwith \"This is not a camlidae.\")\nval handle_camlidaes : Uri.t -\u003e camlidae list\n```\n\nYou can then give this handler to your favorite web server and Tada, a camelidae web API.\n\nYou can also expose the formatted urls for clients:\n```ocaml\nlet query_by_humps = Furl.eval @@ by_humps ()\nval query_by_humps : int -\u003e bool option -\u003e Uri.t\n```\n\nThen you can use your favorite http client to get the answer we all want:\n```ocaml\nfetch_http @@ query_by_hump 2 (Some false) ;;\n[\"Bactrian camel\"; \"Wild camel\"]\n```\n\nSee [camlidae.ml](test/camlidae.ml) for the complete working example.\n\n## Principles\n\nfurl 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.\n\nurls 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.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrup%2Ffurl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdrup%2Ffurl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrup%2Ffurl/lists"}