Page
Library
Module
Module type
Parameter
Class
Class type
Source
Sinatra like web toolkit for OCaml based on cohttp & lwt
Rock
.The latest stable version is available on opam
$ opam install opium
$ opam pin add opium_kernel --dev-repo
$ opam pin add opium --dev-repo
For the API documentation:
odig
: odig doc opium
.The following tutorials walk through various usecases of Opium:
For examples of idiomatic usage, see the ./examples directory and the simple examples below.
Assuming the necessary dependencies are installed, $ dune build @examples
will compile all examples. The binaries are located in _build/default/examples/
.
You can execute these binaries directly, though in the examples below we use dune exec
to run them.
Here's a simple hello world example to get your feet wet:
$ cat hello_world.ml
open Opium.Std
type person = {name: string; age: int}
let json_of_person {name; age} =
let open Ezjsonm in
dict [("name", string name); ("age", int age)]
let print_param =
put "/hello/:name" (fun req ->
`String ("Hello " ^ param req "name") |> respond')
let streaming =
let open Lwt.Infix in
get "/hello/stream" (fun _req ->
(* [create_stream] returns a push function that can be used to
push new content onto the stream. [f] is function that
expects to receive a promise that gets resolved when the user
decides that they have pushed all their content onto the stream.
When the promise forwarded to [f] gets resolved, the stream will be
closed. *)
let f, push = App.create_stream () in
let timers =
List.map
(fun t ->
Lwt_unix.sleep t
>|= fun () -> push (Printf.sprintf "Hello after %f seconds\n" t))
[1.; 2.; 3.]
in
f (Lwt.join timers))
let default =
not_found (fun _req ->
`Json Ezjsonm.(dict [("message", string "Route not found")]) |> respond')
let print_person =
get "/person/:name/:age" (fun req ->
let person =
{name= param req "name"; age= "age" |> param req |> int_of_string}
in
`Json (person |> json_of_person) |> respond')
let _ =
App.empty |> print_param |> print_person |> streaming |> default
|> App.run_command
compile and run with:
$ dune exec examples/hello_world.exe &
then call
curl http://localhost:3000/person/john_doe/42
You should see the JSON message
{"name":"john_doe","age":42}
The two fundamental building blocks of opium are:
Rock.Request.t -> Rock.Response.t Lwt.t
Rock.Handler.t -> Rock.Handler.t
Almost all of opium's functionality is assembled through various middleware. For example: debugging, routing, serving static files, etc. Creating middleware is usually the most natural way to extend an opium app.
Here's how you'd create a simple middleware turning away everyone's favourite browser.
open Opium.Std
(* don't open cohttp and opium since they both define request/response modules*)
let is_substring ~substring =
let re = Re.compile (Re.str substring) in
Re.execp re
let reject_ua ~f =
let filter handler req =
match Cohttp.Header.get (Request.headers req) "user-agent" with
| Some ua when f ua -> `String "Please upgrade your browser" |> respond'
| _ -> handler req
in
Rock.Middleware.create ~filter ~name:"reject_ua"
let _ =
App.empty
|> get "/" (fun _ -> `String "Hello World" |> respond')
|> middleware (reject_ua ~f:(is_substring ~substring:"MSIE"))
|> App.cmd_name "Reject UA" |> App.run_command
Compile with:
$ dune build examples/middleware_ua.ml
Here we also use the ability of Opium to generate a cmdliner term to run your app. Run your executable with -h
to see the options that are available to you. For example:
# run in debug mode on port 9000
$ dune exec examples/middleware_ua.exe -- -p 9000 -d