[ZPT] response.setHeader() best practice

Alan Kennedy zpt@xhaus.com
Wed, 10 Apr 2002 12:19:45 EST5EDT


Toby,

Taking this off list, since I'm not sure it's relevant to 
the list any more.

> You
> are assuming that "SAX2 events" is a convenient format 
for the output
> data. 

Honestly, I couldn't see it operating any other way. A Sax 
event stream gives such fantastic code separation, at a 
very low cost. Every xml parser supports it, and there's 
oodles of SAX handlers already "out there". But this does 
mean that I can't deal with non well-formed HTML files, 
which might create a problem for Netscape 4.x and other 
early browsers (Die, Netscape 4, die, put us all out of our 
misery ;-).

> If the data is going over the wire then your event 
handlers
> perform encoding.

Exactly.

> Do your SAX2 events receive strings in unicode? 

Precisely. Though, because it's Java and Jython, they are 
simply java.lang.String's or PyString's.

> If so there is very little difference between the
> two models.

It's quite likely we've both seen the same mistakes made 
before, and have taken a similar approach to solving them.

>>But I am at a loss to think of any "further textual 
>>processing" I might want to do.
> 
> .....pass the string into a grammar checker, store the 
result as an
> object attribute, or maybe pass it into a module which 
writes the text
> into a banner gif. Im not always calculating a whole 
document, or
> 'response'

OK, I see your point now. Actually, dealing with structure 
validation is one of the next problems I am going to 
address. I plan to use either Relax-NG or TREX (which 
should be fairly straightforward to implement as SAX 
handlers).

> Yes, encoding comes last in both models. You do it 
incrementally, I do
> it in one big hit in ZPublisher. 

Although I do the encoding incrementally, I still most 
often capture the content in a buffer at the end, so that I 
can gzip it.

> >Keeping the output as structured SAX2 events until the 
very 
> >last minute eliminates the need for "further textual 
> >processing", i.e. I don't have to go parsing textual 
HTML 
> >looking for a/@href and form/@action attributes to 
modify.
> 
> Im not sure 'textual' is the right word, but i will use 
it anyway... I
> guess you would perform your textual processing at the 
SAX2 level?

Indeed. For me, URL rewriting is simply a case of 
subclassing the base SAX2 handler, and overriding 
the "startElement" handler to look for HTML attributes that 
might contain URLs. If it finds any, it create  a new SAX 
AttributesImpl object, copied from the original Attributes, 
modifies whichever attributes contain URIs, and passes it 
onto the next handler in the chain.

Here is a demo code snippet (tabs shortened cos of email 
word wrap)
============================================================
======
def createOutputBuffer(outFileName, encoding):
 """
  Create an output file buffer to capture the output.
 """
 try:
  fbuf = TALFileWriter(TALOutputConstants.OUTPUT_HTML, 
outFileName, encoding)
  return fbuf
 except java.io.IOException, exc:
  print "Error creating file output buffer:" + outFileName 
+ ":" + exc.getMessage()
  sys.exit(0)

def createRewritingOutputBuffer(fileBuffer):
 """
  Create a rewriting buffer which hands onto a file buffer.
  The file buffer is a simple character stream.
  The rewriter object is anything that has an "encodeURL" 
method,
  such as javax.servlet.http.HttpServletResponse
 """
 try:
  handler = TALUrlRewriteFilter(fileBuffer, 
TALOutputConstants.HTML4RewriteAttrs, createRewriter())
  return handler
 except java.io.IOException, exc:
  print "Error creating file output buffer:" + outFileName 
+ ":" + exc.getMessage()
  sys.exit(0)

def evalTemplate(template, outFileName, encoding, globals, 
locals):
 """
  Evaluate the template in the provided namespaces. Output 
the results to file named by outFileName
 """
 try:
  fileBuf = createOutputBuffer(outFileName, encoding)
  rewritingBuf = createRewritingOutputBuffer(fileBuf)
  template.evaluate(rewritingBuf, globals, locals)
  fileBuf.close()
 except TALInterpretException, exc:
  print "Error evaluating template:" + exc.getMessage()
  sys.exit(0)
============================================================
======

> One good thing about your model is that you can 
seperately get at:
> 
> 1. A method that sets the response headers for character 
encoding,
> sets up the encoder event handler for the right encoding, 
then passes
> the document through the whole system to create the 
response.

That's why I redesigned the whole TAL thing, to achieve 
exactly that. As you can see from the code snippet above, 
it makes for nice clean code. If I wanted, I could

1. Set the HTTP headers
2. Set the output stream for the template to be the output 
stream from the response object
3. Evaluate the template

And that's it! Although that wouldn't allow me to do nice 
HTTP 1.1 things like set the content-length and gzip the 
content. If you're interested, I'll send you my demo 
servlet (session tracking, url-rewriting) code.

> 2. The raw SAX2 events. There is no assumption that it is 
generating a
> 'response'. Encoding doesnt come into it.  (I would like 
to get at a
> unicode string, not an event stream, but I think that 
difference is
> trivia)

I have a simple TALByteBuffer which captures the output to 
a byte array.

All output in my system goes through a 
java.io.OutputStreamWriter, which either backs onto a 
java.io.ByteArrayOutputStream or a java.io.FileWriter. The 
transcoding is simply an extra parameter to the 
OutputStreamWriter constructor.

> That is very much more than minor philosophy.

Jython and Java has *really* changed my brain. I can't 
recommend it enough.

But then again, I never made an investment in Zope to begin 
with. What got me interested in ZPT was

1. I was struggling to invent a HTML templating system that 
didn't involve using non-HTML element names, and was not 
getting very far.
2. I happily stumbled on ZPT, which was of course created 
by the Great Guido.
3. The scales fell from my eyes.

Nuff said.

Cheers,

Alan.


---------------------------------------------
This message was sent using WebMail by CyberGate.
http://www.gate.net/webmail