Module Madge_server

Madge — server-side

include module type of Madge
module Request = Madge.Request
module Response = Madge.Response
module Route = Madge.Route
type ('a, 'w, 'r) route = ('a, 'w, 'r) Route.t

Engine

The heart of Madge, where we link routes and requests.

from route to request

val uri : ('a, Uri.t, 'r) Madge.Route.t -> 'a

Easiest way to use a route: transform it into a URI. The 'a parameter corresponds to the function of that route, with Uri.t as return type. For instance, if r has type (int -> float -> 'w, 'w, 'r) route, then uri r will have type int -> float -> Uri.t.

val with_request : ('a, 'w, 'r) Madge.Route.t -> ((module Madge__.Serialisation.JSONABLE with type t = 'r) -> Madge.Request.t -> 'w) -> 'a

Generic way to use a route. Given a route and a continuation, create a request from the route, pass that request to the continuation, and return the resulting value. For instance, uri is simply process route (fun (module _) {uri; _} -> uri).

from request to route

val apply' : ('a, 'w, 'r) Madge.Route.t -> (unit -> 'a) -> Madge.Request.t -> (unit -> 'w) option

Given a route, a controller, and a request, check whether the route matches the request. If so, construct a thunk that calls the controller with the correct arguments. Otherwise, return None.

val apply : ('a, 'w, 'r) Madge.Route.t -> (unit -> 'a) -> Madge.Request.t -> ((module Madge__.Serialisation.JSONABLE with type t = 'r) -> (unit -> 'w) -> 'z) -> (unit -> 'z) option

Given a route, a controller, a request, and a continuation, check whether the route matches. If so, construct a thunk that calls the controller with the correct arguments and passes it to the continuation. Otherwise, return None. For instance, apply' is simply apply route controller request (fun _ f -> f ()).

module type STRINGABLE = sig ... end
module type JSONABLE = sig ... end
module SString : sig ... end
module SUnit : sig ... end
module SStatusCode : sig ... end
module SSlug : sig ... end
module JString : sig ... end
module JUri : sig ... end
module JUnit : sig ... end
module JVoid : sig ... end
module JBool : sig ... end
module JInt : sig ... end
module JFloat : sig ... end
module JOption (A : sig ... end) : sig ... end
module JList (A : sig ... end) : sig ... end
module JPair (A : sig ... end) (B : sig ... end) : sig ... end
module JTriple (A : sig ... end) (B : sig ... end) (C : sig ... end) : sig ... end
module JQuad (A : sig ... end) (B : sig ... end) (C : sig ... end) (D : sig ... end) : sig ... end
module type Internal_endpoints = sig ... end
module Make_endpoints (Internal : sig ... end) : sig ... end

Normal behaviour

val match_apply : ('a, 'r Nes.Lwt.t, 'r) Route.t -> (unit -> 'a) -> Request.t -> (unit -> (Cohttp.Response.t * Cohttp_lwt.Body.t) Nes.Lwt.t) option

The main function of this module. Given a route, a controller and a request, attempt to match the request to the route, and, if it succeeds, apply the controller. The result of the controller is serialised as the route commands and returned as JSON under the form of an Lwt promise compatible with the ~callback argument of Cohttp_lwt_unix.Server.make.

module type Endpoints = sig ... end
module type Apply_controller = sig ... end

Successful non-JSON responses

All of these return NesVoid.t, meaning they can only ever be used on a route that is never returning normally anyway; otherwise, this would allow returning non-JSON on normal routes that expect it.

val respond_string : ?content_type:string -> string -> Nes.Void.t Nes.Lwt.t

Returns the given string.

val respond_file : fname:string -> Nes.Void.t Nes.Lwt.t

Returns the given file.

Error responses

Their type might seem over-complicated, but it simply means that these functions can be used as a format, eg.

| shortcut_bad_request "This %s is a %s request" "thing" "bad" |

The shortcut_* variants raise an exception. This is normal behaviour if they are called within the controller of match_apply. However, outside of it, they will leak a private Shortcut exception. Prefer using respond_* variants in those situations.

val shortcut_bad_request : ('a, Nes.Format.formatter, unit, 'any Nes.Lwt.t) Stdlib.format4 -> 'a

Shortcut execution and returns “400 Bad Request” with the given message.

val shortcut_forbidden : ('a, Nes.Format.formatter, unit, 'any Nes.Lwt.t) Stdlib.format4 -> 'a

Shortcut execution and returns “403 Forbidden” with the given message.

val shortcut_forbidden_no_leak : unit -> 'any Nes.Lwt.t

Variant of shortcut_forbidden for when one purposefully does not want to give any information of why that was, typically for user authentication.

val respond_not_found : ('a, Nes.Format.formatter, unit, (Cohttp.Response.t * Cohttp_lwt.Body.t) Nes.Lwt.t) Stdlib.format4 -> 'a

Returns “404 Not Found” with the given message.

val shortcut_not_found : ('a, Nes.Format.formatter, unit, 'any Nes.Lwt.t) Stdlib.format4 -> 'a
val respond_internal_server_error : unit -> (Cohttp.Response.t * Cohttp_lwt.Body.t) Nes.Lwt.t

Returns “500 Internal server error” with no message.

Generic responses

val respond : SStatusCode.t -> ('a, Nes.Format.formatter, unit, (Cohttp.Response.t * Cohttp_lwt.Body.t) Nes.Lwt.t) Stdlib.format4 -> 'a