Module Mehari_lwt_unixSource

An IO module Mehari implementation for Unix and Windows using Lwt. Contains also extra features based on Unix filesystem such as CGI.

Net

include Mehari_mirage.S with type addr = Ipaddr.t
Sourcemodule IO = Lwt
Sourcetype stack

Tcpip stack.

Net

include Mehari.NET with module IO := IO and type addr = Ipaddr.t with type addr = Ipaddr.t
Sourcetype addr = Ipaddr.t

Type for IP address.

Sourcetype route

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

Sourcetype rate_limiter

Rate limiter. See Rate limit.

Middlewares take a handler, and run some code before or after โ€” producing a โ€œbiggerโ€ handler. See Middleware.

Middleware

Sourceval no_middleware : middleware

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

if development then
  my_middleware
else
  Mehari.no_middleware
Sourceval 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.

Routing

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

Sourceval route : ?rate_limit:rate_limiter -> ?mw:middleware -> ?typ:[ `Raw | `Regex ] -> string -> (addr Mehari.request -> Mehari.response IO.t) -> route

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

Sourceval 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.

Sourceval 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

Sourceval make_rate_limit : ?period:int -> int -> [ `Second | `Minute | `Hour | `Day ] -> rate_limiter

make_rate_limit ~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

Sourceval virtual_hosts : ?meth:[ `ByURL | `SNI ] -> (string * (addr Mehari.request -> Mehari.response IO.t)) list -> addr Mehari.request -> Mehari.response IO.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.

Logging

Sourceval set_log_lvl : Logs.level -> unit

Set Mehari's logger to the given log level.

Logs and times requests. Time spent logging is included.

Sourceval debug : 'a Logs.log
Sourceval info : 'a Logs.log
Sourceval warning : 'a Logs.log
Sourceval error : 'a Logs.log

Response

Sourceval respond : 'a Mehari.status -> 'a -> Mehari.response IO.t

Same as Mehari.response, but the new Mehari.response is wrapped in a promise.

Same as respond but respond with given Mehari.body and use given Mehari.mime as mime type.

Sourceval respond_text : string -> Mehari.response IO.t

Same as respond but respond with given text and use text/plain as Mehari.mime type.

Sourceval respond_gemtext : ?charset:string -> ?lang:string list -> Mehari.Gemtext.t -> Mehari.response IO.t

Same as respond but respond with given Mehari.Gemtext.t and use text/gemini as Mehari.mime type.

Sourceval respond_raw : [ `Body of string | `Full of int * string * string ] -> Mehari.response IO.t

Same as Mehari.response_raw, but the new Mehari.response is wrapped in a promise.

Entry point

include Mehari.UNIX with module IO := IO and type addr := addr and type dir_path := string
Sourcetype handler = addr Mehari.request -> Mehari.response IO.t
Sourceval response_document : ?mime:Mehari.mime -> string -> Mehari.response IO.t
Sourceval static : ?handler:(string -> handler) -> ?dir_listing: (([ `Directory | `Other | `Regular_file ] * string) list -> handler) -> ?index:string -> ?show_hidden:bool -> string -> handler

Mime

Sourceval from_filename : ?lookup:[ `Ext | `Content | `Both ] -> ?charset:string -> string -> Mehari.mime option Lwt.t

from_filename ?lookup_into ?charset ?lang fname tries to create a Mehari.mime by performing a mime lookup depending of the value of lookup:

  • `Ext: guesses on the file extension of fname;
  • `Content: guesses on content of fname;
  • `Both: performs successivly a lookup on content and file extension.

Returns Mehari.make_mime ?charset "text/gemini" if one of the previous lookup fails.

  • raises Unix.Unix_error

    if a lookup based on content is performed and reading of fname fails

CGI

Mehari supports CGI scripting as described in RFC 3875

The CGI script must write the gemini response to the stdout stream. Status code and meta string on the first line, and the optional response body on subsequent lines. The bytes generated by the CGI script will be forwarded verbatim to the Gemini client, without any additional modification by the server.

Environment Variables

Some variables are empty for compatibility with other CGI script.

Let's say that the url requested is gemini://localhost/cgi/foo.cgi?input:

Sourceval run_cgi : ?timeout:float -> ?nph:bool -> string -> addr Mehari.request -> Mehari.response Lwt.t

run_cgi ?timeout ?nph script_path req executes the given file as a CGI script and return a Mehari.response based on bytes printed on stdout by script. Responds with Mehari.cgi_error in case of error or timeout exceeding.

  • timeout defaults to 5.0.
  • nph decides if NPH (Non-Parsed Header) is enable. Defaults to false.

Entry point

Sourceval run_lwt : ?port:int -> ?timeout:float -> ?verify_url_host:bool -> ?certchains:(string * string) list -> ?v4:Ipaddr.V4.Prefix.t -> ?v6:Ipaddr.V6.Prefix.t -> handler -> unit Lwt.t
Sourceval run : ?port:int -> ?timeout:float -> ?verify_url_host:bool -> ?certchains:(string * string) list -> ?v4:Ipaddr.V4.Prefix.t -> ?v6:Ipaddr.V6.Prefix.t -> handler -> unit

Like run_lwt but calls Lwt_main.run internally.