Wapp

Check-in [ea88c28347]
Login

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

Overview
Comment:New and improved documentation.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:ea88c28347bb3977c582b45515813c7306d70058f57660b9995cc991d03d0629
User & Date: drh 2018-02-07 01:37:30
Context
2018-02-07
01:38
Mention the license (2-clause BSD) on the homepage. check-in: 8e060c0dec user: drh tags: trunk
01:37
New and improved documentation. check-in: ea88c28347 user: drh tags: trunk
2018-02-06
17:58
Fix filename dequoting in multipart/form-data interpretation. Add two test files for multipart/form-data testing. check-in: 6cd6484c92 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to README.md.

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
Wapp - A Web-Application Framework for TCL
==========================================

1.0 Introduction
----------------

Wapp is a framework for writing web applications in TCL.
Wapp has the following advantages:

  *   Small API surface → Simple to learn and use
  *   Efficient
  *   Self-contained
  *   Resistant to attacks and exploits

  *   Yields applications that are trival to enhance and maintain
  *   Cross-platform - works with any web server, or runs stand-alone
  *   A complete application is contained in a single TCL script
  *   The Wapp framework itself is also just a single TCL script
      that is "source"-ed, "package require"-ed, 
      or even copy/pasted into the application TCL script


2.0 The Problem That Wapp Attempts To Solve

-------------------------------------------

Do you ever need



a simple script to provide a list of files (such as on a download page),
or small app to manage conference room scheduling for the office, or
a few simple pages to monitor or manage the status of a server?
These sorts of problems are traditionally handled with ad-hoc
CGI scripts using libraries that decode the HTTP request and
safely encoding the reply.  This presents a number of problems:

  *   A single application typically involves multiple files.  There
      will be CSS and javascript files and other resources, plus at
      least one file for each distinct URI serviced by the application.
      This makes long-term maintenance difficult because people lose
      track of which files in the web hierarchy belong to which applications.


  *   The implementation will typically only work with a single
      stack.  Case in point:  the web interface for the MailMan
      mailing list manager only works on Apache, so if you are running
      something different you are out of luck.



  *   Because the implementation is tied to a single stack, the
      application development environment must mirror the deployment
      environment.  To debug or enhance an application running on
      web server X, the developer must set up an instance of X on the
      development machine, or else do risky development work directly
      on the production machine.

  *   Great care is required to safely decoding HTTP parameters and
      encoding HTML and JSON, so as to avoid injection attacks.
      A single slip-up can result in a vulnerability.


Wapp seeks to overcome these problems by providing a mechanism to create
powerful applications contained within a single file of easily-readable
TCL script.  Deployment options are flexible:



  1.  During development, a Wapp application can be run from the
      command-line, using a built-in web server listening on the
      loopback IP addrss.  Whenever Wapp is run in this mode, it
      also automatically brings up the start page for the application
      in the systems default web browser.

  2.  The built-in web-server in Wapp can also be used in deployment
      by having it listen on a low-numbered port and on public facing
      IP addresses.


  3.  Wapp applications can be run as CGI on systems like Apache.


  4.  Wapp applications can be run as SCGI on systems like Nginx.

All four deployment options use the same application code and present the
same interface to the application user.  Method (1) is normally used during
development and maintenance.  After testing, the single script file
that implements
the application is pushed out to servers for deployment using one of 
options (2), (3), or (4).  In this way, Wapp applications are easy to 
manage and are not tied to any particular web stack.


Wapp applications are inheriently resistant against XSS and CSRF attacks.
Safety features such as safe parameter decoding and HTML/JSON encoding and
Content Security Policy (CSP) are enabled by default.  This enables
developers to spend more time working on the application, and less
time worrying about whether or not they have introduced some security
hole by failing to safely encode or decode content.



3.0 Further information
-----------------------

  *  [Introduction To Writing Wapp Applications](docs/intro.md)



  *  [Wapp Parameters](docs/params.md)

  *  [Wapp Commands](docs/commands.md)



  *  [Security Features](docs/security.md)

  *  [Limitations of Wapp](docs/limitations.md)

  *  [Example Applications](/file/examples)

  *  [Real-World Uses Of Wapp](docs/usageexamples.md)






|
|

