reblocks-file-server - A Reblocks extension allowing to create routes for serving static files from disk.

REBLOCKS-FILE-SERVER ASDF System Details

Installation

You can install this library from Quicklisp, but you want to receive updates quickly, then install it from Ultralisp.org:

(ql-dist:install-dist "http://dist.ultralisp.org/"
                      :prompt nil)
(ql:quickload :reblocks-file-server)

Usage

A small demo of what this library does:

Here is an example on how this library can be used. All you need is to add a results of call to file-server function call to you Reblocks application's routes.

(defapp app
  :prefix "/"
  :routes ((page ("/" :name "index")
             (make-landing-page))
           
           ;; On /documents/
           (file-server "/sources/"
                        :name "sources"
                        :root (asdf:system-relative-pathname :my-app "./"))))

In this example, we will show sources of the my-app ASDF library starting from path /sources/, ie if user opens your site like https://example.com/sources/, he will see content of the directory returned by (asdf:system-relative-pathname :my-app "./").

By default, all files and directories are shown. If you want to hide something from user, you might provide a list of functions which accepts a pathname and returns :ALLOW :DENY or NIL.

Here is a relatively complex example of filtering:

(file-server "/sources/"
             :name "sources"
             :root (asdf:system-relative-pathname :my-app "./")
             :filter (list
                                ;; This is how to hide a file inside the current
                                ;; directory
                      (deny #P"main.lisp")
                      ;; Or inside some particular directory
                      (deny #P"pages/*.fasl")
                      ;; Also you might whitelist some directories
                      ;; and files:
                      (allow #P"**/" ;; Allow to show any directory
                             #P"**/*.lisp"
                             #P"favicons/*.png"
                             #P"favicons/*.ico")
                      ;; and then deny the rest.
                      ;; 
                      ;; We need this part because by default
                      ;; all files are allowed:
                      (deny-all)))

Here we've used these utils functions:

Read more about how filtering work in the Filtering section.

Filtering

FILTER argument of file-server function accepts a function or a list of functions where each function should accept a pathname relative to the ROOT argument given to the file-server function and return :ALLOW, :DENY or NIL.

When function returns :ALLOW or :DENY, processing is stopped and user see either content or 404 error page. If filter function returns NIL, then other filter functions are checked.

If no functions matched the current path, then reblocks file server consider it to be allowed. So we have a black-list mode as a default - if you want something to be denied - deny it!

In this example we deny access to a config.lisp file and fasl files in all directories. All other files and directories will be allowed:

(list
 (deny #P"config.lisp")
 (deny #P"**/*.fasl"))

Here I've used deny helper which accepts a template pathname and returns a function which checks given pathname to this template pathname.

To switch to the white-list mode, you need to add a last rule which will deny access to any file or directory. Use deny-all helper for this.

In the next example we deny access to all files and directories but allow listing of any directory and files with lisp extension:

(list
 (allow ;; Allow to show any directory
        #P"**/"
        ;; Allow any lisp file
        #P"**/*.lisp")
 (deny-all))

If you need some special filtering, then you can use allow-if or deny-if functions. This is an example how to define a filter to hide empty directories:

(deny-if (lambda (path)
           (and
            (cl-fad:directory-pathname-p path)
            (uiop:emptyp
             (cl-fad:list-directory
              (merge-pathnames path
                               (asdf:system-relative-pathname :my-app "./")))))))

API

REBLOCKS-FILE-SERVER/CORE

Classes

FILE-SERVER-ROUTE

Readers

reader
(:filter = (lambda (pathname) (declare (ignore pathname)) t))

A regular expression to show only selected files.

When nil, directory contents is not shown.

Functions

function
uri-path &key name (route-class 'file-server-route) (root (uiop/pathname:ensure-directory-pathname \*default-pathname-defaults\*)) (dir-listing t) (filter nil)

Returns a file-server-route object suitable for including into Reblocks routes hierarchy.

FILTER argument should be a NIL or a list of filter functions which accept a pathname and return :ALLOW :DENY or NIL.

function
route-path directory-relative-path filter &key directories-first-p

Returns a list of files in the directory. All items of the list are relative.

REBLOCKS-FILE-SERVER/UTILS

Functions

function
pathname &rest more-pathnames

Returns a function of one argument which will check this argument against given pathnames and if there is match, returns :ALLOW.

Returns a function of one argument which will check an argument against given predicate and if it returns T, returns :ALLOW.

function
pathname &rest more-pathnames

Returns a function of one argument which will check this argument against given pathnames and if there is match, returns :DENY.

Returns a function which will deny all files.

Returns a function of one argument which will check an argument against given predicate and if it returns T, returns :DENY.

Types

(FUNCTION (PATHNAME) (VALUES (MEMBER :ALLOW :DENY NIL)))