File: servlet.html

package info (click to toggle)
drscheme 1%3A352-6
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 71,608 kB
  • ctags: 55,284
  • sloc: ansic: 278,966; cpp: 63,318; sh: 32,265; lisp: 14,530; asm: 7,327; makefile: 4,846; pascal: 4,363; perl: 2,920; java: 1,632; yacc: 755; lex: 258; sed: 93; xml: 12
file content (149 lines) | stat: -rw-r--r-- 5,756 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
<html>
<head>
<title>Teachpack : Scheme Web Servlets</title>
</head>
<body bgcolor="#ffffff" text="#000000"
      link="#009900" vlink="#007700" alink="#cc0000">

<a href="index.html">Teachpacks for How to Design Programs</a>

<h1>Scheme Web Servlets</h1>

<hr> <h3><a name="servlet.ss">servlet.ss</a></h3> <!-- DOCNOTE="teach=servlet.ss" -->

<p>The teachpack <code>servlet.ss</code> provides structures and
functions for building Web servlets in Scheme. The data definitions
represent HTTP requests and Web page responses using these two structures:</p>

<pre>
 <code>
  (define-struct request (method uri headers bindings host-ip client-ip))

  (define-struct response/full (code message seconds mime extras body))
 </code>
</pre>

constrained as follows:

<pre>
  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
</pre>

<p>The following functions empower servlets to interact with a Web browser:

<ul>
  <li><code><a name="build-suspender">build-suspender</a> :
         (listof X-expr[HTML]) (listof X-expr[HTML]) [Env] [Env] -> Suspender</code>
    <br>builds a suspender from lists of X-expressions for the head and the
    body of a Web page. The body is put into a form context. The function
    optionally consumes attributes for the <code>head</code> and
    <code>body</code> tags of the constructed page.

  <li><code><a name="send/suspend">send/suspend</a> : Suspender -> Request</code> <br />
  sends the suspender's page to the browser and waits for the browser's request.

  <li><code><a name="send/finish">send/finish</a> : Response -> Void</code> <br />
  sends the response to the browser and terminates the servlet (and the
  REPL,  when used inside of DrScheme).

  <li><code><a name="initial-request">initial-request</a> : Request</code> <br /> a fictitious request
  that looks like a browser initially requested the servlet's URL.

  <li><code><a name="extract-binding/single">extract-binding/single</a> : Symbol Env -> string</code><br>
  consumes the symbol of an HTML form field and a bindings environment.  It
  returns the only value associated with the given symbol.  It raises an
  exception when zero or more than one input is provided for a single symbol.

  <li><code><a name="extract-bindings">extract-bindings</a> : Symbol Env -> (listof String)</code>
  <br /> consumes a symbol and a bindings environment.  It produces all the
  values associated with that symbol.

  <li><code><a name="extract-string">extract-string</a> : String Env -> (listof String)</code>
  <br /> consumes a string and a bindings environment.  It produces all the
  values associated with that string.

  <li><code><a name="exists-binding?">exists-binding?</a> : Symbol Env -> Boolean</code> <br>
  consumes a symbol and a bindings environment.  It produces true when the
  symbol is bound.  This is useful for checkboxes.

  <li><code><a name="extract-user-pass">extract-user-pass</a> : Env -> (union false (cons string string))</code>
  <br>extracts the username and the password from the HTTP headers environment,
  if provided.
  Servlets may use this function to implement password based
  authentication.
</ul>

<p>Here is a sample script that permits consumers to login to a site:

<pre>
; Request -> Request
(define (get-login-information request0)
  (let* ([bindings (request-bindings request0)]
         [name (extract-bindings 'Name bindings)]
         [form '((input ([type "text"][name "Name"][value "<Last Name>"]))
                 (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)))
</pre>

<br>
<br>
</body>
</html>