|
|
<

>
|
<
<
|




<
>
|

<
>
>
>
|
|
|
|
<
<
|
<
<
<
<
<
>

<
<
<
<
>
>

<
<
<
<
<
<
|
<
<
<
>

<
<
<
>
>

<
<
<
<
<
|
<
<
<
>

<
>

<
|
<
<
<
<
<
<
<
>

<
<
<
<
<
<
>
>






>
>



>
>








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
Wapp - A Web-Application Framework for TCL
==========================================

1.0 Introduction
----------------

Wapp is a new framework for writing web applications in TCL,
with the following advantages:

  *   Very small API surface &rarr; Simple to learn and use
  *   A complete application is contained in a single file

  *   Resistant to attacks and exploits
  *   Cross-platform &rarr; Works via CGI, SCGI, or using a built-in web server
  *   Does not require MVC, but can do MVC if desired


  *   The Wapp framework itself is a  single-file TCL script
      that is "source"-ed, "package require"-ed, 
      or even copy/pasted into the application TCL script



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


Here is a minimal web application written using Wapp:

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


    }





    wapp-start $argv





To run this application using the built-in web-server, store the code above
in a file (here we use the name "hello.tcl") and do:







>



    tclsh hello.tcl




To run the app using the built-in web-server bound to all TCP addresses
and listening on port 8080, use:






>



    tclsh hello.tcl --server 8080


To run the app as an SCGI server listening on port 9001:


>







    tclsh hello.tcl --scgi 9001







To run the application as CGI, make the hello.tcl file executable and
move into the appropriate directory of your web server.

3.0 Further information
-----------------------

  *  [Introduction To Writing Wapp Applications](docs/intro.md)

  *  [Quick Reference](docs/quickref.md)

  *  [Wapp Parameters](docs/params.md)

  *  [Wapp Commands](docs/commands.md)

  *  [URL Mapping](docs/urlmapping.md)

  *  [Security Features](docs/security.md)

  *  [Limitations of Wapp](docs/limitations.md)

  *  [Example Applications](/file/examples)

  *  [Real-World Uses Of Wapp](docs/usageexamples.md)

Changes to docs/intro.md.

1
2



3
4
5
6
7
8
9
..
20
21
22
23
24
25
26



27
28
29
30
31
32
33
..
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
..
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
...
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
...
128
129
130
131
132
133
134






















































135
136
137
138
139
140
141
...
157
158
159
160
161
162
163

































Introducing To Writing Wapp Applications
========================================




Wapp applications are easy to develop.  A hello-world program is as follows:

