A functional Web app server.
Greatly inspired by Suave.IO and GIRAFFE of F#, this is OCaml implementation.
Sphingids are some of the faster flying insects; some are capable of flying at over 5.3 m/s (12 miles per hour). --- Wikipedia
let app =
path "/hello"
>=> text "hello, world"
let app =
path_ci "/hello"
>=> text "hello, world"
let app =
path_starts "/hello/"
>=> text "hello, world"
let app =
path_starts_ci "/hello/"
>=> text "hello, world"
let app =
path_regex "/hello/wo{3}rld"
>=> text "hello, world"
let app =
path_scanf "/%d/%d" begin fun x y ->
text @@ Printf.sprintf "hello, %d" (x + y)
end
let app =
meth `GET
>=> text "hello, world"
let app =
filter_p (fun ctx -> true)
>=> text "text."
let app =
path_p (fun path -> true)
>=> text "text."
let app =
choose
[ meth `GET
>=> choose
[ path "/a" >=> text "hello, GET a"
; path "/b" >=> text "hello, GET b"
]
; meth `POST >=> text "hello, POST"
]
let app =
log Logs.err (fun ctx m -> m "error message.")
>=> text "text."
let app =
set_mime_type "text/plain; charset=utf-8"
>=> text "text."
let app =
set_status `Bad_request
>=> text "text."
let app =
set_header "x-test" "my test header"
>=> text "text."
let app =
set_header_unless_exists "x-test" "my test header"
>=> text "text."
let app =
add_header "x-test" "my test header"
>=> text "text."
let app =
use_cookie
>=> text "text."
let app =
set_cookie "key" "value"
>=> text "text."
let app =
browse "/etc"
let app =
browse_file "/etc" "/hosts"
let app =
text "hello, world."
let app =
texts [ "hello"
; ", world."
]
let app =
json (`Assoc [ "hello", `String "world"
; "key", `Int 1 ])
let app =
respond_string "string"
let app =
respond_strings [ "string"; "string" ]
let app =
respond_file "/etc/hosts"
let app =
simple_cors
>=> text "text."
let app =
secure_headers
>=> text "text."
- Web_part.t Web app
- int Listening port
- app Web_part.t
Simple Web_part.t runner.
let yourapp : Web_part.t =
fun next ctx ->
(* your work here *)
if (* should continue *) then
let modified_ctx = ctx in
begin
set_header "a" "b" >=>
set_header "x" "y"
end next modified_ctx
else
Web_part.fail
Example:
open Core
open Async
open Horned_worm
let app =
choose
[ meth `GET >=> choose
[ path "/" >=> text "hello, world"
; path "/cookie" >=> use_cookie >=> begin
let key = "test" in
fun next ctx ->
let v = Option.value Http_context.(cookie ctx ~key)
~default:"hello cookie" in
begin
set_cookie key (v ^ "!") >=>
text v
end next ctx
end
; path_scanf "/%d/%d" begin fun x y ->
text (sprintf "%d + %d = %d" x y (x + y))
end
; path_scanf "/json/%s" begin fun s ->
json (`Assoc ["hello", `String s])
end
]
; meth `POST >=> path "/" >=> text "hello, POST"
]
let () =
run_web_server app
opam install horned_worm
- alpha
Todo:
- more predefined Web parts.
- needs query parm receiver.
- builtin websocket supports.