CGI sessions as threads?

Hello,

One of the things which interests me most about Ruby is its built-in
threading capability.

In particular, I would like to know if anyone has written a library which
allows CGI sessions to be modelled as threads? This would make it extremely
easy to write interactive CGI applications, as the thread would only see
exchanges between itself and its one client.

For example, you might start writing a simple login screen like this:

···

retries = 0

begin
show 'login_page.htm’
u = wait_response
retries+=1
end while retries < 3 && u.username!=‘brian’ && u.password!=‘mypass’

if retries >= 3 then
show 'goaway.htm’
exit
end

show 'main_menu.htm’
u = wait_response

and so on


wait_response blocks until the next CGI request (HTTP post) which is
associated with this particular thread arrives. It also commits suicide if
no response is received within an idle timeout period.

There needs to be a central dispatcher which takes an incoming request,
checks to see if it has a valid session cookie, and if so dispatches it to
the correct thread; if not, then it creates a new thread for it.

Perhaps for safety, the ‘show’ function should set a different cookie every
time, to ensure that the user cannot press ‘back’ multiple times and then
submit an out-of-sequence form - or else the server thread should have the
option of handling this case itself.

Anyway, it seems to me that this ought to be fairly straightforward to
implement, so has anybody done this already? I have a lot of Ruby learning
to do before I would attempt it myself :slight_smile:

Regards,

Brian Candler.

Brian Candler wrote:

Hello,

One of the things which interests me most about Ruby is its built-in
threading capability.

In particular, I would like to know if anyone has written a library which
allows CGI sessions to be modelled as threads? This would make it extremely
easy to write interactive CGI applications, as the thread would only see
exchanges between itself and its one client.

i think you will need at least needs a web server that supports this
model. in apache (unix or windows), a cgi request always ends up forking
a new process.

with fastcgi this is possible, since the fastcgi process lives on
between requests. but i haven’t looked at the available fastcgi ruby
modules to see whether any of them supports multithreading.

···


dave

Brian Candler B.Candler@pobox.com wrote in message news:20021006110515.A13624@uk.tiscali.com

Hello,

One of the things which interests me most about Ruby is its built-in
threading capability.

In particular, I would like to know if anyone has written a library which
allows CGI sessions to be modelled as threads? This would make it extremely
easy to write interactive CGI applications, as the thread would only see
exchanges between itself and its one client.

Brian,

I’ve done a lot of work on and with libraries very much like what you
describe. My talk at RubyConf, in fact, will be on exactly this
approach. Most of my work has been in Smalltalk, although I did spend
some time this summer porting the basic ideas to Ruby; I’ll be
updating that port before my talk. If anyone is interested in taking a
look at it, email me, but if you can wait until November it will be in
much better shape.

A few comments:

For example, you might start writing a simple login screen like this:


retries = 0

begin
show ‘login_page.htm’
u = wait_response
retries+=1
end while retries < 3 && u.username!=‘brian’ && u.password!=‘mypass’

The explicit wait_response in unnecessary - this can just be

begin
u = show ‘login_page.htm’
retries += 1
end while retries < 3 && u.username!=‘brian’ && u.password!=‘mypass’

wait_response blocks until the next CGI request (HTTP post) which is
associated with this particular thread arrives. It also commits suicide if
no response is received within an idle timeout period.

Perhaps for safety, the ‘show’ function should set a different cookie every
time, to ensure that the user cannot press ‘back’ multiple times and then
submit an out-of-sequence form - or else the server thread should have the
option of handling this case itself.

Yes, exactly, although you need to encode this in the URL, not in a
cookie, so that you can actually detect which page the user
backtracked to. What I’ve found works best is this:

  • by default, if the user backtracks (or clones the browser window, or
    whatever), everything keeps working as before. If the user submits a
    form multiple times, that call to show() simply returns multiple
    times
    , and the thread proceeds from there. This is easy to do with
    ruby’s callcc function, and is really what makes the whole approach so
    cool.

  • some times that’s not appropiate; for that, you need to be able to
    set up “transactions” in the thread. For example, a piece of a
    shopping cart app might look like

cart = confirm_cart_contents
cc = ask_for_credit_card
process_payment(cart, cc)
show_thankyou_page

You don’t want a user to hit the back button and change the cart
contents once the credit card has gone through! So you have something
like this:

session.isolate do
cart = confirm_cart_contents
cc = ask_for_credit_card
process_payment(cart, cc)
end
show_thankyou_page

While inside the “isolate” block, backtracking works normally (they
can, for example, go back and change the cart). As soon as the
“isolate” block ends, all of those pages immediately “expire”, in that
attempts to click any links or submit any forms from them will result
in a redirect back to the thankyou page.

Anyway, it seems to me that this ought to be fairly straightforward to
implement, so has anybody done this already? I have a lot of Ruby learning
to do before I would attempt it myself :slight_smile:

The core is indeed very straightforward to implement; it’s probably
about 40 lines of code. What’s fun is all the great stuff you can
build on top once you have this basic facility…

Incidentally, as others have pointed out, this won’t work as straight
CGI; the expirements I’ve done in Ruby use WEBrick, but FastCGI would
also work.

Cheers,
Avi

“David Garamond” davegaramond@icqmail.com wrote in message
news:3DA00E47.9090406@icqmail.com

with fastcgi this is possible, since the fastcgi process lives on
between requests. but i haven’t looked at the available fastcgi ruby
modules to see whether any of them supports multithreading.

According to the Ruby FastCGI page the clean Ruby version supports multiple
connections on the same socket (multiplexing) but it will only be beneficial
with Apache 2.0 which is multithreaded.
But then mod_fastcgi has not yet been released for Apache 2.0 although there
are development versions.

Mikkel

That sounds excellent, exactly what I was looking for. I look forward to
seeing the public release :slight_smile:

Regards,

Brian.

···

On Mon, Oct 07, 2002 at 04:31:23AM +0900, Avi Bryant wrote:

I've done a lot of work on and with libraries very much like what you
describe. My talk at RubyConf, in fact, will be on exactly this
approach. Most of my work has been in Smalltalk, although I did spend
some time this summer porting the basic ideas to Ruby; I'll be
updating that port before my talk. If anyone is interested in taking a
look at it, email me, but if you can wait until November it will be in
much better shape.