Tuesday, August 11, 2009

Evaluate SHP by URL Path

In the previous version we hardcoded the index.shp path, now we want to get rid of the hardcoding and let the handler find the right script to evaluate.

What we need to do is to abstract the path mapping, below is our first attempt:

;; first convert the url path into a list of path segments
(define (url->path-segments url)
(map path/param-path (url-path url)))

;; then we can append the path-segments to the root path
(define (url->shp-path url path)
(apply build-path path (url->path-segments url)))

;; replace the previous build-path with url->shp-path
(define (make-shp-handler path)
(lambda (request)
(let ((terms (file->values (url->shp-path (request-uri request) path))))
(let ((proc (eval `(lambda (request) . ,terms))))
(proc request))
Missing Default Path

The above looks right but we run into our first error - the default case of "http://localhost/" does not point to "http://localhost/index.shp", and it throws the following error:
build-path: 2nd path element is an empty string; other arguments were: "c:\\shp"
That occurs when we do not handle the default segment of "/". url->path-segments will return '("") in such case. That means any trailing slash will add an additional "" to the path, and we do not want that. What we want is instead of replacing such trailing empty string with the default "index.shp".

To fix that we will do the following:

(define (url->path-segments url (default "index.shp"))
(define (helper segments)
;; if the segment is already null, just return it
;; otherwise, check to see if the last is empty string, if so, replace it with default
(cond ((null? segments) segments)
(let ((segments (reverse segments)))
(reverse (if (equal? (car segments) "")
(cons default (cdr segments))
(helper (map path/param-path (url-path url))))

Now we can load any page that lives under the root paths, and default to index.shp!

No comments:

Post a Comment