simple-httpd.elはEmacs Lispで書かれたHTTPサーバー。今回はこれを使ってみる。

HTTPサーバの開始

HTTPサーバーを起動するにはhttpd-startを使う。 httpd-startはホストにhttpd-host、 ポートにhttpd-portを用いてmake-network-processを呼び出す。

(httpd-start)

サーブレットの定義

ここで使っているサーブレットとはJavaサーブレットのことではなく、 HTTPリクエストを受け取りレスポンスを返すもののことをサーブレットと表現している。 他のWebフレームワークではリクエストハンドラと呼ばれるものに近い。 defservletマクロを使うとサーブレットを定義する。

(defservlet hello-world.txt text/plain (path)
  (insert "Hello World!"))
簡単な例

上の例では `/hello-world.txt` にリクエストを受けると BODYに `Hello World!` と書かれたレスポンスを返すサーブレット。 defservletは `httpd/hello-world.txt` という名称の関数を定義した 以下はその処理を行なっているdefservletマクロの定義。

(let ((proc-sym (make-symbol "proc"))
      (fname (intern (concat "httpd/" (symbol-name name)))))
  `(defun ,fname (,proc-sym ,@path-query-request &rest ,(cl-gensym))
     (with-httpd-buffer ,proc-sym ,(httpd--stringify mime)
       ,@body))))
simple-httpd.el抜粋

`(concat "httpd/" (symbol-name name)` で関数名を作成してそれをinternしている。 その後 `defun` に展開して関数定義を作成している。 `/hello-world.txt` にリクエストを受けるとこの関数が呼び出されることになる。

リクエストを送信する

実際にリクエストを送信して挙動を確認する。

GET http://127.0.0.1:8080/hello-world.txt

正しくレスポンスが返ってくることがわかる。

定義を変更すると即座に反映される

先ほどのdefservletで作成していた関数をevalしなおすと即座に挙動が変更される。

(defservlet hello-world.txt text/plain (path)
  (insert "yay!!"))
返却する文字列を変更

リクエストを送信して挙動を確認する。

GET http://127.0.0.1:8080/hello-world.txt

変更されたことがわかる。 挙動を変更するためにプロセスを起動しなおす必要はない。

HTTPサーバの停止

(httpd-stop)

まとめ

simple-httpd.elで簡単なAPIを書いた。