Wapp

Check-in [91b5a1ed09]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Update the documentation page to remove all references to the ::Wapp dict. Describe the wapp-set-param, wapp-param-list, and wapp-param-exists interfaces used as an alternative to direct ::Wapp dict access.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 91b5a1ed09660f603649ea1deda372259b09a3e523214580560e7c3cda43c2e2
User & Date: drh 2018-01-30 19:37:46.343
Context
2018-01-30
20:36
Update example scripts to remove uses of the ::wapp dict. Improvements to the documentation. (check-in: 5d5c1559d7 user: drh tags: trunk)
19:37
Update the documentation page to remove all references to the ::Wapp dict. Describe the wapp-set-param, wapp-param-list, and wapp-param-exists interfaces used as an alternative to direct ::Wapp dict access. (check-in: 91b5a1ed09 user: drh tags: trunk)
19:09
Use 307 instead of 302 to redirect. (check-in: d8cc844e83 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to README.md.
23
24
25
26
27
28
29

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

2.0 Hello World!
----------------

Wapp is designed to be easy to use.  A hello-world program is as follows:

>

    package require wapp  ;# OR just "source wapp.tcl"
    proc wapp-default {req} {
       wapp-subst {<h1>Hello, World!</h1>\n}
    }
    wapp-start $::argv

The application defines one or more procedures that accept HTTP requests
and generate appropriate replies.
For an HTTP request where the initial portion of the URI is "abcde", the
procedure named "wapp-page-abcde" will be invoked to construct the reply.
If no such procedure exists, "wapp-default" is invoked instead.  The latter
technique is used for the hello-world example above.

The procedure generates a reply using one or more calls to the "wapp-subst"
command.  Each "wapp-subst" command appends new text to the reply, applying
various substitutions as it goes.  The only substitution in this example is







>
|







|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

2.0 Hello World!
----------------

Wapp is designed to be easy to use.  A hello-world program is as follows:

>
    #!/usr/bin/tclsh
    package require wapp
    proc wapp-default {req} {
       wapp-subst {<h1>Hello, World!</h1>\n}
    }
    wapp-start $::argv

The application defines one or more procedures that accept HTTP requests
and generate appropriate replies.
For an HTTP request where the initial portion of the URI path is "abcde", the
procedure named "wapp-page-abcde" will be invoked to construct the reply.
If no such procedure exists, "wapp-default" is invoked instead.  The latter
technique is used for the hello-world example above.

The procedure generates a reply using one or more calls to the "wapp-subst"
command.  Each "wapp-subst" command appends new text to the reply, applying
various substitutions as it goes.  The only substitution in this example is
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
150
151
152
153
154
155
156
157
158
159
160
161

Then configure your web-server to send SCGI requests to TCL port 9000
for some specific URI, and point your web-browser at that URI.

3.0 A Slightly Longer Example
-----------------------------


Information about each HTTP request is encoded in the global ::wapp

dict variable.  The following sample program shows the information
available in ::wapp.

>
    package require wapp
    proc wapp-default {} {
      set B [wapp-param BASE_URL]
      wapp-trim {
        <h1>Hello, World!</h1>
        <p>See the <a href='%html($B)/env'>Wapp
        Environment</a></p>
      }
    }
    proc wapp-page-env {} {
      global wapp
      wapp-subst {<h1>Wapp Environment</h1>\n<pre>\n}
      foreach var [lsort [dict keys $wapp]] {
        if {[string index $var 0]=="."} continue
        wapp-subst {%html($var) = %html([list [dict get $wapp $var]])\n}
      }
      wapp-subst {</pre>\n}
    }
    wapp-start $::argv

In this application, the default "Hello, World!" page has been extended
with a hyperlink to the /env page.  The "wapp-subst" command has been
replaced by "wapp-trim", which works the same way with the addition that
it removes surplus whitespace from the left margin, so that the generated
HTML text does not come out indented.  The "wapp-index" command uses
a "%html(...)" substitution.  The "..." argument is expanded using the
usual TCL rules, but then the result is escaped so that it is safe to include

in an HTML document.  Other supported substitutions are "%url(...)" for
URLs on the href= and src= attributes of HTML entities, "%qp(...)" for
query parameters, "%string(...)" for string literals within javascript,
and "%unsafe(...)" for direct literal substitution.  As its name implies,
the %unsafe() substitution should be avoid whenever possible.

The /env page is implemented by the "wapp-page-env" proc.  This proc
generates HTML that describes the content of the ::wapp dict.
Keys that begin with "." are for internal use by Wapp and are skipped
for this display.  Notice the use of "wapp-subst" to safely escape text
for inclusion in an HTML document.

4.0 The ::wapp Global Dict
--------------------------

To better understand how the ::wapp dict works, try running the previous
sample program, but extend the /env URL with extra path elements and query
parameters.  For example:
<http://localhost:8080/env/longer/path?q1=5&title=hello+world%21>

Notice how the query parameters in the input URL are decoded and become
elements of the ::wapp dict.  The same thing occurs with POST parameters
and cookies - they are all converted into entries in the ::wapp dict
variable so that the parameters are easily accessible to page generation
procedures.

The ::wapp dict contains additional information about the request,

roughly corresponding to CGI environment variables.  To prevent environment
information from overlapping and overwriting query parameters, all the
environment information uses upper-case names and all query parameters
are required to be lower case.  If an input URL contains an upper-case
query parameter (or POST parameter or cookie), that parameter is silently
omitted from the ::wapp dict.

The ::wapp dict contains the following environment values:

  +  **HTTP\_HOST**  
     The hostname (or IP address) and port that the client used to create
     the current HTTP request.  This is the first part of the request URL,
     right after the "http://" or "https://".  The format for this value
     is "HOST:PORT".  Examples:  "sqlite.org:80" or "127.0.0.1:32172".








>
|
>
|
<














|

|









|
|
|
>
|






|
|



|


|





|
|
|
<

<
>
|




|

|







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
150
151
152
153
154
155
156
157
158
159
160
161
162
163

Then configure your web-server to send SCGI requests to TCL port 9000
for some specific URI, and point your web-browser at that URI.

3.0 A Slightly Longer Example
-----------------------------

Wapp keeps track of various "parameters" or "params" that describe
each HTTP request.  Those parameters are accessible using routines
like "wapp-param _NAME_"
The following sample program gives some examples:


>
    package require wapp
    proc wapp-default {} {
      set B [wapp-param BASE_URL]
      wapp-trim {
        <h1>Hello, World!</h1>
        <p>See the <a href='%html($B)/env'>Wapp
        Environment</a></p>
      }
    }
    proc wapp-page-env {} {
      global wapp
      wapp-subst {<h1>Wapp Environment</h1>\n<pre>\n}
      foreach var [lsort [wapp-param-list]] {
        if {[string index $var 0]=="."} continue
        wapp-subst {%html($var) = %html([list [wapp-param $var]])\n}
      }
      wapp-subst {</pre>\n}
    }
    wapp-start $::argv

In this application, the default "Hello, World!" page has been extended
with a hyperlink to the /env page.  The "wapp-subst" command has been
replaced by "wapp-trim", which works the same way with the addition that
it removes surplus whitespace from the left margin, so that the generated
HTML text does not come out indented.  The "wapp-trim" and "wapp-subst"
commands in this example use "%html(...)" substitutions.  The "..." argument 
is expanded using the usual TCL rules, but then the result is escaped so
that it is safe to include in an HTML document.  Other supported
substitutions are "%url(...)" for
URLs on the href= and src= attributes of HTML entities, "%qp(...)" for
query parameters, "%string(...)" for string literals within javascript,
and "%unsafe(...)" for direct literal substitution.  As its name implies,
the %unsafe() substitution should be avoid whenever possible.

The /env page is implemented by the "wapp-page-env" proc.  This proc
generates HTML that describes all of the query parameters. Parameter names
that begin with "." are for internal use by Wapp and are skipped
for this display.  Notice the use of "wapp-subst" to safely escape text
for inclusion in an HTML document.

4.0 Parameters
--------------------------

To better understand Wapp parameters, try running the previous
sample program, but extend the /env URL with extra path elements and query
parameters.  For example:
<http://localhost:8080/env/longer/path?q1=5&title=hello+world%21>

Notice how the query parameters in the input URL are decoded and become
parameters.  The same thing occurs with POST parameters
and cookies - they are all converted into parameters accessible
using the "wapp-param" interface.



Wapp also provides parameters that describe the execution environment.
These parameter look like CGI environment variables.  To prevent environment
information from overlapping and overwriting query parameters, all the
environment information uses upper-case names and all query parameters
are required to be lower case.  If an input URL contains an upper-case
query parameter (or POST parameter or cookie), that parameter is silently
omitted.

The following environment parameters are always available:

  +  **HTTP\_HOST**  
     The hostname (or IP address) and port that the client used to create
     the current HTTP request.  This is the first part of the request URL,
     right after the "http://" or "https://".  The format for this value
     is "HOST:PORT".  Examples:  "sqlite.org:80" or "127.0.0.1:32172".

200
201
202
203
204
205
206
207
208
209
210
211
212
213
214

  *  **CONTENT\_TYPE**  
     The mimetype of the POST data.  Usually this is
     application/x-www-form-urlencoded.


All of the above are standard CGI environment values.
The following are additional values add by Wapp:


  *  **CONTENT**  
     The raw POST data text.

  +  **BASE\_URL**  
     The text of the request URL through the SCRIPT\_NAME.  This value can







|







202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

  *  **CONTENT\_TYPE**  
     The mimetype of the POST data.  Usually this is
     application/x-www-form-urlencoded.


All of the above are standard CGI environment values.
The following are supplemental environment parameters are added by Wapp:


  *  **CONTENT**  
     The raw POST data text.

  +  **BASE\_URL**  
     The text of the request URL through the SCRIPT\_NAME.  This value can
281
282
283
284
285
286
287
288



289









290
291
292
293
294
295
296
297
298
299
300
301
     argument is intended in the source script, it will appear at the
     left margin in the generated output.

  +  **wapp-param** _NAME_ _DEFAULT_  
     Return the value of the query parameter or environment variable _NAME_,
     or return _DEFAULT_ if there is no such query parameter or environment
     variable.  If _DEFAULT_ is omitted, then it is an empty string.
     The same information can be obtained directly from the



     $::wapp dict.  This command is merely a convenient shortcut.










  +  **wapp-mimetype** _MIMETYPE_  
     Set the MIME-type for the generated web page.  The default is "text/html".

  +  **wapp-reply-code** _CODE_
     Set the reply-code for the HTTP request.  The default is "200 Ok".

  +  **wapp-redirect** _TARGET-URL_  
     Cause an HTTP redirect to the specified URL.

  +  **wapp-reset**  
     Reset the web page under construction back to an empty string.







|
>
>
>
|
>
>
>
>
>
>
>
>
>




|







283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
     argument is intended in the source script, it will appear at the
     left margin in the generated output.

  +  **wapp-param** _NAME_ _DEFAULT_  
     Return the value of the query parameter or environment variable _NAME_,
     or return _DEFAULT_ if there is no such query parameter or environment
     variable.  If _DEFAULT_ is omitted, then it is an empty string.

  +  **wapp-set-param** _NAME_ _VALUE_  
     Change the value of parameter _NAME_ to _VALUE_.  If _NAME_ does not
     currently exist, it is created.

  +  **wapp-param-exists** _NAME_  
     Return true if and only if a parameter called _NAME_ exists for the
     currentn request.

  +  **wapp-param-list** _NAME_  
     Return a TCL list containing the names of all parameters for the current
     request.  Note that there are several parameters that Wapp uses
     internally.  Those internal-use parameters all have names that begin
     with ".".

  +  **wapp-mimetype** _MIMETYPE_  
     Set the MIME-type for the generated web page.  The default is "text/html".

  +  **wapp-reply-code** _CODE_  
     Set the reply-code for the HTTP request.  The default is "200 Ok".

  +  **wapp-redirect** _TARGET-URL_  
     Cause an HTTP redirect to the specified URL.

  +  **wapp-reset**  
     Reset the web page under construction back to an empty string.
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
Wapp processes.

The POST data parser for Wapp currently only understands
application/x-www-form-urlencoded content.  Wapp does not (currently)
have a decoder for multipart/form-data content.  A multipart/form-data
decoder might be added in the future.  Or, individual applications can
implement their own multipart/form-data decoder using the raw POST data
held in the CONTENT entry of the ::wapp dict.


7.0 Design Rules
----------------

All global procs and variables used by Wapp begin with the four character
prefix "wapp".  Procs and variable intended for internal use begin with
the seven character prefix "wappInt".







|








401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
Wapp processes.

The POST data parser for Wapp currently only understands
application/x-www-form-urlencoded content.  Wapp does not (currently)
have a decoder for multipart/form-data content.  A multipart/form-data
decoder might be added in the future.  Or, individual applications can
implement their own multipart/form-data decoder using the raw POST data
held in the CONTENT parameter.


7.0 Design Rules
----------------

All global procs and variables used by Wapp begin with the four character
prefix "wapp".  Procs and variable intended for internal use begin with
the seven character prefix "wappInt".