• Stars
    star
    750
  • Rank 60,494 (Top 2 %)
  • Language
    OCaml
  • License
    MIT License
  • Created almost 11 years ago
  • Updated 7 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Sinatra like web toolkit for OCaml

Opium

Since version 0.19.0, Opium uses httpaf. The last version that used Cohttp can be found at https://github.com/rgrinberg/opium/tree/0.18.0

Executive Summary

Sinatra like web toolkit for OCaml based on httpaf & lwt

Design Goals

  • Opium should be very small and easily learnable. A programmer should be instantly productive when starting out.

  • Opium should be extensible using independently developed plugins. This is a Rack inspired mechanism borrowed from Ruby. The middleware mechanism in Opium is called Rock.

Installation

Stable

The latest stable version is available on opam

$ opam install opium

Master

$ opam pin add rock.~dev https://github.com/rgrinberg/opium.git
$ opam pin add opium.~dev https://github.com/rgrinberg/opium.git

Documentation

For the API documentation:

The following tutorials walk through various usecases of Opium:

For examples of idiomatic usage, see the ./examples directory and the simple examples below.

Examples

Assuming the necessary dependencies are installed, $ dune build @example will compile all examples. The binaries are located in _build/default/example/.

You can execute these binaries directly, though in the examples below we use dune exec to run them.

Hello World

Here's a simple hello world example to get your feet wet:

$ cat hello_world.ml

open Opium

module Person = struct
  type t =
    { name : string
    ; age : int
    }

  let yojson_of_t t = `Assoc [ "name", `String t.name; "age", `Int t.age ]

  let t_of_yojson yojson =
    match yojson with
    | `Assoc [ ("name", `String name); ("age", `Int age) ] -> { name; age }
    | _ -> failwith "invalid person json"
  ;;
end

let print_person_handler req =
  let name = Router.param req "name" in
  let age = Router.param req "age" |> int_of_string in
  let person = { Person.name; age } |> Person.yojson_of_t in
  Lwt.return (Response.of_json person)
;;

let update_person_handler req =
  let open Lwt.Syntax in
  let+ json = Request.to_json_exn req in
  let person = Person.t_of_yojson json in
  Logs.info (fun m -> m "Received person: %s" person.Person.name);
  Response.of_json (`Assoc [ "message", `String "Person saved" ])
;;

let streaming_handler req =
  let length = Body.length req.Request.body in
  let content = Body.to_stream req.Request.body in
  let body = Lwt_stream.map String.uppercase_ascii content in
  Response.make ~body:(Body.of_stream ?length body) () |> Lwt.return
;;

let print_param_handler req =
  Printf.sprintf "Hello, %s\n" (Router.param req "name")
  |> Response.of_plain_text
  |> Lwt.return
;;

let _ =
  App.empty
  |> App.post "/hello/stream" streaming_handler
  |> App.get "/hello/:name" print_param_handler
  |> App.get "/person/:name/:age" print_person_handler
  |> App.patch "/person" update_person_handler
  |> 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 greeting

{"name":"john_doe","age":42}

Middleware

The two fundamental building blocks of opium are:

  • Handlers: Request.t -> Response.t Lwt.t
  • Middleware: 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

