Writing a webserver with LFE Barista.

I'm going to write a demo of my common lisp htmx applet in lfe.

The webserver of choice is Barista, an lfe native webserver that backends to erlangs hardened and battle tested 'httpd'.

I'd like to write specific handlers for urls and the HTTP methods for those urls.

Oubiwann says you can use the 'default' pass-through handler when started like this.

(set `#(ok ,svr) (barista:start))

This implies there must be some code in the start module to pass of to this pass-through handler.

So lets take a look at barista:start

(defun start ()
  (start '()))

(defun start (overrides)
  (let* ((opts (++ overrides (get-opts overrides))))
    (inets:start 'httpd opts)))

LFE, like erlang allows for arguement matching in function headers, when provided with no arguements it will then fall through to the second start function where it will be provide with no overrides.

The "opts" structure is built, with the (++ overrides (get-opts overrides)) call, and this is where the magic happens of setting the defaults. Whatever get-opts overrides ends up being our starting parameters that erlangs internal httpd implemention.

(defun get-opts (overrides)
  (let ((config-file (proplists:get_value 'config-file overrides 'no-config))
        (config-keys (proplists:get_value 'config-keys overrides '(inets services httpd))))
    (if (== 'no-config config-file)
      (default-options)
      (case (clj:get-in (read-config config-file) config-keys)
        ('undefined '())
        (opts opts)))))

We'll only trace this section of code for our interest. The arguement to get-opt is expected to be a proplist , which has an option 'config-file'. If there is no config-file value in the provided proplist, it returns a 'no-config atom as the variable.

We then see that if the config-file has the value 'no-config the default-options function is called and this provides those values.

So, the long story short is, set a httpd config file up, specify it, and it should work.

Lets work on a sample module.

[{inets,
  [{services,
    [{httpd, [
              {port, 4243},
              {server_name, "barista_test"},
              {server_root, "."},
              {ipfamily, inet4},
              {bind_address, {0,0,0,0} },
              {modules,  [my-demo]}
              ]}]}]}].

This is an erlang term format, that the inets application expects, our module 'my-demo' is there, which we'll need to write.

Starting it now, and specifying the config file..

lfe> (set `#(ok ,svr) (barista:start '(#(config-file "configs/sys.config"))))

Resources: