One handy feature of Object Rexx is its stream class. Subclasses of this
can be defined having their own special methods for open,
charout, close and so on. We use this in defining ``server
output streams'', which send a sequence of characters to GoServe. The
idea is the same as with a normal file-output stream, except that the
open method initiates a transaction and sends back the HTTP
headers, the charout and lineout methods put characters
into a buffer which is flushed as necessary and passed to GoServe line
by line, and the close method terminates the transaction. Given
this stream class, any instance can send its HTML to the server just by
passing an instance of it to its emit method.
The code, which may be of some interest to others, is shown below.
::class ServerOutputStream subclass stream public
/* ivars buffer asc13_seen */
::method init
expose buffer asc13_seen
buffer = ''
asc13_seen = .false
return
::method open
address goserve 'SEND TYPE text/html AS dynamically_generated_html'
address goserve 'STRING <!DOCTYPE HTML>'
return
::method charout
expose buffer asc13_seen
use arg string
asc13 = d2c(13)
buffer = buffer||string
do while pos(asc13,buffer)<>0
parse var buffer buffer (asc13) post
self~flush
buffer = post
end
return
::method lineout
expose buffer
use arg string
self~charout(string)
if buffer<>'' then
self~flush
return
::method flush private
expose buffer
address goserve 'STRING' buffer
buffer = ''
return
::method close
expose buffer
if buffer <> '' then
self~flush
address goserve 'SEND COMPLETE'
return
The tests for asc13 ensure that the buffer is flushed whenever a
newline character is encountered, rather than only after a lineout
or on a close. We have found that if we don't do this, the
buffer can grow to exceed the maximum number of characters GoServe can
send in one line, so that some output gets lost.