Updated 2004-06-13 01:23:29 by CMCc

TclHttpd Needs Stacked domain handlers

Now it's got something like them. HEAD has a -filter argument to [UrlPrefixInstall] and a [Httpd_Filter] command. It provides for a stack of filtering commands which will be run (in reverse order of definition) over data returned by [ReturnData] and [ReturnCacheableData]. Takes args sock and content and is expected to transform the contents on the way to the client. -- 20040613 CMcC

NEM: It's been a little while since I last tinkered with tclhttpd, so this may be inaccuarate. Last time I looked though, you could register a domain handler with the Url_PrefixInstall stuff, and anything from that prefix down would be processed by that script. However, this does longest matching prefix handling. In some cases, it would be nice to be able to nest these domain handlers, so the output of one is fed into another. Something like:
 Url_PrefixInstall /docs [list ProcessDoc]
 Url_PrefixInstall /docs/man [list ProcessMan]
 Url_PrefixInstall /docs/tutorials [list ProcessTutorial]

So, a call to /docs/man/Tcl.n would result in a call to ProcessMan (which could, say, generate XML from a manpage), and then a call to ProcessDoc (which could then generate html/wml/pdf etc from the XML):
 GET /docs/man/Tcl.n HTTP/1.1
 ProcessDoc [ProcessMan /Tcl.n]

Something like that anyway. Perhaps an Url_PrefixInstallNested? Or an option to Url_PrefixInstall?

CMCc I've often thought it would be nice if you could wrap successively higher layers in the URL hierarchy with extra functionality on the way up, and filter and transform requests on the way down.

I don't like the way you suggest, because it would mean changing the Url prefix matching stuff, which already entails a complex regsub, and because I think it would uglify the prefix installation API.

OTOH, I don't tend to use direct domains much, I tend to prefer templates. Perhaps it's worth a [TclHttpd Direct vs. Template] to discuss the differences and virtues of each.

I find you can get some of the desired functionality with .tml documents, because the ./.tml files are sourced from docroot down to containing directory. You can use that to filter URL events going downward, but not to transform them on the way back up.

TclHttpd already has a post-processing callback facility [Httpd_CompletionCallback], but this won't do what you need, because the data's already gone up the spout by then. It's mainly for cleaning up state, I suppose.

In a way, the URL hierarchy is like a widget hierarchy, and incoming calls are like events. Perhaps One could write a domain handler that provided that kind of facility.

All non-exception data goes to the client by way of [Httpd_ReturnData], [Httpd_ReturnCacheableData] or [Httpd_ReturnFile]. These procs all follow roughly the same process:

  • [HttpdRespondHeader] to send common http header elements
  • [HttpdSetCookie] to send any cookies to the client
  • add some more headers
  • send the data to $sock
  • [Httpd_SockClose] (eventually) to finish the reply.

It seems to me that we could easily intervene at the 4th step, to provide some post-processing of data on the wire, as it were. Errors would have to be handled carefully, and redirects and such wouldn't be possible, but one could transform the data on the way back.

By providing a stack of procs to invoke to transform the data, one could effectively do what you (and I) want, at the cost of inspecting some global state (to see if there are stacked transformers) which one could presumably store in the Httpd$sock array under something like data(transform), data(stack) or similar. Cost for normal pages, one 'if {[info exists data(stack)]}'.

NEM - Thanks for separating out this page, and thanks for the info. I'm thinking about writing a small content management system around tclhttpd called ArTcl (as you know). I was planning on implementing it as an Url_PrefixInstall'ed handler, but it would definitely be better if I could hook in closer to the existing infrastructure, as I wouldn't have to reinvent so many wheels for just a little extra functionality. With regards to templates (.tml stuff), I must confess to not having given it much of a look to date, as it seemed like a Tcl version of JSP, which I'm not a huge fan of. Is tml restricted to just generating HTML? Or can it generate arbitrary XML? If the latter, I imagine some powerful things could be done with tdom being used to post-process the results into different formats.

BTW - I really like the observation that URL hierachies are like widget hierachies, with events being delivered... you've got some cogs whirring in my brain now!

CMCc - I don't know anything about JSP. As it stands, the server only looks for templates if it's trying to deliver a URL with suffix .html, it then generates and potentially caches the resultant .html. A .tml file can set its own mime content type, and that can be anything, so I believe you can deliver any content type, but it will always have a .html suffix. I'm proposing a generalisation of template handling, so one could have (say) .csst templates generating .css files, and benefit from the suffix->mime type association. I'll copy the proposal to the Wiki.

You've reminded me that in the stacking idea, we'd need to transform the data before the content-type was sent, so transformation would be before the respond header call, which might also permit redirection, etc.

I find .tml is able to do pretty much anything direct can do, but it is a bit more of a hassle to arrange arguments, etc. Perhaps there's a middle ground with the benefits of both to be had. The Doc domain, under which templating occurs, is certainly feature rich - it gives you things like templating, caching, file-listing, directory aggregation, post-processing by mime type, pretty easy session handling, and subst-semantics.

[ Category TclHttpd ]