Websela

Archive for May 2015

Two years ago I posted that I’d put a stripped down HTTPView2/Seaside into Cuis. At the time there was no response. I was asked on Wednesday if I still had the image. Not likely. Since then I’ve probably bought two new laptops and had two TimeMachines fail on me. So could I rebuild it? Ah…maybe.

I rebuilt it and posted a link (and script for Squeak) on both the Cuis and Squeak mailing lists. Look for a Chris Cunnington post dated 29 May if you want to download the image for Cuis or install using a script for Squeak.

The interest in Cuis for a web framework comes from recent advances in porting Andreas Raab’s WebClient to Cuis. This prompted Edgar to ask me if I still had a framework. I must say I was surprised. Just about everything I build sinks without a trace of interest.

I need to document some things about what I’ve done. Or more importantly, what I haven’t done. This can better allow the Cuis community to either use GreenNeon or leapfrog it with something better.

I’ll address that in four areas: where GreenNeon came from; what it is; how to use it; and, how I ported it to Cuis.

That ends the general specification of this blog post. From here I’m going to go down a rabbit hole of details.

About twelve years ago Avi Bryant and Goran Krampe worked together to bring the HTML domain into Squeak Smalltalk. Their first creation was a Builder like the WAHtmlBuilder in old Seaside images. The big idea was to have one selector for each HTML tag. They built it, it worked, and they found the limitations of that idea fast. Those of you who remember David Shaffer’s blog documentation on Seaside will remember the long selectors that would take six arguments at a time. This wasn’t ideal, so they decided to work on another coded representation of the HTML domain in Smalltalk. This lead them to the Canvas like WAHtmlCanvas.

The big idea here was to have a class for each tag instead of a selector for each tag. The Seaside 2.6 image came with both the WAHtmlBuilder and the WAHtmlCanvas. There was a selector for choosing which to use called #rendererClass, a builder or a canvas. But let’s step back to where Avi and Goran created the Builder.

Avi created Seaside and Goran created HTTPView2. The main difference was the dispatching mechanism. By that I mean how a URI in a request finds the objects it needs to return a response. Continuations in Seaside required a 24-character token. HTTPView2 was more RESTful in that it used conventional looking URIs (i.e. /page/secondtierpage/resource.jpg).

HTTPView2 never adopted a canvas. If you download it into Squeak using SqueakMap you will see it still uses a builder called HVBuilder. A half completed canvas is there, but was never used. As a result, the page descriptions are messier, because one of the virtues of a one-tag-one-class canvas system is a neater looking method. I should point out that the canvas is what Seaside uses to this day.

Goran was ahead of Avi in wiki creation. Avi borrowed some code to create a simple wiki maker in Seaside 2, which stored the text in a method as a string.

Avi’s Seaside went on to be used for SqueakSource and other projects. HTTView2 was used only once and you can still find it online as the SqueakMap server at http://map.squeak.org.

There’s one more piece of background I need to give you. Andreas Raab created a replacement of the Comanche server called WebClient. It’s the success of Cuis programmers to port WebClient to Cuis that porting GreenNeon to Cuis is possible.

HTTPView2 in the SqueakMap server online uses the Comanche server, the HVBuilder for rendering the HTML domain in Smalltalk, and a RESTful dispatcher focused in HVTransientView>>#dispatchOn:.

I took the HTTPView2, replaced the HVBuilder with a WACanvas from a Seaside 2.6. Then I created an adaptor (i.e. GNAdaptor) to replace the Comanche server with WebClient.

Let’s sum up. GreenNeon can do anything that SqueakMap server can do. If you are familiar with Seaside page creation in #renderContentOn: methods, then you are familiar with how GreenNeon adds tags. The part you are not going to be familiar with is the dispatching mechanism adopted from HTTPView2. How does GreenNeon relate the URI to an object with tags to produce an outgoing stream?

Let’s start simple. Say you have “foo.com”. It’s implied that you are accessing the “/” URI. Then the dispatcher looks for the #default selector in the class with your pages in it.

Hold it. I need to back up again.

Let’s say you want to create a Hello World class. You need to subclass from HVTransientView. Let’s call that SuperDuperHelloWorld. We will return to how to add tags in a second. Go to a Workspace and execute “SuperDuperHelloWorld startOn: 9981”. This will start a listening process, which you will see in the ProcessBrowser. (Incidentally that is where you need to kill GreenNeon processes. There are no #start or #stop selectors.)

We have a class. It’s running in a process. The request will be routed to the correct class which we have called SuperDuperHelloWorld. Because we are requesting “foo.com” it will default to a selector called #default. That’s where we put our tag statements like this:

default
	html := self canvas.
	html buildHead.
	html p: 'Hello World !'.
	^html

If you are a Seaside user this will look familiar and weird at the same time. In the usual #renderContentOn: the canvas and head are built somewhere else. And the selector does not terminate with a return caret (i.e. “^”). In Seaside, your selector is one selector inside a class of a graph of classes sent to be rendered with the Chain Of Responsibility pattern. You’ve used composition to create a Composite pattern, decorated it with the Decorator pattern and render the lot to a stream. GreenNeon is a bit simpler.

Each selector is its own page. If in SuperDuperHelloWorld we have selectors for #foo, #bar, #red and #car, then we can make requests like foo.com/foo, foo.com/bar, foo.com/red and foo.com/car. One selector for each page.

This poses an obvious problem. How do we get to second tier pages? How do we reach foo.com/bar/sega or foo.com/bar/genesis? HTTPView2 uses double dispatch. You pass the request from one class where the selectors are whole pages to another class where the selectors are whole pages. I’ll spare myself explaining that for the moment. If there’s any interest, I can blog on that sometime.

What did I add to Cuis to port GreenNeon from Squeak to Cuis?

The Url hierarchy including Url, GenericUrl, FileUrl, etc. All subclasses of Url.

Some methods to String>>#squeakToIso,#utf8ToIso, BlockClosure>>#renderOn:, BlockContext>>#renderOn: and Object>>#asSeasideString,#convertSeasideString:,#renderOn:,#contentsChanged.

I added ValueHolder.

It think that’s about it. That list is not exact or complete.

Cuis renamed WebClient as HTTPClient. It’s included in the core packages in /Packages/Protocols-HTTP.pck.st. HTTPServer is in GNAdaptor>>startOn:.