>
    #!/usr/bin/wapptclsh
    package require wapp
    proc wapp-default {req} {
................................................................................

The hello-world example generates the reply using a single call 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
the \\n at the end of the line.

The "wapp-start" command starts up the application.




To run this application, copy the code above into a file named "main.tcl"
and then enter the following command:

>
    wapptclsh main.tcl

................................................................................

>
    wapptclsh main.tcl --scgi 9000

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.

1.0 Using Plain Old Tclsh
-------------------------

Wapp applications are pure TCL code.  You can run them using an ordinary
"tclsh" command if desired, instead of the "wapptclsh" shown above.  We
normally use "wapptclsh" for the following reasons:

   +  Wapptclsh is statically linked, so there is never a worry about
................................................................................
      run with ordinary tclsh, you might need to change the 
      "package require wapp" into "source wapp.tcl" and ship the separate
      "wapp.tcl" script together with your application.

We prefer to use wapptclsh and wapptclsh is shown in all of the examples.
But ordinary "tclsh" will work in the examples too.

2.0 A Slightly Longer Example
-----------------------------

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

>
................................................................................
      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 
................................................................................

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.























































3.0 General Structure Of A Wapp Application
-------------------------------------------

Wapp applications all follow the same basic template:

>
    package require wapp;
................................................................................
Next the application defines various procs that will generate the
replies to HTTP requests.  Different procs are invoked based on the
first element of the URI past the Wapp script name.  Finally,
the "wapp-start" routine is called to start Wapp running.  The
"wapp-start" routine never returns (or in the case of CGI, it only
returns after the HTTP request has been completely processed), 
so it should be the very last command in the application script.



































>
>
>







 







>
>
>







 







|







 







|
|







 







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
..
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
..
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
..
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
...
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
...
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
...
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
Introducing To Writing Wapp Applications
========================================

1.0 Hello World
---------------

Wapp applications are easy to develop.  A hello-world program is as follows:

>
    #!/usr/bin/wapptclsh
    package require wapp
    proc wapp-default {req} {
................................................................................

The hello-world example generates the reply using a single call 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
the \\n at the end of the line.

The "wapp-start" command starts up the application.

1.1 Running A Wapp Application
------------------------------

To run this application, copy the code above into a file named "main.tcl"
and then enter the following command:

>
    wapptclsh main.tcl

................................................................................

>
    wapptclsh main.tcl --scgi 9000

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.

1.2 Using Plain Old Tclsh
-------------------------

Wapp applications are pure TCL code.  You can run them using an ordinary
"tclsh" command if desired, instead of the "wapptclsh" shown above.  We
normally use "wapptclsh" for the following reasons:

   +  Wapptclsh is statically linked, so there is never a worry about
................................................................................
      run with ordinary tclsh, you might need to change the 
      "package require wapp" into "source wapp.tcl" and ship the separate
      "wapp.tcl" script together with your application.

We prefer to use wapptclsh and wapptclsh is shown in all of the examples.
But ordinary "tclsh" will work in the examples too.

2.0 Longer Examples
-------------------

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

>
................................................................................
      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 
................................................................................

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.

2.1 Binary Resources
--------------------

Here is another variation on the same "hello, world" program that adds an
image to the main page:

>
    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>
        <p>Broccoli: <img src='broccoli.gif'></p>
      }
    }
    proc wapp-page-env {} {
      wapp-allow-xorigin-params
      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}
    }
    proc wapp-page-broccoli.gif {} {
      wapp-mimetype image/gif
      wapp-cache-control max-age=3600
      wapp-unsafe [binary decode base64 {
        R0lGODlhIAAgAPMAAAAAAAAiAAAzMwBEAABVAABmMwCZMzPMM2bMM5nMM5nMmZn/
        mczMmcz/mQAAAAAAACH5BAEAAA4ALAAAAAAgACAAAAT+0MlJXbmF1M35VUcojNJI
        dh5YKEbRmqthAABaFaFsKG4hxJhCzSbBxXSGgYD1wQw7mENLd1FOMa3nZhUauFoY
        K/YioEEP4WB1pB4NtJMMgTCoe3NWg2lfh68SCSEHP2hkYD4yPgJ9FFwGUkiHij87
        ZF5vjQmPO4kuOZCIPYsFmEUgkIlJOVcXAS8DSVoxB0xgA6hqAZaksiCpPThghwO6
        i0kBvb9BU8KkASPHfrXAF4VqSgAGAbpwDgRSaqQXrLwDCF5CG9/hpJKkb17n6RwA
        18To7whJX0k2NHYjtgXoAwCWPgMM+hEBIFDguDrjZCBIOICIg4J27Lg4aGCBPn0/
        FS1itJdNX4OPChditGOmpIGTMkJavEjDzASXMFPO7IAT5M6FBvQtiPnTX9CjdYqi
        cFlgoNKlLbbJfLqh5pAIADs=
      }]
    }
    wapp-start $argv

This application is the same as the previous except that it adds the
"broccoli.gif" image on the main "Hello, World" page.  The image file is
a separate resource, which is provided by the new "wapp-page-broccoli.gif"
proc.  The image is a GIF which has been encoded using base64 so that
it can be put into an text TCL script.  The "[binary decode base64 ...]"
command is used to convert the image back into binary before returning
it.

Other resources might be added using procs like "wapp-page-style.css"
or "wapp-page-script.js".

3.0 General Structure Of A Wapp Application
-------------------------------------------

Wapp applications all follow the same basic template:

>
    package require wapp;
................................................................................
Next the application defines various procs that will generate the
replies to HTTP requests.  Different procs are invoked based on the
first element of the URI past the Wapp script name.  Finally,
the "wapp-start" routine is called to start Wapp running.  The
"wapp-start" routine never returns (or in the case of CGI, it only
returns after the HTTP request has been completely processed), 
so it should be the very last command in the application script.

