Portable websockets for Common Lisp using usocket.
Install with quicklisp.
(ql:quickload 'portal)
Resources are identified by their path in the URL.
A simple echo server.
(pws:define-resource "/echo"
:open (lambda (websocket)
(pws:send websocket "Welcome to echo server."))
:message (lambda (websocket message)
(sleep 1)
(pws:send websocket message)
(sleep 1)
(pws:send websocket message)))
You can also define :close
function and a :error
function in case something goes wrong in your other functions. You can’t send any more messages after a close has begun.
(defparameter server
(pws:server 4433))
Now connect to ws://localhost:4433/echo
in a websocket tester and start echoing.
You can add a :multi-thread
argument to give each client its own thread.
At any point, you can close a client websocket.
(pws:close websocket)
To stop severing:
(pws:server-close server)
It is just a thread!
These two methods are separate, You can both, neither, or any combination.
When defining a resource path, you can pass a :error
argument with a function that takes the websocket and the condition that occurred. Do whatever you want here. It is called when there is an error in your :open
, :message
, or :close
function.
There is a variable: pws:*debug-on-error*
; when it is non-nil, the debugger will be entered when there is a problem with one of your handler functions.
it is bound to t
by default.
Here is another example, this time using the :error
function sends the error over the websocket instead of entering the debugger, and the :close
just prints to the Lisp console.
;; prevent entering debugger
(setq pws:*debug-on-error* nil)
(pws:define-resource "/err"
:open (lambda (socket)
(pws:send socket "Welcome to error server."))
:message (lambda (socket message)
;; error because message is a string
(pws:send socket (1+ message)))
:error (lambda (socket condition)
;; echo error to websocket
(pws:send socket condition))
:close (lambda (socket)
(declare (ignore socket))
(print "Socket leaving error server.")))
If you find any bugs of have any issues (installing, using, questions, adhering to RFC 6455) use the Github issue tracker.
If you want to contact me about collaboration, licensing, etc. You can use the email in portal.asd
.