Skip to content

Instantly share code, notes, and snippets.

@svetlyak40wt
Created July 20, 2020 16:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save svetlyak40wt/855319ce474b69fa3f6b00bcb0b22db4 to your computer and use it in GitHub Desktop.
Save svetlyak40wt/855319ce474b69fa3f6b00bcb0b22db4 to your computer and use it in GitHub Desktop.
;; This example was created to help the author of this thread:
;; https://www.reddit.com/r/Common_Lisp/comments/hu019r/what_is_the_recommended_way_to_readunderstand/
;; Before loading this code, do this in the REPL:
;; (ql:quickload '(log4cl spinneret clack lack))
(defpackage #:server-side
(:use #:cl))
(in-package server-side)
(defun render-page ()
(spinneret:with-html-string
(:html
(:head
(:script "
var source = new EventSource('/events');
source.addEventListener('message', function(e) {
var events = document.getElementById('events')
var new_element = document.createElement('li')
new_element.innerText = e.data;
events.appendChild(new_element)
}, false);
"))
(:body
(:h1 "Server-side events Clack example")
(:h2 "Events:")
(:ul :id "events")))))
(defun main-app (env)
(declare (ignorable env))
(list 200 '(:content-type "text/html")
(list (render-page))))
(defun events-handler (env)
(declare (ignorable env))
(let ((output (getf env :raw-body)))
(lambda (handle-normal-response)
(declare (ignorable handle-normal-response))
(format output "HTTP/1.1~C~C" #\Return #\Newline)
(format output "Content-Type: text/event-stream~C~C" #\Return #\Newline)
(format output "~C~C" #\Return #\Newline)
(format output "~C~C" #\Return #\Newline)
(force-output output)
(handler-case
(loop for i from 1 upto 1000
do (log:info "Returning event" i)
(format output "data: Event ~A~%~%" i)
(force-output output)
(sleep 1))
(sb-int:broken-pipe ()
;; This condition will be signaled if user will close the "tab"
(log:info "Connection was closed")
nil)))))
(defun make-app ()
(lack:builder
(:mount "/events"
'events-handler)
'main-app))
(defvar *server* nil)
(defun start-server (&key (port 8080))
(when *server*
(error "Server already started"))
(setf *server*
(clack:clackup (make-app)
:port port)))
(defun stop-server ()
(when *server*
(clack:stop *server*)
(setf *server*
nil)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment