Originally I generated the sitemap for onsmalltalk as a file on disk and let Apache serve it up. There's nothing wrong with this approach but it'd be cooler if I had Seaside generate and render it on demand and serve as a good excuse to talk about serving up content statelessly in Seaside.
Seaside is a session based web framework, but there's nothing really session specific about a sitemap and I really don't want a new session created when a request for a sitemap is made. There's a lot of overhead in doing that and sometimes you just want to serve up stuff statelessly. When a request comes in, the application mounted on the base URL handles the request by plucking the session id out of the cookie or the URL and either creates a new session or finds the existing one needed to handle the current request. Once found, the request is pumped through the current session which runs through a similar procedure looking for a continuation to invoke.
Since I want to avoid all that and just handle the request at the application level I'll override #handleRequest: in my custom WAApplication subclass, check the URL of the current request and either render the sitemap and end the request by immediately returning a response, or allow processing to continue normally into the session lookup done by the call to super.
handleRequest: aRequest
(aRequest url endsWith: '/sitemap.xml') ifTrue:
[ ^WAResponse new
beXML;
cacheFor: 1 hour;
contents: (self siteMapFrom: aRequest) asString readStream;
yourself ]
^super handleRequest: aRequest
siteMapFrom: aRequest
^ (SBSiteMapGenerator blogRoot: ('http://{1}/' format: { (aRequest host) }))
generateFromItems: { (SBPost new) } , (SBBlog onSmalltalk publicPosts) , SBTag findAll.
If you have things in your application that can be done statelessly, this is a good place to hook into the framework and take care of that stuff at the application level. Sometimes you don't need all that fancy Seaside stuff and you just want to work directly with HTTP requests and responses.
Two small methods and the sitemap is now generated dynamically, and statelessly directly from Seaside, removing the need to manually invoke the sitemap generation as I had previously been doing to the file system.
Oh, one small extension that I've put on WAResponse and use occasionally...
cacheFor: aDuration
self headerAt: 'Expires' put: (TimeStamp now + aDuration) httpFormat