initializing a servlet in WEBRick

X

Xavier Noria

I am writing a web application where all the requests are served by the
same object, which needs initialization. This is being done this way:

<<initialize some stuff from the command line parameters>>
<<initialize the driver of the application from that stuff>>
server.mount_proc(path) { |req, res| driver.process(req, res) }

That seems to work fine, but I wonder if the driver could be a subclass
of HTTPServlet::AbstractServlet so that one would just say

server.mount(path, DriverServlet)

and have one instance serving all the pages and initialized as needed. I
have tried to figure it out from the sources but don't see how would it
work.

-- fxn
 
G

GOTOU Yuuzou

Hi,

In message said:
I am writing a web application where all the requests are served by the
same object, which needs initialization. This is being done this way:

<<initialize some stuff from the command line parameters>>
<<initialize the driver of the application from that stuff>>
server.mount_proc(path) { |req, res| driver.process(req, res) }

That seems to work fine, but I wonder if the driver could be a subclass
of HTTPServlet::AbstractServlet so that one would just say

server.mount(path, DriverServlet)

and have one instance serving all the pages and initialized as needed. I
have tried to figure it out from the sources but don't see how would it
work.

If it's explained simply, servelets are activated in the
following sequence:

<< accept connection and receive HTTP request >>
<< find a ServletClass associated with path of URL >>

# the third and more arguments of mount() will be passed to options.
servlet = ServletClass.get_instance(server, *options)
servlet.service(req, res)

<< send response >>

If it can respond to get_instance and service, any kind of
object can be mounted as a servelet.

AbstractServlet::get_instance just calls new() and instance
of servelet will be created for every request. Conversely
singleton servelet can be up by overriding of get_instance.

The following sample implements get_instance as a instance
method and initialize a servlet out of server before it's
started.

require 'webrick'

class AccessCounter < WEBrick::HTTPServlet::AbstractServlet
def initialize(server)
@mutex = Mutex.new # service should be MT-safe
@count = 0
end
def get_instance(server)
self # always returns same instance
end
def service(req, res)
@mutex.synchronize{ super }
end
def do_GET(req, res)
res.body = "<html><body>@count=<b>#{@count+=1}</b></body></html>"
res['content-type'] = "text/html"
end
end

svr = WEBrick::HTTPServer.new:)Port => 10080)
counter = AccessCounter.new(svr)
svr.mount("/", counter)
svr.start
 
X

Xavier Noria

If it's explained simply, servelets are activated in the
following sequence:

<< accept connection and receive HTTP request >>
<< find a ServletClass associated with path of URL >>

# the third and more arguments of mount() will be passed to
options. servlet = ServletClass.get_instance(server, *options)
servlet.service(req, res)

<< send response >>

If it can respond to get_instance and service, any kind of
object can be mounted as a servelet.

<< cut >>

That's very helpful, thank you very much GOTOU.

The code shouldn't depend on the implementation of WEBrick however, do
you think we can rely on the outlined sequence

  << accept connection and receive HTTP request >>
  << find a ServletClass associated with path of URL >>

  # the third and more arguments of mount() will be passed to options.
  servlet = ServletClass.get_instance(server, *options)
  servlet.service(req, res)

  << send response >>

?

-- fxn

PS: I am sorry for the typo in the subject.
 
G

GOTOU Yuuzou

In message said:
<< cut >>

That's very helpful, thank you very much GOTOU.

The code shouldn't depend on the implementation of WEBrick however, do
you think we can rely on the outlined sequence

  << accept connection and receive HTTP request >>
  << find a ServletClass associated with path of URL >>

  # the third and more arguments of mount() will be passed to options.
  servlet = ServletClass.get_instance(server, *options)
  servlet.service(req, res)

  << send response >>

Yes, requirement of get_instance and service is the spec
of WEBrick::HTTPServer. I guess it will not be changed.
# at least in Ruby-1.8..

By the way, the code of servlet activation is described in
HTTPServer#service. We can rewrite it to build specific
purpose server or realize another idea about uri-to-service
mapping.

require "webrick"
class NotFoundServer < WEBrick::HTTPServer
def service(req, res)
# returns 404 against every request.
raise WEBrick::HTTPStatus::NotFound
end
end
NotFoundServer.new:)Port=>10080).start
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,125
Messages
2,570,748
Members
47,302
Latest member
MitziWragg

Latest Threads

Top