2016-09-08 21:13:10 +04:00
|
|
|
(**************************************************************************)
|
|
|
|
(* *)
|
|
|
|
(* Copyright (c) 2014 - 2016. *)
|
|
|
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
|
|
|
(* *)
|
|
|
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
|
|
|
(* *)
|
|
|
|
(**************************************************************************)
|
|
|
|
|
2016-12-01 21:27:53 +04:00
|
|
|
(** Typed RPC services: definition, binding and dispatch. *)
|
2016-09-08 21:13:10 +04:00
|
|
|
|
|
|
|
(** Typed path argument. *)
|
|
|
|
module Arg : sig
|
|
|
|
|
|
|
|
type 'a arg
|
|
|
|
val make:
|
|
|
|
?descr:string ->
|
|
|
|
name:string ->
|
|
|
|
destruct:(string -> ('a, string) result) ->
|
|
|
|
construct:('a -> string) ->
|
2016-10-16 23:57:29 +04:00
|
|
|
unit -> 'a arg
|
2016-09-08 21:13:10 +04:00
|
|
|
|
|
|
|
type descr = {
|
|
|
|
name: string ;
|
|
|
|
descr: string option ;
|
|
|
|
}
|
|
|
|
val descr: 'a arg -> descr
|
|
|
|
|
|
|
|
val int: int arg
|
|
|
|
val int32: int32 arg
|
|
|
|
val int64: int64 arg
|
|
|
|
val float: float arg
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
(** Parametrized path to services. *)
|
|
|
|
module Path : sig
|
|
|
|
|
|
|
|
type ('prefix, 'params) path
|
|
|
|
type 'prefix context = ('prefix, 'prefix) path
|
|
|
|
|
|
|
|
val root: 'a context
|
|
|
|
|
|
|
|
val add_suffix:
|
|
|
|
('prefix, 'params) path -> string -> ('prefix, 'params) path
|
|
|
|
val (/):
|
|
|
|
('prefix, 'params) path -> string -> ('prefix, 'params) path
|
|
|
|
|
|
|
|
val add_arg:
|
|
|
|
('prefix, 'params) path -> 'a Arg.arg -> ('prefix, 'params * 'a) path
|
|
|
|
val (/:):
|
|
|
|
('prefix, 'params) path -> 'a Arg.arg -> ('prefix, 'params * 'a) path
|
|
|
|
|
|
|
|
val prefix:
|
|
|
|
('prefix, 'a) path -> ('a, 'params) path -> ('prefix, 'params) path
|
|
|
|
|
|
|
|
val map:
|
|
|
|
('a -> 'b) -> ('b -> 'a) -> ('prefix, 'a) path -> ('prefix, 'b) path
|
|
|
|
|
|
|
|
end
|
|
|
|
|
2016-12-11 19:34:58 +04:00
|
|
|
(** HTTP methods as defined in Cohttp.Code *)
|
|
|
|
|
|
|
|
type meth = [
|
|
|
|
| `GET
|
|
|
|
| `POST
|
|
|
|
| `HEAD
|
|
|
|
| `DELETE
|
|
|
|
| `PATCH
|
|
|
|
| `PUT
|
|
|
|
| `OPTIONS
|
|
|
|
| `TRACE
|
|
|
|
| `CONNECT
|
|
|
|
| `Other of string
|
|
|
|
]
|
|
|
|
|
|
|
|
val string_of_method : meth -> string
|
|
|
|
|
2016-09-08 21:13:10 +04:00
|
|
|
(** Services. *)
|
|
|
|
type ('prefix, 'params, 'input, 'output) service
|
|
|
|
|
|
|
|
val service:
|
2016-12-11 19:34:58 +04:00
|
|
|
?meth: meth ->
|
|
|
|
?description: string ->
|
|
|
|
input: 'input Data_encoding.t ->
|
|
|
|
output: 'output Data_encoding.t ->
|
|
|
|
('prefix, 'params) Path.path ->
|
|
|
|
('prefix, 'params, 'input, 'output) service
|
|
|
|
|
|
|
|
val get_service:
|
|
|
|
?description: string ->
|
|
|
|
output: 'output Data_encoding.t ->
|
|
|
|
('prefix, 'params) Path.path ->
|
|
|
|
('prefix, 'params, unit, 'output) service
|
|
|
|
|
|
|
|
val head_service:
|
|
|
|
?description: string ->
|
|
|
|
('prefix, 'params) Path.path ->
|
|
|
|
('prefix, 'params, unit, unit) service
|
|
|
|
|
|
|
|
val post_service:
|
|
|
|
?description: string ->
|
|
|
|
input: 'input Data_encoding.t ->
|
|
|
|
output: 'output Data_encoding.t ->
|
|
|
|
('prefix, 'params) Path.path ->
|
|
|
|
('prefix, 'params, 'input, 'output) service
|
|
|
|
|
|
|
|
val put_service:
|
|
|
|
?description: string ->
|
|
|
|
input: 'input Data_encoding.t ->
|
|
|
|
output: 'output Data_encoding.t ->
|
|
|
|
('prefix, 'params) Path.path ->
|
|
|
|
('prefix, 'params, 'input, 'output) service
|
|
|
|
|
|
|
|
val delete_service:
|
2016-09-08 21:13:10 +04:00
|
|
|
?description: string ->
|
|
|
|
input: 'input Data_encoding.t ->
|
|
|
|
output: 'output Data_encoding.t ->
|
|
|
|
('prefix, 'params) Path.path ->
|
|
|
|
('prefix, 'params, 'input, 'output) service
|
|
|
|
|
|
|
|
val prefix:
|
|
|
|
('prefix, 'inner_prefix) Path.path ->
|
|
|
|
('inner_prefix, 'params, 'input, 'output) service ->
|
|
|
|
('prefix, 'params, 'input, 'output) service
|
|
|
|
|
|
|
|
val forge_request:
|
|
|
|
(unit, 'params, 'input, 'output) service ->
|
2016-12-11 19:34:58 +04:00
|
|
|
'params -> 'input -> meth * string list * Data_encoding.json
|
2016-09-08 21:13:10 +04:00
|
|
|
|
|
|
|
val read_answer:
|
|
|
|
(unit, 'params, 'input, 'output) service ->
|
|
|
|
Data_encoding.json -> ('output, string) result
|
|
|
|
|
|
|
|
(** Service directory description *)
|
|
|
|
module Description : sig
|
|
|
|
|
|
|
|
type service_descr = {
|
|
|
|
description: string option ;
|
|
|
|
input: Json_schema.schema ;
|
|
|
|
output: Json_schema.schema ;
|
|
|
|
}
|
|
|
|
|
|
|
|
type directory_descr =
|
|
|
|
| Static of static_directory_descr
|
|
|
|
| Dynamic of string option
|
|
|
|
|
|
|
|
and static_directory_descr = {
|
|
|
|
service: service_descr option ;
|
|
|
|
subdirs: static_subdirectories_descr option ;
|
|
|
|
}
|
|
|
|
|
|
|
|
and static_subdirectories_descr =
|
|
|
|
| Suffixes of directory_descr Map.Make(String).t
|
|
|
|
| Arg of Arg.descr * directory_descr
|
|
|
|
|
|
|
|
val service:
|
2016-12-11 19:34:58 +04:00
|
|
|
?meth: meth ->
|
2016-09-08 21:13:10 +04:00
|
|
|
?description:string ->
|
|
|
|
('prefix, 'params) Path.path ->
|
|
|
|
('prefix, 'params, bool option, directory_descr) service
|
|
|
|
|
|
|
|
val pp_print_directory_descr:
|
|
|
|
Format.formatter -> directory_descr -> unit
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
module Answer : sig
|
|
|
|
|
|
|
|
(** Return type for service handler *)
|
|
|
|
type 'a answer =
|
|
|
|
{ code : int ;
|
|
|
|
body : 'a output ;
|
|
|
|
}
|
|
|
|
|
|
|
|
and 'a output =
|
|
|
|
| Empty
|
|
|
|
| Single of 'a
|
|
|
|
| Stream of 'a stream
|
|
|
|
|
|
|
|
and 'a stream = {
|
|
|
|
next: unit -> 'a option Lwt.t ;
|
|
|
|
shutdown: unit -> unit ;
|
|
|
|
}
|
|
|
|
|
|
|
|
val ok: 'a -> 'a answer
|
|
|
|
val return: 'a -> 'a answer Lwt.t
|
|
|
|
val return_stream: 'a stream -> 'a answer Lwt.t
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
(** Dispatch tree *)
|
|
|
|
type 'prefix directory
|
|
|
|
|
2016-12-11 19:34:58 +04:00
|
|
|
(** Empty list of dispatch trees *)
|
2016-09-08 21:13:10 +04:00
|
|
|
val empty: 'prefix directory
|
|
|
|
|
|
|
|
val map: ('a -> 'b) -> 'b directory -> 'a directory
|
|
|
|
|
|
|
|
val prefix: ('pr, 'p) Path.path -> 'p directory -> 'pr directory
|
|
|
|
val merge: 'a directory -> 'a directory -> 'a directory
|
|
|
|
|
|
|
|
(** Possible error while registring services. *)
|
|
|
|
type step =
|
|
|
|
| Static of string
|
|
|
|
| Dynamic of Arg.descr
|
|
|
|
type conflict =
|
|
|
|
| CService | CDir | CBuilder | CCustom
|
|
|
|
| CTypes of Arg.descr *
|
|
|
|
Arg.descr
|
|
|
|
| CType of Arg.descr * string list
|
|
|
|
exception Conflict of step list * conflict
|
|
|
|
|
|
|
|
(** Registring handler in service tree. *)
|
|
|
|
val register:
|
|
|
|
'prefix directory ->
|
|
|
|
('prefix, 'params, 'input, 'output) service ->
|
|
|
|
('params -> 'input -> 'output Answer.answer Lwt.t) ->
|
|
|
|
'prefix directory
|
|
|
|
|
|
|
|
(** Registring handler in service tree. Curryfied variant. *)
|
|
|
|
val register0:
|
|
|
|
unit directory ->
|
|
|
|
(unit, unit, 'i, 'o) service ->
|
|
|
|
('i -> 'o Answer.answer Lwt.t) ->
|
|
|
|
unit directory
|
|
|
|
|
|
|
|
val register1:
|
|
|
|
'prefix directory ->
|
|
|
|
('prefix, unit * 'a, 'i, 'o) service ->
|
|
|
|
('a -> 'i -> 'o Answer.answer Lwt.t) ->
|
|
|
|
'prefix directory
|
|
|
|
|
|
|
|
val register2:
|
|
|
|
'prefix directory ->
|
|
|
|
('prefix, (unit * 'a) * 'b, 'i, 'o) service ->
|
|
|
|
('a -> 'b -> 'i -> 'o Answer.answer Lwt.t) ->
|
|
|
|
'prefix directory
|
|
|
|
|
|
|
|
val register3:
|
|
|
|
'prefix directory ->
|
|
|
|
('prefix, ((unit * 'a) * 'b) * 'c, 'i, 'o) service ->
|
|
|
|
('a -> 'b -> 'c -> 'i -> 'o Answer.answer Lwt.t) ->
|
|
|
|
'prefix directory
|
|
|
|
|
|
|
|
val register4:
|
|
|
|
'prefix directory ->
|
|
|
|
('prefix, (((unit * 'a) * 'b) * 'c) * 'd, 'i, 'o) service ->
|
|
|
|
('a -> 'b -> 'c -> 'd -> 'i -> 'o Answer.answer Lwt.t) ->
|
|
|
|
'prefix directory
|
|
|
|
|
|
|
|
val register5:
|
|
|
|
'prefix directory ->
|
|
|
|
('prefix, ((((unit * 'a) * 'b) * 'c) * 'd) * 'e, 'i, 'o) service ->
|
|
|
|
('a -> 'b -> 'c -> 'd -> 'e -> 'i -> 'o Answer.answer Lwt.t) ->
|
|
|
|
'prefix directory
|
|
|
|
|
|
|
|
(** Registring dynamic subtree. *)
|
|
|
|
val register_dynamic_directory:
|
2016-12-11 19:34:58 +04:00
|
|
|
?meths:meth list ->
|
2016-09-08 21:13:10 +04:00
|
|
|
?descr:string ->
|
|
|
|
'prefix directory ->
|
2016-12-11 19:34:58 +04:00
|
|
|
('prefix, 'a) Path.path ->
|
|
|
|
('a -> 'a directory Lwt.t) ->
|
2016-09-08 21:13:10 +04:00
|
|
|
'prefix directory
|
|
|
|
|
|
|
|
(** Registring dynamic subtree. (Curryfied variant) *)
|
|
|
|
val register_dynamic_directory1:
|
|
|
|
?descr:string ->
|
|
|
|
'prefix directory ->
|
|
|
|
('prefix, unit * 'a) Path.path ->
|
|
|
|
('a -> (unit * 'a) directory Lwt.t) ->
|
|
|
|
'prefix directory
|
|
|
|
|
|
|
|
val register_dynamic_directory2:
|
|
|
|
?descr:string ->
|
|
|
|
'prefix directory ->
|
|
|
|
('prefix, (unit * 'a) * 'b) 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) Path.path ->
|
|
|
|
('a -> 'b -> 'c -> (((unit * 'a) * 'b) * 'c) directory Lwt.t) ->
|
|
|
|
'prefix directory
|
|
|
|
|
|
|
|
(** Registring custom directory lookup. *)
|
2016-12-11 19:34:58 +04:00
|
|
|
type custom_lookup = RestoDirectory.custom_lookup
|
|
|
|
(* | CustomService of Description.service_descr * *)
|
|
|
|
(* ( Data_encoding.json option -> *)
|
|
|
|
(* Data_encoding.json Answer.answer Lwt.t ) *)
|
|
|
|
(* | CustomDirectory of Description.directory_descr *)
|
2016-09-08 21:13:10 +04:00
|
|
|
|
|
|
|
val register_custom_lookup:
|
2016-12-11 19:34:58 +04:00
|
|
|
?meth:meth ->
|
2016-09-08 21:13:10 +04:00
|
|
|
?descr:string ->
|
|
|
|
'prefix directory ->
|
|
|
|
('prefix, 'params) Path.path ->
|
|
|
|
('params -> string list -> custom_lookup Lwt.t) ->
|
|
|
|
'prefix directory
|
|
|
|
|
|
|
|
val register_custom_lookup1:
|
2016-12-11 19:34:58 +04:00
|
|
|
?meth:meth ->
|
2016-09-08 21:13:10 +04:00
|
|
|
?descr:string ->
|
|
|
|
'prefix directory ->
|
|
|
|
('prefix, unit * 'a) Path.path ->
|
|
|
|
('a -> string list -> custom_lookup Lwt.t) ->
|
|
|
|
'prefix directory
|
|
|
|
|
|
|
|
val register_custom_lookup2:
|
2016-12-11 19:34:58 +04:00
|
|
|
?meth:meth ->
|
2016-09-08 21:13:10 +04:00
|
|
|
?descr:string ->
|
|
|
|
'prefix directory ->
|
|
|
|
('prefix, (unit * 'a) * 'b) Path.path ->
|
|
|
|
('a -> 'b -> string list -> custom_lookup Lwt.t) ->
|
|
|
|
'prefix directory
|
|
|
|
|
|
|
|
val register_custom_lookup3:
|
2016-12-11 19:34:58 +04:00
|
|
|
?meth:meth ->
|
2016-09-08 21:13:10 +04:00
|
|
|
?descr:string ->
|
|
|
|
'prefix directory ->
|
|
|
|
('prefix, ((unit * 'a) * 'b) * 'c) Path.path ->
|
|
|
|
('a -> 'b -> 'c -> string list -> custom_lookup Lwt.t) ->
|
|
|
|
'prefix directory
|
|
|
|
|
|
|
|
(** Registring a description service. *)
|
|
|
|
val register_describe_directory_service:
|
|
|
|
'prefix directory ->
|
|
|
|
('prefix, 'prefix, bool option, Description.directory_descr) service ->
|
|
|
|
'prefix directory
|
|
|
|
|
2016-12-01 21:27:53 +04:00
|
|
|
exception Cannot_parse of Arg.descr * string * string list
|
2016-09-08 21:13:10 +04:00
|
|
|
|
2016-12-01 21:27:53 +04:00
|
|
|
(** Resolve a service. *)
|
|
|
|
val lookup:
|
2016-12-11 19:34:58 +04:00
|
|
|
'prefix directory -> ?meth:meth -> 'prefix -> string list ->
|
2016-12-01 21:27:53 +04:00
|
|
|
(Data_encoding.json option -> Data_encoding.json Answer.answer Lwt.t) Lwt.t
|