How to get started with Sven's minimal Common Lisp s-http-server.
This page assumes that you are using LispWorks OS X Personal Edition 4.4.6 though s-http-server is written in portable ANSI Common Lisp, and should work out of the box in other environments.
You have a working asdf intallation. You can get asdf here and follow this installation instructions.
You will need to get s-http-server source from Sven's homepage. Specifically, if you use darcs, wou will need to cd to your chosen destination directory and issue the following commands:
darcs get http://www.beta9.be/darcs/s-http-server
darcs get http://www.beta9.be/darcs/s-sysdeps
darcs get http://www.beta9.be/darcs/s-base-64
darcs get http://www.beta9.be/darcs/s-utils
darcs get http://www.beta9.be/darcs/puri
In order for asdf to be able to locate each of the required components, you will need to create a symbolic link to each of the .asd file, as in:
ln -s /Users/verec/workspace/WebLisp/s-http-server/s-http-server.asd .
ln -s /Users/verec/workspace/WebLisp/s-sysdeps/s-sysdeps.asd .
ln -s /Users/verec/workspace/WebLisp/s-base-64/s-base-64.asd .
ln -s /Users/verec/workspace/WebLisp/s-utils/s-utils.asd .
ln -s /Users/verec/workspace/WebLisp/puri/puri.asd .
Where the final . (dot) of the ln command refers to the current directory, that which you specified
as your asdf repository when first installing asdf.
(setf *print-case* :downcase) ;; tell Lisp to quit SHOUTING
(load (compile-file "/Users/verec/workspace/WebLisp/asdf.lisp"))
(pushnew "/Users/verec/workspace/registry/" asdf:*central-registry* :test #'equal)
(asdf:operate 'asdf:compile-op :asdf-install)
(asdf:operate 'asdf:load-op :asdf-install)
(asdf:oos 'asdf:load-op :s-http-server)
Note that at this time, s-http-server is not asdf-intallable.
We set to create a plain vanilla server:
CL-USER 1 > (asdf:oos 'asdf:load-op :s-http-server)
CL-USER 2 > (in-package :s-http-server)
#<The S-HTTP-SERVER package, 91/128 internal, 29/64 external>
S-HTTP-SERVER 3 > (defvar *server* (make-s-http-server :name "Hello-World Server"))
*server*
S-HTTP-SERVER 4 > (inspect *server*)
#<s-http-server "Hello-World Server" port 1701 not running 1009578B>
is a s-http-server
port 1701
name "Hello-World Server"
debug-mode t
server-process nil
log-stream #<editor::rubber-stream #<editor:buffer CAPI
interactive-pane 3> 10EC2907>
contexts ((s-http-server-handler "/s-http-server" :builtin))
S-HTTP-SERVER 6 : Inspect 2 > :q
We can now check whether everything works. Since the server object is instantiated but not started yet, we get:
We now activate the server:
S-HTTP-SERVER 8 > (start-server *server*)
;; HELLO-WORLD SERVER: Started a new server on port 1701
#<s-http-server "Hello-World Server" port 1701 running 10ED58DF>
S-HTTP-SERVER 9 > (inspect *server*)
#<s-http-server "Hello-World Server" port 1701 running 10ED58DF>
is a s-http-server
port 1701
name "Hello-World Server"
debug-mode t
server-process #<mp:process Name "Hello-World Server"
Priority 3 State "Waiting for connection">
log-stream #<editor::rubber-stream #<editor:buffer CAPI
interactive-pane 3> 10EC2907>
contexts ((s-http-server-handler "/s-http-server" :builtin))
S-HTTP-SERVER 10 : Inspect 1 > :q
We can now add a "static page" server. Note that static-resource-handler is builtin within s-http-server.
S-HTTP-SERVER 13 > (register-context-handler *server*
"/my-site"
'static-resource-handler
:arguments
'("/Users/verec/Sites/lisp/tutorials/svc/"))
But things get really interesting when we can add dynamic contents. For this, we define our own dynamic content handler:
(in-package :s-http-server)
(defun dynamic-context-handler (s-http-server handler http-request stream)
"The Dynamic Version that takes over when no default applies."
(logm s-http-server "Running dynamic s-http-server handler")
(let ((body (with-output-to-string (out)
(format out "<p>Active handler binding is ~s for path ~s</p>"
handler
(get-path http-request)))))
(standard-http-html-message-response http-request stream "S-HTTP-SERVER" body)
t))
And register it with s-http-server:
S-HTTP-SERVER 14 > (register-context-handler *server*
"/"
'dynamic-context-handler
:arguments
'("no one cares, really")
:at-end-p t)
Note the use of the :at-end-p keyword. This is so more specific handlers will get a chance to match the request first, otherwise, the dynamic-context-handler would always be the most specific handler for any possible query.
20060109 JFB added reference to kpax
20051223 JFB first release -- unedited draft