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'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.
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
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
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".)
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.
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 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.