2002-08-26 11:15:02 -04:00
|
|
|
;;; http server in the Scheme Shell -*- Scheme -*-
|
|
|
|
|
|
|
|
;;; This file is part of the Scheme Untergrund Networking package.
|
|
|
|
|
|
|
|
;;; Copyright (c) 1995 by Olin Shivers.
|
|
|
|
;;; Copyright (c) 1996-2002 by Mike Sperber.
|
|
|
|
;;; Copyright (c) 2002 by Andreas Bernauer.
|
|
|
|
;;; For copyright information, see the file COPYING which comes with
|
|
|
|
;;; the distribution.
|
|
|
|
|
|
|
|
;;; Path handlers
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;; Path handlers are the guys that actually perform the requested operation
|
|
|
|
;;; on the URL. The handler interface is
|
|
|
|
;;; (handler path-list request)
|
|
|
|
;;; The path-list is a URL path list that is a suffix of REQUEST's url's
|
|
|
|
;;; path-list. Path handlers can decide how to handle an operation by
|
|
|
|
;;; recursively keying off of the elements in path-list.
|
|
|
|
;;;
|
|
|
|
;;; The object-oriented view:
|
|
|
|
;;; One way to look at this is to think of the request's METHOD as a
|
2002-09-22 11:41:41 -04:00
|
|
|
;;; generic operation on the URL. Recursive request handlers do method
|
2002-08-26 11:15:02 -04:00
|
|
|
;;; lookup to determine how to implement a given operation on a particular
|
|
|
|
;;; path.
|
|
|
|
;;;
|
2005-04-04 16:57:36 -04:00
|
|
|
;;; The REQUEST is a request record, as defined in request.scm, containing
|
2002-09-22 11:41:41 -04:00
|
|
|
;;; the details of the client request.
|
2000-09-26 10:35:26 -04:00
|
|
|
|
2002-09-22 11:41:41 -04:00
|
|
|
;; general request handler combinator:
|
2002-08-22 11:32:03 -04:00
|
|
|
;; predicate: path x request --> boolean
|
|
|
|
;; if #t, handler is called
|
|
|
|
;; if #f, default-handler is called
|
2002-09-22 11:41:41 -04:00
|
|
|
(define (make-predicate-handler predicate handler default-handler)
|
2002-08-22 11:32:03 -04:00
|
|
|
(lambda (path req)
|
|
|
|
(if (predicate path req)
|
|
|
|
(handler path req)
|
|
|
|
(default-handler path req))))
|
|
|
|
|
2002-09-22 11:41:41 -04:00
|
|
|
;; same as MAKE-PREDICATE-HANDLER except that the predicate is only
|
2002-08-22 11:32:03 -04:00
|
|
|
;; called with the path:
|
|
|
|
;; predicate: path --> boolean
|
2002-09-22 11:41:41 -04:00
|
|
|
(define (make-path-predicate-handler predicate handler default-handler)
|
|
|
|
(make-predicate-handler
|
2002-08-22 11:32:03 -04:00
|
|
|
(lambda (path req) (predicate path)) handler default-handler))
|
|
|
|
|
|
|
|
;; selects handler according to host-field of http-request
|
2002-08-27 05:05:16 -04:00
|
|
|
(define (make-host-name-handler hostname handler default-handler)
|
2002-09-22 11:41:41 -04:00
|
|
|
(make-predicate-handler
|
2002-08-27 05:05:16 -04:00
|
|
|
(lambda (path req)
|
|
|
|
;; we expect only one host-header-field
|
2004-08-14 18:03:19 -04:00
|
|
|
(let ((maybe-val (get-header (request-headers req) 'host)))
|
|
|
|
(if maybe-val
|
|
|
|
(let ((val (string-trim maybe-val)))
|
|
|
|
(or (string-ci=? hostname val)
|
|
|
|
(string-prefix-ci? (string-append hostname ":") val)))
|
|
|
|
(http-error (status-code bad-request) "No Host: header"))))
|
2002-08-27 05:05:16 -04:00
|
|
|
handler default-handler))
|
2002-08-22 11:32:03 -04:00
|
|
|
|
|
|
|
;; selects handler according to path-prefix
|
|
|
|
;; if path-prefix matches, handler is called without the path-prefix
|
|
|
|
(define (make-path-prefix-handler path-prefix handler default-handler)
|
|
|
|
(lambda (path req)
|
2003-01-20 11:24:29 -05:00
|
|
|
(if (and (pair? path) (string=? path-prefix (car path)))
|
2002-08-22 11:32:03 -04:00
|
|
|
(handler (cdr path) req)
|
|
|
|
(default-handler path req))))
|
2000-09-26 10:35:26 -04:00
|
|
|
|
2002-08-22 11:32:03 -04:00
|
|
|
;;; (alist-path-dispatcher handler-alist default-handler) -> handler
|
2000-09-26 10:35:26 -04:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
2002-09-22 11:41:41 -04:00
|
|
|
;;; This function creates a table-driven request handler that dispatches off
|
2000-09-26 10:35:26 -04:00
|
|
|
;;; of the car of the request path. The handler uses the car to index into
|
2002-09-22 11:41:41 -04:00
|
|
|
;;; a request handler alist. If it finds a hit, it recurses using the table's
|
|
|
|
;;; request handler. If no hits, it handles the path with a default handler.
|
2000-09-26 10:35:26 -04:00
|
|
|
;;; An alist handler is passed the tail of the original path; the
|
|
|
|
;;; default handler gets the entire original path.
|
|
|
|
;;;
|
|
|
|
;;; This procedure is how you say: "If the first element of the URL's
|
|
|
|
;;; path is 'foo', do X; if it's 'bar', do Y; otherwise, do Z."
|
|
|
|
|
|
|
|
(define (alist-path-dispatcher handler-alist default-handler)
|
2002-08-22 11:32:03 -04:00
|
|
|
(fold-right
|
|
|
|
(lambda (handler-pair default-handler)
|
|
|
|
(make-path-prefix-handler
|
|
|
|
(car handler-pair)
|
|
|
|
(cdr handler-pair)
|
|
|
|
default-handler))
|
|
|
|
default-handler
|
|
|
|
handler-alist))
|
2002-08-27 05:42:02 -04:00
|
|
|
|
2002-09-22 11:41:41 -04:00
|
|
|
;;; The null request handler -- handles nothing, sends back an error response.
|
|
|
|
;;; Can be useful as the default in table-driven request handlers.
|
2002-08-27 05:42:02 -04:00
|
|
|
|
2002-09-22 11:41:41 -04:00
|
|
|
(define (null-request-handler path req)
|
2003-01-10 04:52:35 -05:00
|
|
|
(make-error-response (status-code not-found) req))
|