Thanks to the excellent tutorials, it was no problem to start building Seaside applications.
I am however at a loss at how the larger HTTP server infrastructure (Comanche ?) works. Does there exist *any* good/recent documentation about this ? By looking at some code and wiki pages, there seem to be multiple HTTP servers...
For example, what is the right/simple way to serve some static files ? There seem to be several ways of doing it, but I can't get any of them to work reliably. Where can I learn more about this ?
Thx,
Sven
Sven Van Caekenberghe wrote:
For example, what is the right/simple way to serve some static files ? There seem to be several ways of doing it, but I can't get any of them to work reliably. Where can I learn more about this ?
Here is what I do:
I have a custom subclass of WAKom (which I happen to call ComancheInterface) for connecting Comanche to Seaside. (I use Comanche 5.x, and Seaside 2.x -- Sorry, I've forgotten what the 'x' value is for both of them).
I implement a ComancheInterface>>process: method that essentially does this:
process: aRequest | url | httpRequest _ aRequest. url _ httpRequest url. (url beginsWith: '/seaside/') ifTrue: [^ self processSeaside: aRequest]. self processMultipartFields: aRequest. ^ self siteManager process: httpRequest
Then, my #processSeaside: method is essential WAKom's process: method.
'self siteManager' just returns a normal Comanche module that is appropriate for the incoming URL. The default siteManager module has a #process: method similar to the following:
process: aRequest | str docFile doc | doc _ self relativePath. (self class cgiMap at: doc ifAbsent: []) isNil ifFalse: [^ self perform: (self class cgiMap at: doc)]. [docFile _ (FileDirectory on: self docRoot) oldFileNamed: doc] on: FileDoesNotExistException do: [:ex | self logError: ex asString. ^ self errorPage]. (docFile name endsWith: 'ssp') ifTrue: [str _ HTMLformatter evalEmbedded: docFile contents with: httpRequest. docFile close] ifFalse: [str _ docFile]. ^ str
With this approach, for any URL that does *not* have '/seaside/' in it, Comanche handles it. When Comanche handles it, my default #process: method for Comanche allows classic cgi style processing, as well as ssp processing (for embedding Smalltalk code into the pages), as well as static file serving. And, instead of the default, I can insert any Comanche module into it instead.
And, for any URL that has '/seaside/' in it, the request is passed to Seaside.
Thus, static file serving, and a bunch more, is integrated into Seaside.
In actual practice, though, I find myself never using ssp, or any cgi-style processing, or any other Comanche modules, or any other tricks. On my bountifulbaby.com site, everything is either pure Seaside (with '/seaside/' in the URL), or else a jpg image served statically. And most of the time I don't even serve the images statically that way, as I instead let Earthlink host the pictures, and my site just serves pure Seaside.
In fact, in hindsight, I doubt I would have bothered with all of the above. I'd have probably just let my site serve Seaside, and let my Earthlink site serve all of the static stuff. The static stuff (i.e., pictures) are the most bandwidth intensive-- let it chew up Earthlink's bandwidth rather than mine. :-) Of course, I pay an extra $19.95 a month for that privilege, but it's worth it.
Nevin
On 17 Nov 2003, at 17:40, Nevin Pratt wrote:
Sven Van Caekenberghe wrote:
For example, what is the right/simple way to serve some static files ? There seem to be several ways of doing it, but I can't get any of them to work reliably. Where can I learn more about this ?
Here is what I do:
I have a custom subclass of WAKom (which I happen to call ComancheInterface) for connecting Comanche to Seaside. (I use Comanche 5.x, and Seaside 2.x -- Sorry, I've forgotten what the 'x' value is for both of them).
...
In fact, in hindsight, I doubt I would have bothered with all of the above. I'd have probably just let my site serve Seaside, and let my Earthlink site serve all of the static stuff. The static stuff (i.e., pictures) are the most bandwidth intensive-- let it chew up Earthlink's bandwidth rather than mine. :-) Of course, I pay an extra $19.95 a month for that privilege, but it's worth it.
Google found a previous posting of you where you explained your approach - minus the last paragraph. Why did you do it that way ? To get both seaside and static http on the same port ? For speed reasons ?
Sven
Sven Van Caekenberghe wrote:
In fact, in hindsight, I doubt I would have bothered with all of the above. I'd have probably just let my site serve Seaside, and let my Earthlink site serve all of the static stuff. The static stuff (i.e., pictures) are the most bandwidth intensive-- let it chew up Earthlink's bandwidth rather than mine. :-) Of course, I pay an extra $19.95 a month for that privilege, but it's worth it.
Google found a previous posting of you where you explained your approach - minus the last paragraph. Why did you do it that way ? To get both seaside and static http on the same port ? For speed reasons ?
You mean, why do I let Earthlink host my pictures?
Bandwidth. Pure and simple. I only have a 300k uplink speed coming from my site. But, minus the pictures, 300k is quite good.
Or, did you mean, why did I ever set Comanche up to integrate static content with Seaside?
Well, because I didn't always have Earthlink hosting my pictures.
Nevin
On 17 Nov 2003, at 19:53, Nevin Pratt wrote:
Sven Van Caekenberghe wrote:
In fact, in hindsight, I doubt I would have bothered with all of the above. I'd have probably just let my site serve Seaside, and let my Earthlink site serve all of the static stuff. The static stuff (i.e., pictures) are the most bandwidth intensive-- let it chew up Earthlink's bandwidth rather than mine. :-) Of course, I pay an extra $19.95 a month for that privilege, but it's worth it.
Google found a previous posting of you where you explained your approach - minus the last paragraph. Why did you do it that way ? To get both seaside and static http on the same port ? For speed reasons ?
You mean, why do I let Earthlink host my pictures?
Bandwidth. Pure and simple. I only have a 300k uplink speed coming from my site. But, minus the pictures, 300k is quite good.
Or, did you mean, why did I ever set Comanche up to integrate static content with Seaside?
Well, because I didn't always have Earthlink hosting my pictures.
No, my question was, why make a subclass of WAKom instead of a module/plug/whatever directly in Comanche ?
Sven Van Caekenberghe wrote:
No, my question was, why make a subclass of WAKom instead of a module/plug/whatever directly in Comanche ?
I'm using Comanche 5, not Comanche 6. In Comanche 5 (with Seaside), WAKom was already there to connect Comanche to Seaside. I just wanted to specialize WAKom's behavior a little bit. So, a subclass seemed, at the time, to be the "right thing".
Nevin
On 18 Nov 2003, at 00:20, Nevin Pratt wrote:
Sven Van Caekenberghe wrote:
No, my question was, why make a subclass of WAKom instead of a module/plug/whatever directly in Comanche ?
To answer my own question: I now have Seaside, static file serving and XML-RPC in one image, under the same port using this code:
| ma xmlrpc seaside | ma := ModuleAssembly core. ma serverRoot: (FileDirectory on: '/Users/sven/Sites/') fullName. xmlrpc := XMLRPCHttpModule new. ma alias: '/xmlrpc' to: [ma addPlug: [:request | xmlrpc process: request]]. seaside := WAKom default. ma alias: '/seaside' to: [ma addPlug: [:request | seaside process: request]]. ma documentRoot: (FileDirectory on: '/Users/sven/Sites/') fullName. ma directoryIndex: 'index.html index.htm'. ma serveFiles. (HttpService startOn: 9090 named: 'httpd') plug: ma rootModule
This is very elegant, I like begin to like the heavily refactored design that was confusing at first.
Sven
Sven Van Caekenberghe wrote:
On 18 Nov 2003, at 00:20, Nevin Pratt wrote:
Sven Van Caekenberghe wrote:
No, my question was, why make a subclass of WAKom instead of a module/plug/whatever directly in Comanche ?
To answer my own question: I now have Seaside, static file serving and XML-RPC in one image, under the same port using this code:
| ma xmlrpc seaside | ma := ModuleAssembly core. ma serverRoot: (FileDirectory on: '/Users/sven/Sites/') fullName. xmlrpc := XMLRPCHttpModule new. ma alias: '/xmlrpc' to: [ma addPlug: [:request | xmlrpc process: request]]. seaside := WAKom default. ma alias: '/seaside' to: [ma addPlug: [:request | seaside process: request]]. ma documentRoot: (FileDirectory on: '/Users/sven/Sites/') fullName. ma directoryIndex: 'index.html index.htm'. ma serveFiles. (HttpService startOn: 9090 named: 'httpd') plug: ma rootModule
This is very elegant, I like begin to like the heavily refactored design that was confusing at first.
Sven
Actually, it can get more elegant than that. If the XML-RPC and Seaside modules were both implemented as subclasses of ComancheModule, you could do something like:
| ma | ma := ModuleAssembly core. ma serverRoot: (FileDirectory on: '/Users/sven/Sites/') fullName. ma alias: '/xmlrpc' to: [ma addModule: XMLRPCModule new]. ma alias: '/seaside' to: [ma addModule: SeasideModule new]. ma documentRoot: (FileDirectory on: '/Users/sven/Sites/') fullName. ma directoryIndex: 'index.html index.htm'. ma serveFiles. (HttpService startOn: 9090 named: 'httpd') plug: ma rootModule
The Seaside and XML modules could also extend the ModuleAssembly class with new methods such that you could then refine this to something like:
| ma | ma := ModuleAssembly core. ma serverRoot: (FileDirectory on: '/Users/sven/Sites/') fullName. ma alias: '/xmlrpc' to: [ma enableXMLRPC]. ma alias: '/seaside' to: [ma invokeSeaside]. ma documentRoot: (FileDirectory on: '/Users/sven/Sites/') fullName. ma directoryIndex: 'index.html index.htm'. ma serveFiles. (HttpService startOn: 9090 named: 'httpd') plug: ma rootModule
The #addPlug: method is intended to be used where you really need to plug in a Block or MessageSend (i.e. you need to adapt to something that doesn't implement the ComancheModule protocol).
- Stephen
On Nov 19, 2003, at 6:27 AM, Stephen Pair wrote:
Actually, it can get more elegant than that. If the XML-RPC and Seaside modules were both implemented as subclasses of ComancheModule, you could do something like:
| ma | ma := ModuleAssembly core. ma serverRoot: (FileDirectory on: '/Users/sven/Sites/') fullName. ma alias: '/xmlrpc' to: [ma addModule: XMLRPCModule new]. ma alias: '/seaside' to: [ma addModule: SeasideModule new].
WAKom isn't a subclass of ComancheModule, but I believe I've implemented the right methods for this to work (substituting "WAKom default" for "SeasideModule new"). You can also use WAKom to wrap any individual Seaside request handler (like a single application), you don't have to use the default.
Sven Van Caekenberghe wrote:
Thanks to the excellent tutorials, it was no problem to start building Seaside applications.
I am however at a loss at how the larger HTTP server infrastructure (Comanche ?) works. Does there exist *any* good/recent documentation about this ? By looking at some code and wiki pages, there seem to be multiple HTTP servers...
For example, what is the right/simple way to serve some static files ? There seem to be several ways of doing it, but I can't get any of them to work reliably. Where can I learn more about this ?
Sven,
For Comanche 6.2, the following will start an http file server on your default directory:
| ma | ma := ModuleAssembly core. ma serverRoot: FileDirectory default fullName. ma documentRoot: FileDirectory default fullName. ma directoryIndex: 'index.html index.htm'. ma serveFiles. (HttpService startOn: 8080 named: 'httpd') plug: ma rootModule
The best docs for Comanche 6.2 (registered as KomHttpServer on SqueakMap) are located in various class comments. Start with the class comments for KomHttpServerInfo. Most (if not all) of the ComancheModule subclasses also include helpful class comments with examples.
- Stephen
On 17 Nov 2003, at 17:47, Stephen Pair wrote:
For Comanche 6.2, the following will start an http file server on your default directory:
| ma | ma := ModuleAssembly core. ma serverRoot: FileDirectory default fullName. ma documentRoot: FileDirectory default fullName. ma directoryIndex: 'index.html index.htm'. ma serveFiles. (HttpService startOn: 8080 named: 'httpd') plug: ma rootModule
Yeah, I found that somewhere in a class comment, I now have it working as
| ma | ma := ModuleAssembly core. ma serverRoot: (FileDirectory on: '/Users/sven/Sites/') fullName. ma documentRoot: (FileDirectory on: '/Users/sven/Sites/') fullName. ma directoryIndex: 'index.html index.htm'. ma serveFiles. (HttpService startOn: 8080 named: 'httpd') plug: ma rootModule
I don't understand the difference between #serverRoot and #documentRoot, I thought an HTTP service only needed a directory to serve files from, and an optional URL prefix ?
The best docs for Comanche 6.2 (registered as KomHttpServer on SqueakMap) are located in various class comments. Start with the class comments for KomHttpServerInfo. Most (if not all) of the ComancheModule subclasses also include helpful class comments with examples.
There are indeed some class comments, but the overall structure is quite factored and hard to follow/grasp. Many classes in Squeak(Map) are lacking (class) comments. Unless I am mistaken and remember it incorrectly, VisualWorks used to be (and maybe still is) much better in that respect (let alone the fact that there was a real manual).
Thanks for the help,
Sven
Sven Van Caekenberghe wrote:
On 17 Nov 2003, at 17:47, Stephen Pair wrote:
For Comanche 6.2, the following will start an http file server on your default directory:
| ma | ma := ModuleAssembly core. ma serverRoot: FileDirectory default fullName. ma documentRoot: FileDirectory default fullName. ma directoryIndex: 'index.html index.htm'. ma serveFiles. (HttpService startOn: 8080 named: 'httpd') plug: ma rootModule
Yeah, I found that somewhere in a class comment, I now have it working as
| ma | ma := ModuleAssembly core. ma serverRoot: (FileDirectory on: '/Users/sven/Sites/') fullName. ma documentRoot: (FileDirectory on: '/Users/sven/Sites/') fullName. ma directoryIndex: 'index.html index.htm'. ma serveFiles. (HttpService startOn: 8080 named: 'httpd') plug: ma rootModule
I don't understand the difference between #serverRoot and #documentRoot, I thought an HTTP service only needed a directory to serve files from, and an optional URL prefix ?
This was originally intended to be something akin to Apache's notion of a server root and a document root. The document root can be different in different contents (i.e. for different virtual hosts) and is used to establish the root path for serving static documents from disk. Server root is a location on disk that is not in the document root hiearchy and is thus appropriate for things that shouldn't be accessible over the web. A module could use this path to store configuration settings or something (as an example). However, at this point, I don't think anything uses the server root variable.
The best docs for Comanche 6.2 (registered as KomHttpServer on SqueakMap) are located in various class comments. Start with the class comments for KomHttpServerInfo. Most (if not all) of the ComancheModule subclasses also include helpful class comments with examples.
There are indeed some class comments, but the overall structure is quite factored and hard to follow/grasp. Many classes in Squeak(Map) are lacking (class) comments. Unless I am mistaken and remember it incorrectly, VisualWorks used to be (and maybe still is) much better in that respect (let alone the fact that there was a real manual).
Yes, I know...with Comanche I've tried to be better that what is typically found in Squeak (therefore, people often just assume that Comanche has no docs). I just checked and all but one class (the SUnit test class) in the KomHttpServer package is documented with class comments.
The basic idea in Comanche is that an HttpRequest is received then delegated to a hierarchy of ComancheModules. A module accepts a request and decides if it can build a response or whether it should delegate the request to its sub-modules. Some modules transform a request on the way in, and other modules will modify a response on the way out, and still others do both.
- Stephen
On Nov 17, 2003, at 7:57 AM, Sven Van Caekenberghe wrote:
For example, what is the right/simple way to serve some static files ? There seem to be several ways of doing it, but I can't get any of them to work reliably. Where can I learn more about this ?
I'm curious what the several ways are that you tried, and which of them were unreliable.
Personally, if I had a lot of static files and I wanted them served fast, I would let Apache do it, and graft my Seaside application into Apache's URL space using mod_proxy.
On the other hand, if I had only a few static files and wanted the simplest deployment package, I would suck them into the image (maybe even managing them as Smalltalk source by sticking them into a string literal somewhere), and use the #anchorWithDocument: methods.
On 17 Nov 2003, at 23:34, Avi Bryant wrote:
On Nov 17, 2003, at 7:57 AM, Sven Van Caekenberghe wrote:
For example, what is the right/simple way to serve some static files ? There seem to be several ways of doing it, but I can't get any of them to work reliably. Where can I learn more about this ?
I'm curious what the several ways are that you tried, and which of them were unreliable.
I was fiddling with StaticFileModule, the aproach described by Stephen and the one described by Nevin. With 'unreliable' I meant that (due to my lack of understanding) I failed to get any of them working well (especially since everytime you try one of them, you get yet another service ;-)
Personally, if I had a lot of static files and I wanted them served fast, I would let Apache do it, and graft my Seaside application into Apache's URL space using mod_proxy.
On the other hand, if I had only a few static files and wanted the simplest deployment package, I would suck them into the image (maybe even managing them as Smalltalk source by sticking them into a string literal somewhere), and use the #anchorWithDocument: methods.
Very valid point. I did not yet notice the #anchorWithDocument method - interesting.
Thx,
Sven
seaside@lists.squeakfoundation.org