module Reject_user_agent = struct
  let is_ua_msie =
    let re = Re.compile (Re.str "MSIE") in
    Re.execp re
  ;;

  let m =
    let filter handler req =
      match Request.header "user-agent" req with
      | Some ua when is_ua_msie ua ->
        Response.of_plain_text ~status:`Bad_request "Please upgrade your browser"
        |> Lwt.return
      | _ -> handler req
    in
    Rock.Middleware.create ~filter ~name:"Reject User-Agent"
  ;;
end

let index_handler _request = Response.of_plain_text "Hello World!" |> Lwt.return

let _ =
  App.empty
  |> App.get "/" index_handler
  |> App.middleware Reject_user_agent.m
  |> App.cmd_name "Reject UA"
  |> App.run_command
;;

Compile with:

$ dune build example/simple_middleware/main.ml

Here we also use the ability of Opium to generate a cmdliner term to run your app. Run your executable with --help to see the options that are available to you. For example:

# run in debug mode on port 9000
$ dune exec example/simple_middleware/main.exe -- -p 9000 -d

More Repositories

1

ocaml-mustache

mustache.js logic-less templates in OCaml
OCaml
82
star
2

curly

Command line curl wrapper for OCaml
OCaml
43
star
3

onanomsg

nanomsg bindings for ocaml
OCaml
38
star
4

vim-operator-gsearch

Vim operator to search using Ag/Ack/CtrlSF/Ggrep/etc.
Vim Script
31
star
5

lev

Low Level Bindings to Libev
OCaml
29
star
6

humane-re

The human friendly interface to ocaml-re
OCaml
25
star
7

bencode

Bencode (.torrent file format) reader/writer in OCaml
OCaml
23
star
8

stringext

Extra string functions for OCaml
OCaml
21
star
9

ppx_getenv2

Sample ppx to demo making, testing, and packaging a simple ppx rewriter
OCaml
18
star
10

ocaml-hamt

Mirror of: http://gitorious.org/ocaml-hamt/ocaml-hamt
OCaml
13
star
11

ocaml-mtl

Monad Transformers Library for OCaml
OCaml
11
star
12

ranger

OCaml library for creating efficient ranges out of indexed data structures (arrays, strings, etc.)
OCaml
11
star
13

async-zmq

Async wrapper around ocaml-zmq
OCaml
11
star
14

n2omegle

Tiny omegle clone using n2o
Erlang
10
star
15

opam-lock

Dump/restore opam dependencies using a lock file
OCaml
9
star
16

ocamlbuild-atdgen

ocamlbuild plugin for atdgen
OCaml
9
star
17

json-derivers

Common derviers for the Yojson and Ezjsonm json types
OCaml
8
star
18

ocaml-json-benchmark

benchmarking OCaml json libraries
OCaml
8
star
19

evil-quick-diff

linediff.vim for evil
Emacs Lisp
8
star
20

deriving-slowly

See http://rgrinberg.com/posts/deriving-slowly/
OCaml
8
star
21

ebqueue

Tiny simple blocking queue in erlang
Erlang
8
star
22

ocaml-depgraph

Generate a dot graph from your OCaml sources
OCaml
7
star
23

opam-hub

Opam + Github = <3
OCaml
6
star
24

async-mvar

Port of Lwt_mvar to Async
OCaml
6
star
25

ocaml-fileio

A demo of dune's virtual libraries
OCaml
6
star
26

ocaml-diffbot

OCaml client for the diffbot api
OCaml
6
star
27

mix_ctags

Mix task to generate tags file using ctags for Elixir
Elixir
6
star
28

ackdo-reloaded

The companion to sed and ack/grep/ag
OCaml
5
star
29

obeanstalk

async beanstalkd client for OCaml
OCaml
5
star
30

exjsonrpc

Jsonrpc 2.0 in Elixir
Elixir
5
star
31

ocamlnet

Mirror of ocamlnet
OCaml
3
star
32

ocaml-pgn

OCaml library for parsing pgn files
OCaml
3
star
33

bruda-prolog

Stefan Bruda's Prolog mode for Emacs
Emacs Lisp
3
star
34

xxh

OCaml Bindings to xxHash
C
3
star
35

otags

OPAMified mirror of http://askra.de/software/otags/
OCaml
3
star
36

opam.vim

Vim plugin for OPAM
Vim Script
2
star
37

ngram-rps-predictor

Hierarchical Ngram Predictor
OCaml
2
star
38

flask-gevent-omegle

A little omegle clone in gevent/flask/websockets
Python
2
star
39

ocamlbuild-piqi

OCaml
2
star
40

randomknapsack

Example of approximation to knapsack problem using random hill climbing in the context of generating a playlist of a certain length from a library of songs.
OCaml
2
star
41

cohttp-serve

SimpleHTTPServer replacement in OCaml.
OCaml
1
star
42

chess.com-scraper

Chess.com scraper for games/players
Ruby
1
star
43

jbuilder-c-stubs

C
1
star
44

ackdo

sed ack ouput and write the result
OCaml
1
star
45

logarion

A blog server for Yamado articles
OCaml
1
star
46

batteries-optparse

Batteries getopt style command line parsing library
OCaml
1
star
47

FlexArray

Simple OCaml library for flexible and functional arrays
OCaml
1
star
48

async-ssl-leak

OCaml
1
star
49

edebug-hydra

Hydra shortcuts for Edebug
Emacs Lisp
1
star