chickadee » uri-dispatch

Outdated egg!

This is an egg for CHICKEN 4, the unsupported old release. You're almost certainly looking for the CHICKEN 5 version of this egg, if it exists.

If it does not exist, there may be equivalent functionality provided by another egg; have a look at the egg index. Otherwise, please consider porting this egg to the current version of CHICKEN.

Uri-dispatch

Caution: This egg doesn't work with CHICKEN >= 4.7.4.

Introduction

uri-dispatch is a simple mechanism to dispatch uris to procedures. This is useful for webprogramming where you might want to map uris of a certain kind to procedures that implement the logic for those uris.

Examples

(use spiffy intarweb uri-common uri-dispatch)

(module example
  (echo tabulate)
  (import scheme chicken srfi-1 extras)
  (require-library spiffy)
  (import (only spiffy send-status))

  (define (tabulate #!optional (start "0") (steps "10") #!rest rest)
    (send-status 200 (sprintf "tabulate called: ~A" (iota (string->number steps) (string->number start)))))

  (define (echo . args)
    (send-status 200 (sprintf "echo: ~A" args))))

(define (outsidemodule . args) (send-status 200 "Outside module")) 

(vhost-map `(("localhost" . ,(lambda (continue)
                              (parameterize ((handle-not-found  (lambda (path) (dispatch-uri (request-uri (current-request)))))
                                             (dispatch-error (lambda path (send-status 404 (sprintf "Path not found: ~A" path)))))
                                (continue))))))
(start-server)


;;Now start the server and visit the following pages:
;;* http://localhost:8080/example/tabulate/2/10/
;;* http://localhost:8080/example/tabulate/2/20/
;;* http://localhost:8080/example/echo/this/please
;;* http://localhost:8080/outsidemodule
;;* http://localhost:8080/i/do/not/exist

Authors

David Krentzlin

Requirements

Requires the uri-common and environments extensions.

Documentation

dispatch-uri URIprocedure

The main interface to dispatch-uri. This procedure invokes the dispatch-mechanism with the supplied uri. The dispatch-algorithm is implemented as follows:

(Note See also the whitelisting-section, to learn how to limit the exposure of procdures)

  • The path is empty. It checks if default-dispatch-target is bound to a procedure. If it is, then it is invoked. If it is not, then dispatch-error is invoked.
  • The path has exactly one element. It assumes that this element is the name of a thunk that was defined outside a module. If such a thunk exists it is invoked. If no such a thunk exists dispatch-error.is invoked.
  • The path contains at least two elements.
    • It checks if the second element is a procedure defined in a module named by the first element. So if it sees (foo bar) it tries to find the procedure bar inside the module foo. If the procedure exists it is invoked with the rest of the elements as arguments.
    • If it does not exist, it interpretes the first element as the name of a procedure that was defined outside any module. If such a procedure exists, it is invoked passing the rest of the elements as arguments. If no such procedure exists dispatch-error is invoked with the full path as arguments. The path is applied to the procedure so you can use for example dsssl-style lambda-lists to declare optional arguments or a rest-argument.

All those lookups are done in the current dispatch-environment, which can be parameterized.

Whitelisting

Though nice for development it is not advisable to allow everybody out there to invoke abritary procedures of your application. So you might want to whitelist only those procedures that really acts as the interface of your application.

To enable whitelisting you simply parameterize the whitelist parameter with your whitelisting-specification. If a procedure is requested that does exist but is not whitelisted dispatch-error is invoked.

Whitelisting specification

The whitelist allows to selectivly whitelist procedures modules and procedures inside modules. The examples explain all three cases

(whitelist '(proc1 proc2 proc3)) 

This will whitelist the procedures proc1..proc3. Those procedures must be defined outside a module.

(whitelist '((mod1 . (proc1 proc2))

This will whitelist the procedures proc1 and proc2 that must reside inside the module mod1.

(whitelist '((mod1 . *))

This will whitelist all procedures inside the module mod1.

Of course you can mix those declarations.

whitelistparameter

The parameter holding the whitelist. It defaults to #f which means whitelisting is disabled.

dispatch-errorparameter

If no handler for a uri can be found, the dispatcher will invoke the procedure that dispatch-error is currently parameterized with. NOTE dispatch-error is also invoked if the requested handler exists but is not whitelisted. Defaults to (constantly #f).

default-dispatch-targetparameter

A thunk that is invoke when the uri-path was empty. If set to #f then an empty path leads to the invocation of dispatch-error. Defaults to #f.

dispatch-environmentparameter

The environment that is used to lookup the procedures. It defaults to interaction-environment.

License

  Copyright (c) <2009> David Krentzlin <david@lisp-unleashed.de>

  Permission is hereby granted, free of charge, to any person
  obtaining a copy of this software and associated documentation
  files (the "Software"), to deal in the Software without
  restriction, including without limitation the rights to use,
  copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the
  Software is furnished to do so, subject to the following
  conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  OTHER DEALINGS IN THE SOFTWARE.

Contents »