@peccul is peccu

(love peccu '(emacs lisp cat outdoor bicycle mac linux coffee))

CavemanでWebSocketしつつslime-connectでデバッグ

cavemanでwebsocket-driverを読み込んで、defrouteにwebsocket-driver:make-serverを入れるとよい。

前提

caveman2:make-projectでひな形を作成している。

(ql:quickload :caveman2)
(caveman2:make-project #P"/path/to/myapp/"
                       :author "<Your full name>")

参考:CavemanのQuickstart

システムにwebsocket-driverとswankを追加する

asdファイルのdefsystemに記載されている:depends-onに:websocket-driver:swankを追加しておく。

websocketのルートを書く

websocket-driverのサンプルを動かすならこんな感じになる。

(defroute "/echo" ()
  (format t "env: ~a~%" (request-env *request*))
  (let ((ws (make-server (request-env *request*))))
    (on :message ws
      (lambda (message)
        (format t "~a~%" message)
        (send ws message)))
    (on :open ws
      (lambda ()
        (format t "Connected.~%")))
    (on :error ws
      (lambda (error)
        (format t "Got an error: ~S~%" error)))
    (on :close ws
      (lambda (code reason)
        (format t "Closed because '~A' (Code=~A)~%" reason code)))
    (lambda (responder)
      (declare (ignore responder))
      (start-connection ws))))

Swankサーバーの起動

asdファイルのdefsystemにある:componentsの:module “src"に(:file "swank")を追加して、

以下の内容のsrc/swank.lispを作成する。

(in-package :cl-user)
(defpackage no-name-server.swank
  (:use :cl
        :swank))
(in-package :no-name-server.swank)

(swank:create-server :port 4005)

ポート番号は環境変数から取得するように書いた方がいいと思ってる。

参考: The Common Lisp Cookbook - Interfacing with your OSのmy-getenv

cavemanの起動

起動するときはclackupを使う。(ros install clack)

APP_ENV=development clackup --server :woo --port 5000 app.lisp

caveman2:make-projectでパスの通っていない場所にひな形を作成した場合は ros tap tap path-to.asdでシステムにパスを通しておく必要がある。(ros install t-sin/ros-tap)

github.com

slime-connectで接続

Slimeが設定されたEmacsM-x slime-connect を実行すると接続先IPとポートを聞いてくるので入力すると、 上記cavemanの実行している環境にREPLで入れる。

クライアント(JS)の実装

クライアント側はサンプルそのまま。

var ws = null;
function connect() {
  ws = new WebSocket("ws://localhost:5000/echo");
  ws.onmessage = function(evt) {
    console.log(evt.data);
  };
}
function send(message) {
  ws.send(message)
}

その他

cavemanでenvを取り出す方法がわからなくて悩んで探して (request-env *request*)にたどり着いたので記録。

broadcastするにはwsを保持して全てにsendかな。

認証するなら以下の記事がわかりやすい。

blog.stratumsecurity.com

以下の3種類が取り上げられていた。