{ (define LIBNAME "Scheme Web Servlets") (include "head.tinc") }
The teachpack servlet.ss
provides structures and
functions for building Web servlets in Scheme. The data definitions
represent HTTP requests and Web page responses using these two structures:
(define-struct request (method uri headers bindings host-ip client-ip))
(define-struct response/full (code message seconds mime extras body))
constrained as follows:
Env = (listof (cons Symbol String)) Request = (make-request (union 'get 'post) URL Env Env String String) ;; (search for "net" in Help Desk) Response = (union X-expression ;; represent XHTML (search for "XML" in help-desk) (cons String (listof String)) ;; where the first string is the mime type from RFC 2822, often ;; "text/html", and the rest of the strings provide the document's ;; content. (make-response/full N String N String Env (listof String)) ;; where the fields are interpreted as follows: ;; code indicates the HTTP response code. ;; message describes the code in human language. ;; seconds indicates the origination time of the ;; response. Use (current-seconds) for dynamically created responses. ;; mime indicates the response type. ;; extras is an environment with extra headers for redirects, authentication, or cookies. ;; body is the message body. Suspender = String -> Response
The following functions empower servlets to interact with a Web browser:
{(idx build-suspender)} :
(listof X-expr[HTML]) (listof X-expr[HTML]) [Env] [Env] -> Suspender
head
and
body
tags of the constructed page.
{(idx send/suspend)} : Suspender -> Request
{(idx send/finish)} : Response -> Void
{(idx initial-request)} : Request
{(idx extract-binding/single)} : Symbol Env -> string
{(idx extract-bindings)} : Symbol Env -> (listof String)
{(idx extract-string)} : String Env -> (listof String)
{(idx exists-binding?)} : Symbol Env -> Boolean
{(idx extract-user-pass)} : Env -> (union false (cons string string))
Here is a sample script that permits consumers to login to a site:
; Request -> Request (define (get-login-information request0) (let* ([bindings (request-bindings request0)] [name (extract-bindings 'Name bindings)] [form '((input ([type "text"][name "Name"][value "{(include "foot.tinc")}"])) (br) (input ([type "password"][name "Passwd"])) (br) (input ([type "submit"][value "Login"])))]) (if (null? name) (send/suspend (build-suspender '("Login") form)) (send/suspend (build-suspender '("Repeat Login") `(("Dear " ,(car name) " your username didn't match your password. Please try again." (br)) ,@form)))))) ; Request -> Void (define (check-login-information request) (let* ([bindings (request-bindings request)] [name (extract-binding/single 'Name bindings)] [passwd (extract-binding/single 'Passwd bindings)]) (if (and (string=? "Paul" name) (string=? "Portland" passwd)) request (check-login-information (get-login-information request))))) ; Request -> Void (define (welcome request) (let ([bindings (request-bindings request)]) (send/finish `(html ,(extract-binding/single 'Name bindings) " Thanks for using our service." " We're glad you recalled that your password is " ,(extract-binding/single 'Passwd bindings))))) ; RUN: (welcome (check-login-information (get-login-information initial-request)))