sb-fastcgi is a Common Lisp FastCGI API Toolkit for SBCL, It contains a group of low-level API’s which like the c API of FastCGI, a group of fcgi-server implementations, and a high-level WSGI style interface.
You can get it from https://github.com/KDr2/sb-fastcgi .
If you want use sb-fastcgi on some other Common Lisp implementations rather than SBCL, you can refer to CL-FastCGI
Frist, install SBCL and sb-fastcgi asdf-package. Then get a share object of FastCGI (usually named libfcgi.so*). You can get it by installing the package libfcgi-dev in your box, or by exceuting command make under the directory sb-fastcgi/c_src.
Now, you need load the asdf-package and the libfcgi.so:
;;; A1. load sb-fascgi asdf
(asdf:operate 'asdf:load-op 'sb-fastcgi)
;;; A2. load libfcgi.so
(sb-fastcgi:load-libfcgi "/usr/lib/libfcgi.so.0.0.0")
sb-fastcgi provides a group of low-level API’s corresponding to the c-API of FastCGI, see the list below:
- fcgx-init
- fcgx-init-request
- fcgx-accept
- fcgx-finish
- fcgx-puts
- fcgx-read
- fcgx-read-all
- fcgx-getparam
- fcgx-getenv
Usually you need not use the first four functions (fcgx-init / fcgx-init-request / fcgx-accept / fcgx-finish), there are some fcgi-server implementations in sb-fastcgi(will be demonstrated in next section), you can use these implementations rather than use the first four functions in the list above.
The last three functions (fcgx-puts / fcgx-getparam / fcgx-getenv) is very useful :
fcgx-puts is for writting content to a http-response, e.g. use (fcgx-puts req "CONETNT") to write the string “CONTENT” to the http-response corresponding to http-request req.
fcgx-read(-all) is for reading data from the input stream of the http-request. usually, you must use it to get the POST data.
fcgx-getparam is for getting parameter from the http-request header, e.g. (fcgx-getparam req "QUERY_STRING") will return the QUERY_STRING of the http-request req.
fcgx-getenv is like fcgx-getparam, (fcgx-getenv req) return all the headers/parameters of the http-request req, in a assoc-list format.
In this section we will finish our first FCGI-APP with sb-fastcgi.
First we write a function called simple-app, which has one argument(the http-request), in this function, we use fcgx-puts to write a simple string to the http-response:
(defun simple-app (req)
(let ((c (format nil "Content-Type: text/plain
Hello, I am a fcgi-program using Common-Lisp")))
(sb-fastcgi:fcgx-puts req c)))
Then we can run this simple-app:
(sb-fastcgi:simple-server #'simple-app)
the simple-server runs the simple-app on stdin, so you can integrate it with apache via mod_fastcgi, or use spawn-fcgi to run it on a listening socket.
There are four fcgi-server implementations in sb-fastcgi now:
(sb-fastcgi:simple-server #'simple-app)
(sb-fastcgi:simple-server-threaded #'simple-app)
(sb-fastcgi:socket-server #'simple-app)
(sb-fastcgi:socket-server-threaded #'simple-app)
See sb-fastcgi/test.lisp for more examples.
If you do not know WSGI, get to know it first, and then see this example:
;;; C1. app using WSGI-style interface
(defun wsgi-app (env start-response)
(funcall start-response "200 OK" '(("X-author" . "Who?")
("Content-Type" . "text/html")))
(list "ENV (show in alist format): <br>" env))
;;; C2. run app above on 0.0.0.0:9000 (by default)
(defun run-app-1 ()
(sb-fastcgi:socket-server-threaded
(sb-fastcgi:make-serve-function #'wsgi-app)
:inet-addr "0.0.0.0"
:port 9000))
The wsgi-app can be nested:
;;; C4. a nested WSGI-style app example
(defun wsgi-app2 (app)
(lambda (env start-response)
(let ((content-0 (funcall app env start-response))) ; call outter app
;;reset X-author in headers
(funcall start-response nil '(("X-author" . "KDr2!")))
(append '("Prefix <br/>") content-0 '("<br/>Postfix")))))
;;; C5. run (test-app1 test-app2) nested app
(defun run-app-2 ()
(sb-fastcgi:socket-server-threaded
(sb-fastcgi:make-serve-function (wsgi-app2 #'wsgi-app))
:inet-addr "0.0.0.0"
:port 9000))
Nested wsgi-style-app make you webapp like an onion, and you can add/remove a layer from it conveniently, use sb-fastcgi’s WSGI-Style API you can build/run your webapp or webapp-framework easily.
See sb-fastcgi/test.lisp for more examples.
- on github : https://github.com/KDr2/sb-fastcgi
- email me : killy.draw<@>gmail.com