package resto-cohttp-server
module Service = Resto_directory.Make(Encoding).Service
type step = Resto_directory.Make(Encoding).step =
| Static of string
(*A literal chunk
*)| Dynamic of Resto.Arg.descr
(*A chunk which describes a argument to a service
*)| DynamicTail of Resto.Arg.descr
(*The remainder of the chunks are to be interpreted as a list of arguments
*)
The different chunks of a path
E.g., /archive/<year>/<months>/
has a Static "archive"
step followed by a Dynamic _
step followed by a Dynamic _
step. Each Dynamic _
step has an Resto.Arg
payload describing the chunk.
type conflict = Resto_directory.Make(Encoding).conflict =
| CService of Resto.meth
(*A collision with a service that has been already defined for the given method at the certain path.
*)| CDir
(*An incompatibility with the directory at a certain path.
*)| CBuilder
(*A collision with the builder part of another dynamic directory of a certain path.
*)| CDynDescr of string * string
(*A collision between the descriptions of two given dynamic directories.
*)| CTail
(*A collision with another dynamic tail directory of a certain path.
*)| CTypes of Resto.Arg.descr * Resto.Arg.descr
(*A typing incompatibility with an URI parameter of a certain type when another parameter type was expected.
*)| CType of Resto.Arg.descr * string list
(*A typing impompatibility with an URI parameter with the given subdirectories.
*)
Possible kind of conflictual error that can occur while registering services into a directory or while merging directories.
type ('query, 'input, 'output, 'error) types =
('query, 'input, 'output, 'error) Resto_directory.Make(Encoding).types =
{
query : 'query Resto.Query.t;
input : 'input Service.input;
output : 'output Encoding.t;
error : 'error Encoding.t;
}
type registered_service = Resto_directory.Make(Encoding).registered_service =
| Service : {
types : ('q, 'i, 'o, 'e) types;
handler : 'q -> 'i -> ('o, 'e) Resto_directory.Answer.t Lwt.t;
} -> registered_service
type 'prefix t = 'prefix Resto_directory.Make(Encoding).t
Dispatch tree
type 'prefix directory = 'prefix t
type lookup_error = [
| `Not_found
| `Method_not_allowed of Resto.meth list
| `Cannot_parse_path of string list * Resto.Arg.descr * string
]
val string_of_step : step -> string
string_of_step step
converts the given steps
into a string.
val string_of_conflict_kind : conflict -> string
string_of_conflict_kind conflict_kind
converts the given conflict_kind
into a string.
string_of_conflict conflict
converts the given conflict
into a string.
val lookup :
'prefix directory ->
'prefix ->
Resto.meth ->
string list ->
(registered_service, [> lookup_error ]) result Lwt.t
lookup d m p
is Ok (Service _)
if there is a service s
registered in d
and both the method of s
is m
and the path of s
matches p
. It is Error _
otherwise.
If it is Ok (Service _)
then the returned value corresponds to the registered service.
val lookup_uri_desc :
'prefix directory ->
'prefix ->
Resto.meth ->
string list ->
(string, [> lookup_error ]) result Lwt.t
lookup_uri_desc d p
is Ok u
where u
is a formated URI description, if there is a service s
registered in d
and the path of s
matches p
. It is Error _
otherwise.
For instance, given the following path p
: "/entries-by-date/2022/01/10"
where "2022"
, "01"
, and "10"
are expected to be paramaters in the path of s
, the function will evaluate in "/entries-by-date/<year>/<month>/<day>"
.
val allowed_methods :
'prefix directory ->
'prefix ->
string list ->
(Resto.meth list, [> lookup_error ]) result Lwt.t
allowed_methods d p
is the set of methods m
such that lookup d m p
is Ok _
. In other words, it is the set of methods m
such that a service has been registered in d
for a path that matches p
.
val transparent_lookup :
'prefix directory ->
('meth, 'prefix, 'params, 'query, 'input, 'output, 'error) Service.t ->
'params ->
'query ->
'input ->
[> ('output, 'error) Resto_directory.Answer.t ] Lwt.t
val empty : 'prefix directory
Empty tree
val prefix : ('pr, 'p) Resto.Path.path -> 'p directory -> 'pr directory
prefix p d
is a directory of services which includes a service registered on the path p / q
for each service registered on the path q
in d
.
val merge :
?strategy:[ `Raise | `Pick_left | `Pick_right ] ->
'a directory ->
'a directory ->
'a directory
merge ~strategy d1 d2
is a directory which includes all the services of d1
and d2
.
It is possible to merge both static and dynamic trees.
- In case of static trees, the resulting merge will occur in a eager way at function call.
- In case of dynamic trees and because of their nature, the resulting merging directory can't however be computed directly: We don't know the subtree of such a tree before resolving it whith a proper argument
key
and thus don't have a way to merge it directly at function call. In such a case, the merging computation will be delayed at resolving time. This may not be a problem in most cases. But merging directories containing a lot of nested dynamic directories should still be avoided as it may impact queries performances.
As a few elements that constitutes a directory tree are not mergeable, it may be possible to come upon a collision case during a merge. Unmergeable elements are:
- Services
- Dynamic directories description.
If one or more of these elements from d1
collides with one or more element from d2
, the function will make a choice depending on the given merging strategy
:
`Raise
will raise aConflict
exception. This is the default choice.`Pick_left
will pick the element fromd1
to be part of the resulting directory.`Pick_right
will pick the element fromd2
to be part of the resulting directory.
val register :
'prefix directory ->
('meth, 'prefix, 'params, 'query, 'input, 'output, 'error) Service.t ->
('params ->
'query ->
'input ->
[< ('output, 'error) Resto_directory.Answer.t ] Lwt.t) ->
'prefix directory
register d s h
is a directory that contains all the services registered in d
plus the service s
. Requests to the service s
are handled by the handler h
.
val register0 :
unit directory ->
('m, unit, unit, 'q, 'i, 'o, 'e) Service.t ->
('q -> 'i -> [< ('o, 'e) Resto_directory.Answer.t ] Lwt.t) ->
unit directory
Registring handler in service tree. Curryfied variant.
val register1 :
'prefix directory ->
('m, 'prefix, unit * 'a, 'q, 'i, 'o, 'e) Service.t ->
('a -> 'q -> 'i -> [< ('o, 'e) Resto_directory.Answer.t ] Lwt.t) ->
'prefix directory
val register2 :
'prefix directory ->
('m, 'prefix, (unit * 'a) * 'b, 'q, 'i, 'o, 'e) Service.t ->
('a -> 'b -> 'q -> 'i -> [< ('o, 'e) Resto_directory.Answer.t ] Lwt.t) ->
'prefix directory
val register3 :
'prefix directory ->
('m, 'prefix, ((unit * 'a) * 'b) * 'c, 'q, 'i, 'o, 'e) Service.t ->
('a -> 'b -> 'c -> 'q -> 'i -> [< ('o, 'e) Resto_directory.Answer.t ] Lwt.t) ->
'prefix directory
val register4 :
'prefix directory ->
('m, 'prefix, (((unit * 'a) * 'b) * 'c) * 'd, 'q, 'i, 'o, 'e) Service.t ->
('a ->
'b ->
'c ->
'd ->
'q ->
'i ->
[< ('o, 'e) Resto_directory.Answer.t ] Lwt.t) ->
'prefix directory
val register5 :
'prefix directory ->
('m, 'prefix, ((((unit * 'a) * 'b) * 'c) * 'd) * 'f, 'q, 'i, 'o, 'e)
Service.t ->
('a ->
'b ->
'c ->
'd ->
'f ->
'q ->
'i ->
[< ('o, 'e) Resto_directory.Answer.t ] Lwt.t) ->
'prefix directory
val register_dynamic_directory :
?descr:string ->
'prefix directory ->
('prefix, 'a) Resto.Path.path ->
('a -> 'a directory Lwt.t) ->
'prefix directory
Registring dynamic subtree.
val register_dynamic_directory1 :
?descr:string ->
'prefix directory ->
('prefix, unit * 'a) Resto.Path.path ->
('a -> (unit * 'a) directory Lwt.t) ->
'prefix directory
Registring dynamic subtree. (Curryfied variant)
val register_dynamic_directory2 :
?descr:string ->
'prefix directory ->
('prefix, (unit * 'a) * 'b) Resto.Path.path ->
('a -> 'b -> ((unit * 'a) * 'b) directory Lwt.t) ->
'prefix directory
val register_dynamic_directory3 :
?descr:string ->
'prefix directory ->
('prefix, ((unit * 'a) * 'b) * 'c) Resto.Path.path ->
('a -> 'b -> 'c -> (((unit * 'a) * 'b) * 'c) directory Lwt.t) ->
'prefix directory
val register_describe_directory_service :
'prefix directory ->
('prefix, 'prefix, 'error) Service.description_service ->
'prefix directory
Registring a description service.
val describe_directory :
recurse:bool ->
?arg:'a ->
'a directory ->
Encoding.schema Resto.Description.directory Lwt.t