Module Mehari_eio

An IO module Mehari implementation based on Eio library.

module Addr : sig ... end
module Direct : sig ... end


include Mehari.NET with module IO := Direct and type addr = Addr.t and type clock := Eio.Time.clock
type route

Routes tell router which handler to select for each request. See Routing.

type rate_limiter

Rate limiter. See Rate limit.

Middlewares take a handler, and run some code before or after — producing a “bigger” handler. See Middleware.


val no_middleware : middleware

Does nothing but call its inner handler. Useful for disabling middleware conditionally during application startup:

if development then
val pipeline : middleware list -> middleware

Combines a list of middlewares into one, such that these two lines are equivalent: Mehari.pipeline [ mw1 ; mw2 ] @@ handler mw1 @@ mw2 @@ handler.


Creates a router. If none of the routes match the Mehari.request, the router returns Mehari.not_found.

val route : ?rate_limit:rate_limiter -> ?mw:middleware -> ?regex:bool -> string -> (Addr.t Mehari.request -> Mehari.response Direct.t) -> route

route ~rate_limit ~mw ~regex path handler forwards requests for path to handler. path can be a string literal or a regex in Perl style depending of value of regex. If rate limit is in effect, handler is not executed and a respond with Mehari.status Mehari.slow_down is sended.

val scope : ?rate_limit:rate_limiter -> ?mw:middleware -> string -> route list -> route

scope ~rate_limit ~mw prefix routes groups routes under the path prefix, rate_limit and mw.

val no_route : route

A dummy value of type route that is completely ignored by the router. Useful for disabling routes conditionally during application start.

Rate limit

val make_rate_limit : Eio.Time.clock -> ?period:int -> int -> [ `Second | `Minute | `Hour | `Day ] -> rate_limiter

make_rate_limit clock ~period n unit creates a rate_limiter which limits client to n request per period * unit. For example,

make_rate_limit ~period:2 5 `Hour

limits client to 5 requests every 2 hours.

Virtual hosting

val virtual_hosts : ?meth:[ `ByURL | `SNI ] -> (string * (Addr.t Mehari.request -> Mehari.response Direct.t)) list -> Addr.t Mehari.request -> Mehari.response Direct.t

virtual_hosts ?meth [(domain, handler); ...] produces a handler which enables virtual hosting at the TLS-layer using SNI.

  • meth can be used to choose which source to match the hostnames against. Defaults to `SNI.


val set_log_lvl : Logs.level -> unit

Set Mehari's logger to the given log level.

Logs and times requests. Time spent logging is included.

val debug : 'a Logs.log
val info : 'a Logs.log
val warning : 'a Logs.log
val error : 'a Logs.log
include Mehari.FS with module IO := Direct and type addr = Addr.t and type dir_path := Eio.Fs.dir Eio.Path.t
type addr = Addr.t

Static files

val response_document : ?mime:Mehari.mime -> Eio.Fs.dir Eio.Path.t -> Mehari.response Direct.t

Same as Mehari.response but respond with content of given filename and use given Mehari.mime as mime type. If filename is not present on filesystem, responds with Mehari.not_found. If mime parameter is not supplied, use Mehari.no_mime as mime type.

val static : ?handler:(Eio.Fs.dir Eio.Path.t -> handler) -> ?dir_listing: (([ `Regular_file | `Directory | `Other ] * string) list -> handler) -> ?index:string -> ?show_hidden:bool -> Eio.Fs.dir Eio.Path.t -> handler

static dir validates the path parameter (retrieved by calling Mehari.param req 1) by checking that it is relative and does not contain parent directory references. If these checks fail, responds with Mehari.not_found.

If the checks succeed, static calls handler path request, where path is the path generated by the concatenation of directory that was passed to static and path of request. handler defaults to response_document.

If a directory is requested, static will look for a file named index in that directory to return. Otherwise, a directory file listing will be generated by calling dir_listing [ filename; ... ] request. index is default on index.gmi.

show_hidden decides whether hidden files should be listed. It defaults to false for security reasons.

Entry point

val run : ?port:int -> ?verify_url_host:bool -> ?config:Tls.Config.server -> ?timeout:(float * Eio.Time.clock) -> ?backlog:int -> ?addr:addr -> certchains:Tls.Config.certchain list -> Eio.Net.t -> handler -> unit

run ?port ?verify_url_host ?config ?backlog ?addr certchains net handler runs the server using handler.

  • port is the port to listen on. Defaults to 1965.
  • verify_url_host, if true (by default), will verify if the URL hostname corresponds to the server's certificate (chosen according to ocaml-tls
  • config is the TLS server configuration. Defaults to

    Tls.Config.server ~certificates
        ~authenticator:(fun ?ip:_ ~host:_ _ -> Ok None)

    To support client certificates, specify the authenticator.

  • timeout is a couple of form (duration, eio_clock). duration is the maximum waiting time in seconds for the client to write a request after TLS handshake. Unset by default.
  • backlog is the the number of pending connections that can be queued up. Defaults to 4096.
  • addr is the socket addresses. Defaults to Eio.Net.Ipaddr.V4.loopback.
  • certchains is the list of form [(certs, key); ...], the last one is considered default.
  • raises Invalid_argument

    if certchains is empty.