3.1 Wapp Applications As Model-View-Controller
----------------------------------------------

If you are accustomed to thinking of web applications using the
Model-View-Controller (MVC) design pattern, Wapp supports that
point of view.  A basic template for an MVC Wapp application
is like this:

>
    package require wapp;
    # procs to implement the model go here
    proc wapp-page-XXXXX {} {
      # code to implement controller for XXXXX
      # code to implement view for XXXXX
    }
    proc wapp-page-YYYYY {} {
      # code to implement controller for YYYYY
      # code to implement view for YYYYY
    }
    proc wapp-default {} {
      # code to implement controller for all other pages
      # code to implement view for all other pages
    }
    wapp-start $argv

The controller and view portions of each page need not be coded
together into the same proc.  They can each be sub-procs that
are invoked from the main proc, if separating the functions make
code clearer.

So Wapp does support MVC, but without a lot of extra
machinary and syntax.

Added docs/quickref.md.























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
Wapp Quick Reference
====================

1.0 Interfaces
--------------

|**wapp-start** $argv|&rarr;|Starts up the Wapp application.  Should be last.|
|**wapp-subst** {_TEXT_}|&rarr;|Append _TEXT_ to the output with substitution|
|**wapp-trim** {_TEXT_}|&rarr;|Like **wapp-subst** but also removes left-margin whitespace|
|**wapp-param** _NAME_ _DEFAULT_|&rarr;|Return value of parameter _NAME_|
|**wapp-set-param** _NAME_ _VALUE_|&rarr;|Set parameter _NAME_ to _VALUE_|
|**wapp-param-exists** _NAME_|&rarr;|True if parameter _NAME_ exists|
|**wapp-param_list** _GLOB_|&rarr;|Return parameter names matching _GLOB_|
|**wapp-allow-xorigin-params**|&rarr;|Allow GET and POST parameters for cross-origin requests|
|**wapp-mimetype** _MIMETYPE_|&rarr;|Make _MIMETYPE_ the reply mimetype|
|**wapp-reply-code** _CODE_|&rarr;|Set the HTTP reply code to _CODE_|
|**wapp-redirect** _TARGET_|&rarr;|Redirect to _TARGET_|
|**wapp-reset**|&rarr;|Reset the output back to an empty string|
|**wapp-set-cookie** _NAME_ _VALUE_|&rarr;|Set cookie _NAME_ to have _VALUE_|
|**wapp-clear_cookie** _NAME_|&rarr;|Delete cookie _NAME_|
|**wapp-cache-control** _CONTROL_|&rarr;|Set caching behavior of current page|
|**wapp-content-security-policy** _POLICY_|&rarr;|Set the CSP for the current page|
|**wapp-debug-env**|&rarr;|Return a text description of the Wapp environment|
|**wapp** {_TEXT_}|&rarr;|Append _TEXT_ without substitution|
|**wapp-unsafe** _TEXT_|&rarr;|Append _TEXT_ that contains nothing that needs to be escaped|


2.0 Parameters
--------------

|BASE\_URL|&rarr;|URL for the Wapp script without a method|
|CONTENT|&rarr;|Raw (unparsed) POST content|
|CONTENT\_LENGTH|&rarr;|Number of bytes of raw, unparsed POST content|
|CONTENT\_TYPE|&rarr;|Mimetype of the POST content|
|DOCUMENT\_ROOT|&rarr;|Directory that is the root of the webserver content tree|
|HTTP\_COOKIE|&rarr;|Raw, unparsed cookies|
|HTTP\_HOST|&rarr;|Hostname to which this request was sent|
|HTTP\_USER\_AGENT|&rarr;|Name of client program that sent current request|
|HTTPS|&rarr;|Exists and has value "on" if the request is encrypted|
|PATH\_HEAD|&rarr;|First element of PATH\_INFO. Determines request handler|
|PATH\_INFO|&rarr;|URL path beyond the application script name|
|PATH\_TAIL|&rarr;|Part of PATH\_INFO beyond PATH\_HEAD|
|REMOTE\_ADDR|&rarr;|IP address of the client|
|REMOTE\_PORT|&rarr;|TCP port of the client|
|REQUEST\_METHOD|&rarr;|"GET" or "POST" or "HEAD"|
|SAME\_ORIGIN|&rarr;|True if this request is from the same origin|
|SCRIPT\_FILENAME|&rarr;|Full pathname of the Wapp application script|
|SCRIPT\_NAME|&rarr;|Prefix of PATH\_INFO that identifies the application script|
|SELF\_URL|&rarr;|URL of this request without PATH\_TAIL|
|WAPP\_MODE|&rarr;|One of "cgi", "scgi", "server", or "local"|

