Wapp

Check-in [5d5c1559d7]
Login

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

Overview
Comment:Update example scripts to remove uses of the ::wapp dict. Improvements to the documentation.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 5d5c1559d7f8f7d6936c3f7e6db30e672deaf8af8c598a9034357ad8c6a0ae5e
User & Date: drh 2018-01-30 20:36:59.887
Context
2018-01-30
23:46
Add wapp-allow-xorigin-params and SAME_ORIGIN. Update the documentation accordingly. (check-in: e82121be4d user: drh tags: trunk)
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)
Changes
Unified Diff Ignore Whitespace Patch
Changes to README.md.
324
325
326
327
328
329
330




331
332
333
334
335
336
337
     Examine all TCL procedures in the application and report errors about
     unsafe usage of "wapp".

  +  **wapp-cache-control** _CONTROL_  
     The _CONTROL_ argument should be one of "no-cache", "max-age=N", or
     "private,max-age=N", where N is an integer number of seconds.






The following additional interfaces are envisioned, but are not yet
implemented:

  +  **wapp-send-hex** _HEX_  
     Cause the HTTP reply to be binary that is constructed from the
     hexadecimal text in the _HEX_ argument.  Whitespace in _HEX_ is ignored.







>
>
>
>







324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
     Examine all TCL procedures in the application and report errors about
     unsafe usage of "wapp".

  +  **wapp-cache-control** _CONTROL_  
     The _CONTROL_ argument should be one of "no-cache", "max-age=N", or
     "private,max-age=N", where N is an integer number of seconds.

  +  **wapp-debug-env**  
     This routine returns text that describes all of the Wapp parameters.
     Use it to get a parameter dump for troubleshooting purposes.


The following additional interfaces are envisioned, but are not yet
implemented:

  +  **wapp-send-hex** _HEX_  
     Cause the HTTP reply to be binary that is constructed from the
     hexadecimal text in the _HEX_ argument.  Whitespace in _HEX_ is ignored.
381
382
383
384
385
386
387































388
389
390
391
392
393
394
395

  +  **wapp-escape-url** _TEXT_  
     Add _TEXT_ to the web page under construction after first escaping any
     characters so that the result is safe to include as the value of a
     query parameter on a URL.  This command is equivalent to
     "wapp-subst {%url(_TEXT_)}".
































6.0 Limitations
---------------

Each Wapp process is single-threaded.
The fileevent command is used to allow accepting multiple simultaneous
HTTP requests.  However, as soon as a complete request is received, and
the "wapp-page-NAME" proc runs, all other processing is suspended until 
that proc completes.







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







385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430

  +  **wapp-escape-url** _TEXT_  
     Add _TEXT_ to the web page under construction after first escaping any
     characters so that the result is safe to include as the value of a
     query parameter on a URL.  This command is equivalent to
     "wapp-subst {%url(_TEXT_)}".


6.0 Developing Applications Using Wapp
--------------------------------------

You can use whatever development practices you are comformable with.  But
if you want some hints for getting started, consider the following:

  1.  Compile the "wapptclsh" executable.  You do not need a separate
      interpreter to run Wapp.  A standard "tclsh" will work fine.  But
      "wapptclsh" contains the a built-in copy of "wapp.tcl" and it
      has SQLite compiled in.  We find it convenient to use.  The sequel
      will assume you have "wapptclsh" somewhere on your $PATH.

  2.  Seed your application using one of the short scripts shown above,
      or perhaps one of the [examples](/file/examples) in this repository.

  3.  Make a few simple changes to the code.

  4.  Run "wapptclsh yourcode.tcl" to test your changes.

  5.  Goto 3.  Continue until your application is working.

  6.  Move the "yourcode.tcl" file to your server for deployment.

During the loop between steps (3) and (5), there is no web server sitting
in between the application and your browser, which means there is no
translation or interpretation of traffic.  This can help make debugging
easier.  Also, you can add "puts" commands to the application to get
interactive debugging information on your screen while the application
is running.

7.0 Limitations
---------------

Each Wapp process is single-threaded.
The fileevent command is used to allow accepting multiple simultaneous
HTTP requests.  However, as soon as a complete request is received, and
the "wapp-page-NAME" proc runs, all other processing is suspended until 
that proc completes.
403
404
405
406
407
408
409






410
411
412
413
414
415
416
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".







>
>
>
>
>
>

|





438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
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.

