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.