3.0 URL Parsing
---------------

Assuming "env.tcl" is the name of the Wapp application script:

>
    https://wapp.tcl.tk/demo/env.tcl/abc/def/ghi?a=5&b=22.425#point42
            \_________/ \__________/\__________/
                 |           |          |
             HTTP_HOST  SCRIPT_NAME  PATH_INFO

>
    https://wapp.tcl.tk/demo/env.tcl/abc/def/ghi?a=5&b=22.425#point42
    \______________________________/ \_/ \_____/
                   |                  |     |
                BASE_URL         PATH_HEAD  '-- PATH_TAIL     

>
    https://wapp.tcl.tk/demo/env.tcl/abc/def/ghi?a=5&b=22.425#point42
    \__________________________________/         \__________/
                   |                                  |
                SELF_URL                         QUERY_STRING

SCRIPT\_FILENAME := DOCUMENT\_ROOT + SCRIPT\_NAME

Added docs/urlmapping.md.







































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
URL Mapping In Wapp
===================

1.0 Anatomy Of A URL
--------------------

A Uniform Resource Locator (URL) is divided into parts as follows:

>
    https://wapp.tcl.tk/demo/env.tcl/abc/def/ghi?a=5&b=22.425#point42
    \___/   \_________/ \______________________/ \__________/ \_____/
      |          |              |                     |          |
    scheme   authority        path                  query      fragment


Assuming that /demo/env.tcl is the script that implements the application,
tradition CGI and SCGI, and Wapp, break a URL down like this:

>
    https://wapp.tcl.tk/demo/env.tcl/abc/def/ghi?a=5&b=22.425#point42
            \_________/ \__________/\__________/
                 |           |          |
             HTTP_HOST  SCRIPT_NAME  PATH_INFO

>
    https://wapp.tcl.tk/demo/env.tcl/abc/def/ghi?a=5&b=22.425#point42
    \______________________________/ \_/ \_____/
                   |                  |     |
                BASE_URL         PATH_HEAD  '-- PATH_TAIL     

>
    https://wapp.tcl.tk/demo/env.tcl/abc/def/ghi?a=5&b=22.425#point42
    \__________________________________/         \__________/
                   |                                  |
                SELF_URL                         QUERY_STRING


2.0 URL Mapping
---------------

The URL Mapper is the function that determines which routine in the
application should handle an HTTP request based on the URL.  In Wapp,
the default URL Mapper simply looks at PATH_HEAD and invokes the
application-defined proc name "wapp-page-$PATH_HEAD".  If no such
proc exists, then Wapp invokes the application-defined proc "wapp-default".

2.1 Customizing The URL Mapper
------------------------------

Just prior to dispatch of the HTTP request handler, Wapp invokes a
proc named "wapp-before-dispatch-hook".  This proc is normally a no-op.
But, applications can redefine the "wapp-before-dispatch-hook" proc to
make modifications to the environment prior to dispatch.  So, for example,
a custom wapp-before-dispatch-hook function can change the value of
the PATH_HEAD parameter to cause a different request handler to be invoked.

The [checklist](https://sqlite.org/checklistapp) application does this.
See [these lines](https://sqlite.org/checklistapp/artifact/8f94882fa0?ln=715-744)
for the implementation.  If the original PATH\_HEAD is really the name of
a checklist database, then that name is moved to a new parameter called
OBJECT, and PATH\_HEAD is shifted to be the next element of PATH_TAIL.
In this way, the PATH\_INFO for checklist is parsed into OBJECT/METHOD
rather than just a METHOD.

This is but one example.  Applications can make creative use of
the "wapp-before-dispatch-hook" to make whatever changes are appropriate
for the task at hand.