Wapp

Check-in [70438dc56d]
Login

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

Overview
Comment:Add support for decoding multipart/form-data on POST queries.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:70438dc56dbfb57a3f6270fa2d3f675c65e454d56bcd9c9bb5b4ec4eb9b05a03
User & Date: drh 2018-02-06 15:47:39
Context
2018-02-06
16:36
Enhance the file upload test to show uploaded images inline. check-in: 089322b3a4 user: drh tags: trunk
15:47
Add support for decoding multipart/form-data on POST queries. check-in: 70438dc56d user: drh tags: trunk
13:14
Add the WAPP_MODE cgi parameter. check-in: 7700f1866a user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to docs/limitations.md.

7
8
9
10
11
12
13
14
15
16
17
       connections can be incoming and multiple replies can be in-flight
       at the same time.  But the generation of each reply happens all
       at once.
       <p>
       This limitation can be worked around by deploying the Wapp application
       using CGI, such that each HTTP request is handled by a separate
       process.

  2.   POST parameter decoding currently only understands
       application/x-www-form-urlencoded content.  The multipart/form-data
       stil of POST content is not currently understood.







<
<
<
<
7
8
9
10
11
12
13




       connections can be incoming and multiple replies can be in-flight
       at the same time.  But the generation of each reply happens all
       at once.
       <p>
       This limitation can be worked around by deploying the Wapp application
       using CGI, such that each HTTP request is handled by a separate
       process.




Changes to tests/test01.tcl.

22
23
24
25
26
27
28

29
30
31
32
33
34
35
...
117
118
119
120
121
122
123















124
125
126
127
128
129
130
  wapp-trim {
    <li><p><a href='%html($B)/lint'>Lint</a>
    <li><p><a href='%html($B)/errorout'>Deliberate error</a>
    <li><p><a href='%html($B)/encodings'>Encoding checks</a>
    <li><p><a href='%html($B)/redirect'>Redirect to env</a>
    <li><p><a href='globals'>TCL global variables</a>
    <li><p><a href='csptest'>Content Security Policy</a>

  }
  set x "%string(...)"
  set v abc'def\"ghi\\jkl
  wapp-subst {<li>%html($x) substitution test: "%string($v)"\n}
  wapp "</ol>"
  if {[dict exists $wapp showenv]} {
    wapp-page-env
................................................................................
    wapp-trim {
      <pre>
      %html($res)
      </pre>
    }
  }
}















proc wapp-page-encodings {} {
  set strlist {
     {Johann Strauß}
     {Вагиф Сәмәдоғлу}
     {中国}
     {$[hi]{there}$}
     {https://drh@sqlite.org/info?name=trunk#block2}







>







 







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







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
...
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
  wapp-trim {
    <li><p><a href='%html($B)/lint'>Lint</a>
    <li><p><a href='%html($B)/errorout'>Deliberate error</a>
    <li><p><a href='%html($B)/encodings'>Encoding checks</a>
    <li><p><a href='%html($B)/redirect'>Redirect to env</a>
    <li><p><a href='globals'>TCL global variables</a>
    <li><p><a href='csptest'>Content Security Policy</a>
    <li><p><a href='fileupload'>File Upload Using multipart/form-data</a>
  }
  set x "%string(...)"
  set v abc'def\"ghi\\jkl
  wapp-subst {<li>%html($x) substitution test: "%string($v)"\n}
  wapp "</ol>"
  if {[dict exists $wapp showenv]} {
    wapp-page-env
................................................................................
    wapp-trim {
      <pre>
      %html($res)
      </pre>
    }
  }
}
proc wapp-page-fileupload {} {
  wapp-trim {
    <h1>Wapp Form Test</h1>
    <p><form method="POST" enctype="multipart/form-data">
    <input type="file" name="f1"><br>
    <input type="file" name="f2"><br>
    <input type="file" name="f3"><br>
    <input type="submit" value="Go">
    </form></p>
    <pre>%html([wapp-debug-env])
    .header = %html([wapp-param .header])
    </pre>
  }
}

proc wapp-page-encodings {} {
  set strlist {
     {Johann Strauß}
     {Вагиф Сәмәдоғлу}
     {中国}
     {$[hi]{there}$}
     {https://drh@sqlite.org/info?name=trunk#block2}

Changes to wapp.tcl.

517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534












535
536
537
538
539



540
541
542
543
544
545
546
      set qsplit [split $qterm =]
      set nm [lindex $qsplit 0]
      if {[regexp {^[a-z][a-z0-9]*$} $nm]} {
        dict set wapp $nm [wappInt-decode-url [lindex $qsplit 1]]
      }
    }
  }
  if {[dict exists $wapp CONTENT_TYPE]
   && [dict get $wapp CONTENT_TYPE]=="application/x-www-form-urlencoded"
   && [dict exists $wapp CONTENT]
  } {
    foreach qterm [split [string trim [dict get $wapp CONTENT]] &] {
      set qsplit [split $qterm =]
      set nm [lindex $qsplit 0]
      if {[regexp {^[a-z][-a-z0-9_]*$} $nm]} {
        dict set wapp $nm [wappInt-decode-url [lindex $qsplit 1]]
      }
    }












  }
  # To-Do:  Perhaps add support for multipart/form-data decoding.
  # Alternatively, perhaps multipart/form-data decoding can be done
  # by application code using a separate helper function, like
  # "wapp_decode_multipart_formdata" or somesuch.



}

# Invoke application-supplied methods to generate a reply to
# a single HTTP request.
#
# This routine always runs within [catch], so handle exceptions by
# invoking [error].







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







517
518
519
520
521
522
523
524
525
526

527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546




547
548
549
550
551
552
553
554
555
556
      set qsplit [split $qterm =]
      set nm [lindex $qsplit 0]
      if {[regexp {^[a-z][a-z0-9]*$} $nm]} {
        dict set wapp $nm [wappInt-decode-url [lindex $qsplit 1]]
      }
    }
  }
  if {[dict exists $wapp CONTENT_TYPE] && [dict exists $wapp CONTENT]} {
    set ctype [dict get $wapp CONTENT_TYPE]
    if {$ctype=="application/x-www-form-urlencoded"} {

      foreach qterm [split [string trim [dict get $wapp CONTENT]] &] {
        set qsplit [split $qterm =]
        set nm [lindex $qsplit 0]
        if {[regexp {^[a-z][-a-z0-9_]*$} $nm]} {
          dict set wapp $nm [wappInt-decode-url [lindex $qsplit 1]]
        }
      }
    } elseif {[string match multipart/form-data* $ctype]} {
      regexp {^(.*?)\r\n(.*)$} [dict get $wapp CONTENT] all divider body
      set ndiv [string length $divider]
      while {[string length $body]} {
        set idx [string first $divider $body]
        set unit [string range $body 0 [expr {$idx-3}]]
        set body [string range $body [expr {$idx+$ndiv+2}] end]
        if {[regexp {^Content-Disposition: form-data; name="(.*)"; filename="(.*)"\r\nContent-Type: (.*)\r\n\r\n(.*)$}\
             $unit unit name filename mimetype content]} {
          dict set wapp $name.filename $filename
          dict set wapp $name.mimetype $mimetype
          dict set wapp $name.content $content
        }




      }
    }
  }
}

# Invoke application-supplied methods to generate a reply to
# a single HTTP request.
#
# This routine always runs within [catch], so handle exceptions by
# invoking [error].