As a defense against
[Cross-Site Request Forgery (CSRF)](https://en.wikipedia.org/wiki/Cross-site_request_forgery)
attacks, Wapp refuses to parse any POST query parameters unless there
is a Referer entry in the header that matches the request URI.  In other
words, Wapp assumes that POST requests originate from itself and any other
POST requests are treated as an attack and ignored.

8.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".
Changes to examples/env.tcl.
1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# This script is a template used for testing.
#
# After making modifications to this script to test out bits of HTML
# (or not - the script works fine as it is), invoke the script using
#
#   wapptclsh env.tcl
#
# All web pages show the CGI environment.


#
package require wapp
proc wapp-default {} {
  global wapp
  wapp-trim {
    <h1>Wapp Environment</h1>
    <pre>
  }
  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







|
>
>



<


|

<
<
<
<
<


1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17





18
19
# This script is a template used for testing.
#
# After making modifications to this script to test out bits of HTML
# (or not - the script works fine as it is), invoke the script using
#
#   wapptclsh env.tcl
#
# All web pages show the Wapp execution environment, which includes
# CGI-line environment variables, decoded query and POST parameters, and 
# decoded cookies.
#
package require wapp
proc wapp-default {} {

  wapp-trim {
    <h1>Wapp Environment</h1>
    <pre>%html([wapp-debug-env])</pre>
  }





}
wapp-start $argv
Changes to examples/formajax01.tcl.
1
2
3
4
5
6
7
8
9
# This script demonstrates how to send form data as JSON using
# XMLHttpRequest
#
package require wapp
proc wapp-default {} {
  wapp-trim {
    <h1>Example Of Sending Form Data As JSON Using AJAX</h1>
    <form id="nameForm">
    <table border="0">
|
|







1
2
3
4
5
6
7
8
9
# This script demonstrates how to send form data from the client browser
# back up to the server using an XMLHttpRequest with JSON content.
#
package require wapp
proc wapp-default {} {
  wapp-trim {
    <h1>Example Of Sending Form Data As JSON Using AJAX</h1>
    <form id="nameForm">
    <table border="0">
Changes to examples/formajax02.tcl.
1
2

3
4
5
6
7
8
9
# This script demonstrates how to send form data as JSON using
# XMLHttpRequest

#
package require wapp
proc wapp-default {} {
  wapp-trim {
    <h1>Example Of Sending application/x-www-form-urlencoded Using AJAX</h1>
    <form id="nameForm">
    <table border="0">
|
|
>







1
2
3
4
5
6
7
8
9
10
# This script demonstrates how to send form data from the client browser
# back up to the server using an XMLHttpRequest with 
# application/x-www-form-urlencoded content.
#
package require wapp
proc wapp-default {} {
  wapp-trim {
    <h1>Example Of Sending application/x-www-form-urlencoded Using AJAX</h1>
    <form id="nameForm">
    <table border="0">
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
      xhttp.send(jx);
      return false
    }
    </script>
  }
}
proc wapp-page-acceptjson {} {
  global wapp
  puts "Accept Callback"
  puts "mimetype: [list [wapp-param CONTENT_TYPE]]"
  puts "content: [list [wapp-param CONTENT]]"
  foreach var [lsort [dict keys $wapp]] {
    if {![regexp {^[a-z]} $var]} continue
    puts "$var = [list [wapp-param $var]]"
  }
}
wapp-start $argv







<



|





30
31
32
33
34
35
36

37
38
39
40
41
42
43
44
45
      xhttp.send(jx);
      return false
    }
    </script>
  }
}
proc wapp-page-acceptjson {} {

  puts "Accept Callback"
  puts "mimetype: [list [wapp-param CONTENT_TYPE]]"
  puts "content: [list [wapp-param CONTENT]]"
  foreach var [lsort [wapp-param-list]] {
    if {![regexp {^[a-z]} $var]} continue
    puts "$var = [list [wapp-param $var]]"
  }
}
wapp-start $argv
Changes to examples/tableajax01.tcl.
1
2
3
4
5
6
7
8
9
# This script demonstrates how to receive bulk HTML content
# (such as a complete <table>) and inserting it in the middle
# of the DOM using XMLHttpRequest
#
package require wapp
proc wapp-default {} {
  wapp-trim {
    <html>
    <body>

|







1
2
3
4
5
6
7
8
9
# This script demonstrates how to receive bulk HTML content
# (such as a complete <table>) and insert it in the middle
# of the DOM using XMLHttpRequest
#
package require wapp
proc wapp-default {} {
  wapp-trim {
    <html>
    <body>