Writing WEBrick Servlets

WEBrick is an HTTP server written in Ruby that uses servlets to extend its capabilities. Built into WEBrick are four servlets, handling CGI, ERb, file directories, and a generic Proc servlet. These are built on an abstract servlet class that makes it easy to build your own WEBrick servlets.

You will need either Ruby 1.8 or an older version of Ruby with WEBrick installed.

WEBrick::HTTPServlet::AbstractServlet

WEBrick's AbstractServlet provides a simple way of servicing HTTP requests. For each HTTP request method you want to handle you implement a method to handle it. For example, to handle a GET, you implement the do_GET method.

A Simple Servlet

Here is a simple servlet:

require 'webrick'

class Simple < WEBrick::HTTPServlet::AbstractServlet
  
  def do_GET(request, response)
    status, content_type, body = do_stuff_with(request)
    
    response.status = status
    response['Content-Type'] = content_type
    response.body = body
  end
  
  def do_stuff_with(request)
    return 200, "text/plain", "you got a page"
  end
  
end

A Configureable Servlet

So now we have a simple servlet, but right now it is completely unconfigurable. Let us add an initialize method to it:

class Configureable < Simple
  
  def initialize(server, color, size)
    super(server)
    @color = color
    @size = size
  end
  
  def do_stuff_with(request)
    content = "<p style="color: #{@color}; font-size: #{@size}">some text"
    return 200, "text/html", content
  end
  
end

Initializing Servlets

Now you may be wondering what the server argument is for. When initializing a servlet, WEBrick provides three handy instance variables for your use, @server, @logger, and @options. @server allows you to access the current server, with which you can check server configuration variables. @logger allows you to easily log the status of your servlet, and @options can be used as a generic way of retrieving servlet configuration (I prefer to use instance variables directly).

Those arguments get passed to your servlet by WEBrick when a request matches a path you mounted your servlet on. Here is how you mount a servlet:

server = WEBrick::HTTPServer.new
server.mount "/configurable", Configureable, "red", "2em"

The first argument to mount is the path that the servlet will be handling. The second is the class of your servlet, and any arguments after get passed to the servlet when it is initialized. The code above will create a servlet that returns pages with red text twice the usual size for any request under "/configurable". (In other words, your servlet gets initialized like this: Configureable.new server, "red", "2em".)

Controlling Servlet Creation

By default, a new servlet gets created for every request. Fortunately WEBrick provides an easy way to work around this if creation of a servlet is expensive through AbstractServlet's get_instance class method. Here is the default get_instance for AbstractServlet:

class AbstractServlet
  def self.get_instance(server, *options)
    self.new(server, *options)
  end
end

If you need to, you can override this method with your own that creates, for example, a pool of servlets to use.

Redirecting to Directories

AbstractServlet has one additional convenience method, \#redirect_to_directory_uri which will redirect the user from a path without a trailing '/' to a path with a trailing '/'. Pass it the request and response from the do_* method.

Download

Download the WEBrick servlet example presented above to play with. Running the servlet example will start an HTTP server on your machine that listens on port 8000 and handles requests for /simple and /configurable.