Skip to content

Commit

Permalink
Add more matchers
Browse files Browse the repository at this point in the history
* int32
* int64
* boolean
  • Loading branch information
anuragsoni committed Apr 4, 2019
1 parent 50a0e95 commit 48c9a30
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 17 deletions.
27 changes: 15 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@
This library will help with adding typed routes to OCaml applications.

Users can create a list of routes, and handler function to work
on the extracted entities. using the combinators provided by
the library. This list of routes will then in-turn be provided the
string value of the URL path for a request under consideration.
Every handler will be provided an instance of the request that is
being processed.

The core library in the current state has no depndencies and isn't tied
to any particular library or framework. It should be usable in the current state too
but, the idea would be to provide sub-libraries with tighter integration with the remaining
on the extracted entities using the combinators provided by
the library. To perform URL matching one would just need to forward
the URL's path and query to the matcher.

The core library in the current state has just one dependency ([Astring](https://github.com/dbuenzli/astring)) and isn't tied
to any particular library or framework. It should be usable in the current state,
but the idea would be to provide sub-libraries with tighter integration with the remaining
ecosystem. Future work would also include working on client side routing for use
with `js_of_ocaml` libraries like [incr_dom](https://github.com/janestreet/incr_dom) or [ocaml-vdom](https://github.com/LexiFi/ocaml-vdom).

Expand All @@ -28,10 +26,15 @@ module Response = struct
...
end
let get_user (id: int) =
...
let get_user state (id: int) =
(* Request handlers can define their own routes too *)
let open Routes in
let routes = [ int64 </> boolean </> ==> (fun _ i b -> ... ) ] in
match_with_state ~state routes with
| None -> ...
| Some response -> ...
let search_user (name: string) (city : string) =
let search_user _ (name: string) (city : string) =
...
let routes =
Expand Down
10 changes: 5 additions & 5 deletions example/main.ml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ let respond_with_text reqd status text =

module Handlers = struct
(* The first parameter *)
let greeter router_state name city =
let greeter router_state id name city b =
let (req : Request.t) = Routes.RouterState.get_request router_state in
Log.Global.printf "Woohoo! I have access to the Httpaf request here: %s\n" req.target;
Log.Global.printf "Woohoo! I have access to the Httpaf request here: Id: %Ld %s - %B" id req.target b;
`String ("Hello, " ^ name ^ ". How was your trip to " ^ city ^ "?")
;;

Expand All @@ -33,13 +33,13 @@ module Handlers = struct

let retrieve_user state name id =
let req : Request.t = Routes.RouterState.get_request state in
Log.Global.printf "Fetching user with name %s and id %d." name id;
Log.Global.printf "Fetching user with name %s and id %ld." name id;
`String req.target
;;

let user_routes state =
let open Routes in
let routes = [ str </> int </> empty ==> retrieve_user ] in
let routes = [ str </> int32 </> empty ==> retrieve_user ] in
match match_with_state ~state routes with
| None -> `String "user not found"
| Some s -> s
Expand All @@ -50,7 +50,7 @@ let routes =
let open Routes in
let open Handlers in
[ empty ==> return_bigstring
; method' `GET </> s "greet" </> str </> str </> empty ==> greeter
; method' `GET </> s "greet" </> int64 </> str </> str </> boolean </> empty ==> greeter
; method' `GET </> s "sum" </> int </> int </> empty ==> sum
; method' `GET </> s "user" ==> user_routes
]
Expand Down
27 changes: 27 additions & 0 deletions src/routes.ml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,33 @@ let int { req; unvisited = params; meth } =
| None -> None)
;;

let boolean { req; unvisited = params; meth } =
match params with
| [] -> None
| x :: xs ->
(match String.Sub.to_bool x with
| None -> None
| Some b -> Some ({ req; unvisited = xs; meth }, fun k -> k b))
;;

let int32 { req; unvisited = params; meth } =
match params with
| [] -> None
| x :: xs ->
(match String.Sub.to_int32 x with
| None -> None
| Some i -> Some ({ req; unvisited = xs; meth }, fun k -> k i))
;;

let int64 { req; unvisited = params; meth } =
match params with
| [] -> None
| x :: xs ->
(match String.Sub.to_int64 x with
| None -> None
| Some i -> Some ({ req; unvisited = xs; meth }, fun k -> k i))
;;

let ( </> ) m1 m2 state =
match m1 state with
| None -> None
Expand Down
12 changes: 12 additions & 0 deletions src/routes.mli
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ val str : ('req, 'meth) state -> (('req, 'meth) state * ((string -> 'a) -> 'a))
the request handler. *)
val int : ('req, 'meth) state -> (('req, 'meth) state * ((int -> 'a) -> 'a)) option

(** [int32] will match and extract a 32 bit integer. *)
val int32 : ('req, 'meth) state -> (('req, 'meth) state * ((int32 -> 'a) -> 'a)) option

(** [int64] will match and extract a 64 bit integer. *)
val int64 : ('req, 'meth) state -> (('req, 'meth) state * ((int64 -> 'a) -> 'a)) option

(** [boolean] will match and extract a boolean value. *)
val boolean : ('req, 'meth) state -> (('req, 'meth) state * ((bool -> 'a) -> 'a)) option

(** [</>] is used to connect two path parsers. Ex: str </> int
will first try and parse a string, followed by an integer.
If any of the parsers fail, the whole route matching fails.*)
Expand Down Expand Up @@ -70,6 +79,9 @@ val match'
-> ('req, 'res, 'meth) route list
-> 'res option

(** [match_with_state] takes a router state and runs it through a list of
routes. This is useful when using handlers that in-turn define
their own routes. *)
val match_with_state
: state:('req, 'meth) state
-> ('req, 'res, 'meth) route list
Expand Down

0 comments on commit 48c9a30

Please sign in to comment.