/emnode

Elnode-inspired HTTP server in Emacs Lisp with stripped down features

Primary LanguageEmacs LispGNU General Public License v3.0GPL-3.0

Emnode

A fork of Elnode with bugs fixed, cleaner APIs, better organized code.

Current changes over Elnode

  • No authentication.

  • Basic support for log level with elnode:*log-level*.

  • Support for HTTP data/body retrieving with elnode:http-data.

  • No more Wiki.

  • Renaming elnode to emnode.

No fancy features, it does exactly what a simple webserver does.

Example

Simplest example:

(defun handle-/ (httpcon)
  (emnode:http-start httpcon 200 '("Content-Type" . "text/plain"))
  (emnode:http-end httpcon "Hello World"))

(setq *route-table*
      '(("^.*/" . handle-/)))

(emnode:start-server *route-table* :port 8088)

The following one is taken from my config. Actually we could do better than this:

(setq *emnode-routes*
      '(("^.*//eval/?"         . ~ipc-eval)
        ("^.*//open/\\(.*\\)"  . ~ipc-open-file)
        ("^.*//exec/\\(.*\\)"  . ~ipc-exec-file)))

(defun ~ipc-eval (httpcon)
  (let* ((expr (format "%s" (emnode:http-data httpcon)))
         (sexp (if (not (and (s-starts-with? "(" expr)
                             (s-ends-with?   ")" expr)))
                   (format "(%s)" expr)
                   expr)))
    (emnode:http-start httpcon 200 '("Content-Type" . "text/plain"))
    (emnode:http-end httpcon (format "> Eval'ing: %s" sexp))
    (unless (zerop (length (s-trim expr)))
      (with-temp-buffer
        (insert expr)
        (eval-buffer)))))

(defun ~ipc-open-file (httpcon)
  (let ((path (emnode:http-get-arg httpcon 1)))
    (emnode:http-start httpcon 200 '("Content-Type" . "text/plain"))
    (emnode:http-end httpcon (format "> Opening: %s" path))
    (find-file path)))

(defun ~ipc-exec-file (httpcon)
  (let ((path (emnode:http-get-arg httpcon 1)))
    (emnode:http-start httpcon 200 '("Content-Type" . "text/plain"))
    (emnode:http-end httpcon (format "> Executing: %s" path))
    (with-temp-buffer
      (insert-file-contents path)
      (eval-buffer))))

(use-package emnode
  :load-path "/m/src/emnode"
  :config
  (progn
    (setq emnode:*log-level* emnode:+log-none+)
    (emnode-stop 9999)
    (emnode-start (lambda (httpcon)
                    (emnode-hostpath-dispatcher httpcon *emnode-routes*))
                  :port 9999)))

Try:

curl 0:9999/eval/ -d 'message-box "Hello World"'
curl 0:9999/eval -d '(message-box "Hello") (message-box "World)"'
curl 0:9999/open//tmp/
echo '(message-box "Hello") (message-box "World")' >! /tmp/tmp.el
curl 0:9999/exec//tmp/tmp.el

TODOs

  • Clean-up APIs, re-organize to have good convention.

  • Better names

  • Higher level APIs.

Documentation

  • Get argument: emnode:http-get-arg

  • HTTP data/message/body: emnode:http-data