[REBOL] [Fwd: POST CGI testing]
From: joel::neely::fedex::com at: 20-Nov-2000 11:04
Hi, all...
I've spent WAAAAYYYY too much time on this. However, I hope that by
documenting my experiences (and frustrations!) I can benefit the next
REBOLite that has to walk this path.
I ran a series of tests using the HTML form previously posted, and the
cgi script given at the end of this note. During the tests, I added a
couple of variations, and the code to display the REBOL version number,
but those don't appear in my sample output until later on.
If you want to cut to the solution, look at test case #15 and the code
that appears at the end of this message. When I get a chance, I'll
provide a condensed version of the feedback issues that resulted from
this exploration (cases 2, 3, 7, 9, etc..)
The first eight test cases submit the form with its default data content
(short data, that fits within the apparent buffer limitation).
Test case #1:
====================
test: input
request-method: POST
content-length: 53
content: area=Hello&field=Goodbye&submit=Submit&secret=whisper
length?: 53
====================
Remarks: Correct output.
Test case #2:
====================
test: system/ports/input
request-method: POST
content-length: 53
content: area=Hello&field=Goodbye&submit=Submit&secret=whisper
length?: 1
====================
Remarks: Correct content, but notice strange length? value. (???)
Test case #3:
====================
test: console port
request-method: POST
content-length: 53
====================
Remarks: Browser reports "Document: Done." and cgi process terminates,
but notice that the last part of the output is missing. Perhaps the
cgi
process went sideways?
Test case #4:
====================
test: read-io
request-method: POST
content-length: 53
content: area=Hello&field=Goodbye&submit=Submit&secret=whisper
length?: 53
====================
Remarks: Correct output.
Test case #5:
====================
test: read-io loop
request-method: POST
content-length: 53
====================
Remarks: Browser stalls, and cgi process never terminates. The relevant
portion of top output shows the following interesting state of
affairs:
5298 httpd 14 0 5900 5900 596 R 0 91.3 9.3 1:29 testcgi.r.cg
3504 httpd 0 0 416 0 0 SW 0 0.0 0.0 0:00 httpd
3505 httpd 0 0 872 740 640 S 0 0.0 1.1 0:00 httpd
3506 httpd 0 0 416 0 0 SW 0 0.0 0.0 0:00 httpd
3507 httpd 0 0 372 0 0 SW 0 0.0 0.0 0:00 httpd
3508 httpd 0 0 372 0 0 SW 0 0.0 0.0 0:00 httpd
3509 httpd 0 0 872 740 640 S 0 0.0 1.1 0:00 httpd
3510 httpd 0 0 420 0 0 SW 0 0.0 0.0 0:00 httpd
3511 httpd 0 0 372 0 0 SW 0 0.0 0.0 0:00 httpd
3512 httpd 0 0 372 0 0 SW 0 0.0 0.0 0:00 httpd
3513 httpd 0 0 372 0 0 SW 0 0.0 0.0 0:00 httpd
3812 httpd 0 0 424 0 0 SW 0 0.0 0.0 0:00 httpd
5299 httpd 0 0 376 376 328 S 0 0.0 0.5 0:00 testcgi.r.cg
Note that there are TWO testcgi.r.cgi processes (the names were
truncated by the width of the terminal window) -- one of which is a
busy beaver and the other of which is doing nothing. Pressing the
"Stop" button on the browser takes it out of "65 bytes read (stalled)"
state, but leaves the cgi processes running.
If I kill the lower-numbered process (SIG 15) they both die.
Test case #6:
====================
test: read-io loop 2
request-method: POST
content-length: 53
content: area=Hello&field=Goodbye&submit=Submit&secret=whisper
length?: 53
====================
Remarks: Correct output.
Test case #7:
====================
test: input? loop
request-method: POST
content-length: 53
====================
Remarks: Premature termination again. Browser reports "Document:
Done." and cgi process terminates, but last part of output is
simply missing.
Test case #8:
====================
test: noise not matched
request-method: POST
content-length: 53
content: input=default
length?: 13
====================
Remarks: For the sake of completeness, here's what happens if the
test selector fails to match any of the actual input choices...j
The second set of test cases submit the form with long data content,
created by pasting a large number of copies of the same line into
the textarea:
Test case #9:
====================
test: input
request-method: POST
content-length: 4608
content: area=123456789012345678901...012345678901
length?: 4094
====================
Remarks: The received data are truncated (the ellipsis in the the
string from the textarea was inserted by me for this email -- you
don't want to see 4K of digits ;-). Notice that the length of
the content is the curious number 4094 and that the content stops
in the textarea value (the other fields are completely missing,
as they follow the textarea). Also note that there was a line
break every 70 characters in the textarea data -- cgi encoded
as "%0D%0A" -- but my little snippet above isn't long enough to
contain one of those occurrences.
Test case #10:
====================
test: system/ports/input
request-method: POST
content-length: 4608
content: area=12345678901...0123456789012345678901
length?: 1
====================
Remarks: Despite the peculiar reported length of the content string,
that string is actually truncated to the same length as the
previous case. Notice that the data end with the same fragmentary
value for the textarea and the other input fields are missing.
Test case #11:
====================
test: console port
request-method: POST
content-length: 4608
====================
Remarks: As before (with short data) the browser reports "Document:
Done." and the cgi process goes away. However, the remaining
output is missing.
Test case #12:
====================
test: read-io
request-method: POST
content-length: 4608
content: area=123456789012345678901...01234567890123
length?: 4096
====================
Remarks: Once again, the input data string is truncated, but to a
slightly longer size than before (a round number ?!?!?!).
Test case #13:
====================
test: read-io loop
request-method: POST
content-length: 4608
====================
Remarks: As in the first set of test cases, the browser stalls and the
cgi process pair hangs around until killed. This time, just for
variety, I killed the cgi processes first, after which the browser
displayed "Document: Done."
Test case #14:
====================
REBOL version: 2.3.0.4.2
test: read-io loop 2
request-method: POST
content-length: 4608
content: rea=12345...90%0D%0A&field=Goodbye&submit=Submit&secret=whisper
length?: 8704
====================
Remarks: AHA!!! Two useful lessons:
1) The read-io loop appears to work!
2) Read-io apparently appends to its argument instead of
overwriting it. Notice that 8704 = 4096 + 4608.
With those lessons in mind, let's try a variation on this theme.
Test case #15:
====================
REBOL version: 2.3.0.4.2
test: read-io loop 2a
request-method: POST
content-length: 4608
content:
area=123456789...01234567890%0D%0A&field=Goodbye&submit=Submit&secret=whisper
length?: 4608
====================
Remarks: SUCCESS AT LAST!
Additional warnings: The R/CUG 2.3 sent me down a couple of blind
alleys, as documented in the test cases below. I'm including
these for completeness and as a public feedback item on the
manual.
Test cases #16a and #16b:
====================
REBOL version: 2.3.0.4.2
test: console port 2
request-method: POST
content-length: 4608
** Script Error: open has no refinement called nowait.
** Where: port: open/binary/nowait console://
while [found? wait [port 1]]
====================
REBOL version: 2.3.0.4.2
test: console port 2
request-method: POST
content-length: 4608
** Script Error: open has no refinement called no-wait.
** Where: port: open/binary/no-wait console://
while [found? wait [port 1]]
====================
Remarks: Gabriele suggested I open a console, possibly with the
/no-wait refinement. R/CUG 2.3 page 13-4 listed /nowait as
a refinement to the open function, but (as you can see above)
that doesn't seem to be valid, either with or without the hyphen.
Test case:
====================
REBOL version: 2.3.0.4.2
test: foreach system/ports/input
request-method: POST
content-length: 4608
content: area=12345678901...012345678901
length?: 4095
====================
Remarks: R/CUG 2.3 page 12-56 contains an example script entitled
"Show POST data" which loops over system/ports/input using
a data buffer with a 10000 byte capacity. "Self," I said to myself,
"that must be the clue you've been missing!" So Self tried it, and
got the disappointing result above. Still truncated!
TEST SCRIPT FOLLOWS:
All of the various attempts to obtain input are contained within the
function named read-post-input and selected by the test variable
which controls the switch in that function.
================================================================================
#!/usr/local/bin/rebol -cs
REBOL []
print [
{Content-type: text/plain^/^/REBOL version: } system/version
]
clen: to-integer system/options/cgi/content-length
reqm: system/options/cgi/request-method
test: "foreach system/ports/input"
print [
{^/test: } test
{^/request-method: } reqm
{^/content-length: } clen
]
read-post-input: func [/local ct cs port] [
ct: make string! clen
cs: make string! clen
switch/default test [
"input" [ cs: input ]
"system/ports/input" [ cs: copy system/ports/input ]
"console port" [
port: open/binary console://
while [found? wait [port 1]] [
insert tail cs copy port
]
close port
]
"read-io" [ read-io system/ports/input cs clen ]
"read-io loop" [
read-io system/ports/input ct clen
while [0 < length? ct] [
append cs ct
read-io system/ports/input ct clen
]
]
"read-io loop 2" [
read-io system/ports/input ct clen
while [clen > length? cs] [
append cs ct
read-io system/ports/input ct clen
]
]
"input? loop" [ while [input?] [ ct: input append cs ct ] ]
"read-io loop 2a" [
until [
read-io system/ports/input cs clen
clen = length? cs
]
]
"console port 2" [
port: open/binary/no-wait console://
while [found? wait [port 1]] [
insert tail cs copy port
]
close port
]
"foreach system/ports/input" [
foreach ct copy system/ports/input [
repend cs [ct newline]
]
]
][
cs: "input=default"
]
return cs
]
cont: any [
if reqm = "get" [ system/options/cgi/query-string ]
if reqm = "post" [ read-post-input ]
input
]
print [
newline
{^/content: } cont
{^/length?: } length? head cont
newline
]
================================================================================
-jn-