BACK | INDEX | EXIT | NEXT

# The Jetty HTTP Server

Introduction
This section describes the important concepts in the Jetty HttpServer model. It should be read by those with an interest in gaining a deeper insight into the Jetty architecture and those considering writing custom handlers.
The Introduction to the HttpServer explained that the server accepts requests and passes them off to handlers for processing but did not elaborate on how this is acheived. This section discusses the server, listener, context and handler entities and the relationships between them.
HttpServer
The org.mortbay.http.HttpServer class provides a linkage between a collection of request listeners and collections of request handlers:

    HttpListener n-->1 HttpServer 1-->n HttpContext 1-->n HttpHandler
Diagram: HttpServer relationship model

It is the responsibility of an HttpServer to accept requests received by an HttpListener, and match them to suitable HttpContext(s). It does this by using the host and context path elements from the request. Note that more than one HttpContext might match the request, and in this case, all HttpContexts are tried in the order in which they were registered with the server until the request is marked as having been handled.
The trivial code snippet from the Introduction to the HttpServer can then be represented as:

    SocketListener1-->1HttpServer1-->1HttpContext1-->1ResourceHandler
    port:8080                        "/"             "./docroot"
Diagram: Trivial file server object relationships

This depicts a single listener on port 8080 passing requests to a single server, which in turn passes them to a single context with a single handler which returns static content from the directory `./docroot` .
HttpListener
Implementations of the org.mortbay.http.HttpListener interface are added to a HttpServer and act as sources of requests for the server. The org.mortbay.http.SocketListener is the main implementation. It listens on a standard TCP/IP port for requests, but there are also listener implementations for SSL, Non blocking IO, testing and others.

Multiple listeners may be used to listen on different ports and/or on specific IP addresses. This is most frequently used with SSL or with multi-hosting:

    SocketListener -+
    port:80         |
                    |
    JSSEListener   -+> HttpServer --> HttpContext --> ResourceHandler
    port:443        |                 "/"             "./docroot"
                    |
    SocketListener -+
    host:1.2.3.4
    port: 80
Diagram: Multiple listeners with multihosting

Listeners are configured via `set` methods. Listeners can be created by using the HttpServer as a factory to create a standard type of listener:

    HttpServer server=new HttpServer();
    HttpListener listener=
        server.addListener(new InetAddrPort("myhost",8080));
Code Example: Convenience methods for adding standard listeners

However, in order to provide detailed configuration, it is more common to create the listener directly and then add it to the HttpServer:

`
    HttpServer server = new HttpServer();
    SocketListener listener = new SocketListener();
    listener.setHost("myhost");
    listener.setPort(8080);
    listener.setMinThreads(5);
    listener.setMaxThreads(250);
    server.addListener(listener);
` Code Example: Configuring a listener

All HttpListeners are responsible for allocating threads to requests, so most implementations are extensions of the org.mortbay.util.ThreadedServer or org.mortbay.util.ThreadPool. Thus attributes such as min/max threads, min/max idle times etc are also set via the API.

Jetty has several type of HttpListeners including:

- org.mortbay.http.SocketListener for normal http connections.
- org.mortbay.http.JsseListener for SSL https connections using JSSE provider.
- org.mortbay.http.SunJsseListener for SSL https connections using Suns JSSE provider.
- org.mortbay.http.SocketChannelListener for normal http connections using the java.nio library for non-blocking idle connections.
- org.mortbay.http.ajp.AJP13Listener for integration with apache, IIS etc. See FAQ.

HttpContext

A org.mortbay.http.HttpContext aggregates org.mortbay.http.HttpHandler implementations. When a request is passsed to a HttpContext it tries each of its HttpHandlers in turn ( in the order in which they were registered) until the request is marked as handled. Note that it is perfectly possible for more than one handler to process the request, but only one handler can mark the request as being finally handled.

Note that in Jetty 3.1 and previous releases, the HttpContext class was called HandlerContext.

A typical a context might have handlers for security, servlets and static resources:

`
                                                  +-> SecurityHandler
                                                  |
    SocketListener --> HttpServer --> HttpContext +-> ServletHandler
    port: 80                          "/"         |
                                                  +-> ResourceHandler
` Diagram: Single context, multiple handlers

All HttpHandlers within a single HttpContext share the following attributes:

- Initialization parameters
- An optional virtual host name for the context
- A path prefix for the context
- A resource base for loading static resources (files/urls)
- A memory cache of resources (files/urls)
- A ClassLoader and set of Java permissions
- A request log
- Statistics
- Error page mappings
- MIME type suffix maps

A single HttpServer can have multiple HttpContexts. This is typically used to serve several applications from the same port(s) using URL mappings:

`
    SocketListener --> HttpServer +-> HttpContext --> HttpHandler(s)
    port:80                       |   path:"/alpha/*"
                                  |
                                  +-> HttpContext --> HttpHandler(s)
                                      path:"/beta/*"
` Diagram: Multiple contexts with URL mapping

Alternatively, different applications can be served from the same port using virtual hosts:

`
    SocketListener --> HttpServer +-> HttpContext --> HttpHandler(s)
    port:80                       |   vhost: www.alpha.com
                                  |   path: "/"
                                  |
                                  +-> HttpContext --> HttpHandler(s)
                                      vhost: www.beta.com
                                      path: "/"
` Diagram: Multiple contexts with virtual hosts

If multiple contexts are to be served from the same port, but on different IP addresses, then it is possible to give each context its own HttpServer:

`
    SocketListener --> HttpServer --> HttpContext --> HttpHandler(s)
    host:www.alpha.com                path:"/"
    port:80

    SocketListener --> HttpServer --> HttpContext --> HttpHandler(s)
    host:www.beta.com                 path: "/"
    port:80
` Diagram: Multiple servers

HttpContexts can be instantiated by the HttpServer as part of a call to `addContext()` with context args:

    HttpContext context = server.addContext("/mydocs/*");
    context.setResourceBase("./docroot/");
Code Example: Implied context creation

As addContext() will always create a new context instance, it is possible to accidentally create multiple copies of the same context (by calling addContext() with the same parameters). To avoid this, you can use the `getContext()` method instead, which will only create a new context if one with the same specification does not already exist:

    HttpContext context = server.getContext("myhost","/mydocs/*");
    context.setResourceBase("./docroot/");
Code Example: Lazy context creation

The previous example highlights that it is possible specify a virtual host as well as the context path. A single context may be registered with different virtual hosts. Once context configuration becomes complex, it is best to take explicit control over context creation:

    HttpContext context = new HttpContext();
    context.setContextPath("/context/*");
    context.setVirtualHosts(new String[]{"alpa.com","beta.com"});
    context.setResourceBase("./docroot/");
    server.addContext(context);
Code Example: Creating a context with multiple virtual hosts

Developers Note: Derivations of HttpServer may implement the `newHttpContext()` method to change the factory method for creating new contexts. This is used, for example, by the org.mortbay.jetty.Server class to return HttpContext derivations that have convenience methods for configuring servlets. The org.mortbay.jetty.servlet.WebApplicationContext class is a specialization of HttpContext that configures the handlers by looking at the standard web application XML files.

HttpHandler

The org.mortbay.http.HttpHandler interface represents Jetty's core unit of content generation or manipulation. Implementations of this interface can be used to modify or handle requests. Typically, handlers are arranged in a list, and a request presented to each handler in turn until (at most) one indicates that the request has been handled. This allows handlers to:

- Ignore requests that are not applicable
- Handle requests by populating the response and/or generating content
- Modify the request but allow it to pass onto the next handler(s). Headers and attributes may be modified or an InputStream filter added
- Modify the response but allow the request to pass onto the next handler(s). Headers may be modified or OutputStream filters added.

The handlers provided with the org.mortbay.http.handler package are:

ResourceHandler | Serve static content from the resource base of the HttpContext (see below).
SecurityHandler | Provide BASIC and FORM authentication.
HTAccessHandler | Provide apache .htaccess style security.
NotFoundHandler | Handles unserviced requests.
DumpHandler | A debugging tool that dumps the request and response headers.
ForwardHandler | Forward a request to another URL
NullHandler | An abstract base implementation of the interface, used for to derive other handlers.

A ServletHandler and WebApplicationHandler are provided by the org.mortbay.jetty.servlet package and is discussed in detail in the Jetty Server section.

HttpHandlers are tried within a context in the order they were added to the HttpContext. The following code creates a context that checks authentication, then tries a servlet mapping before trying static content then finally dropping through to an error page generator if no handler marks the request as handled:

`
    HttpContext context = server.addContext("/");
    context.add(new SecurityHandler());
    context.add(new ServletHandler());
    context.add(new ResourceHandler());
    context.add(new NotFoundHandler());
` Code Example: Importance of handler ordering

Resource Handler

One of the most common things for a HttpServer to do is to serve static content from a base directory or URL. The org.mortbay.http.handler.ResourceHandler implementation of HttpHandler is provided for this purpose. Its features include:

- Support for GET, PUT, MOVE, DELETE, HEAD and OPTIONS methods.
- Handling of IfModified headers.
- HTTP/1.1 Range support for partial content serving.
- Index/welcome files.
- Generation of directory listings.

The root directory or URL for serving static content is the ResourceBase of the HttpContext. Thus, to serve static content from the directory `"./docroot/"`:

    HttpContext context = server.getContext("/context/*");
    context.setResourceBase("./docroot/");
    ResourceHandler handler = new ResourceHandler();
    handler.setDirAllowed(true);
    handler.setPutAllowed(false);
    handler.setDelAllowed(false);
    handler.setAcceptRanges(true);
    context.addHandler(handler);
    context.addHandler(new NotFoundHandler());
Code Example: Detailed configuration of a ResourceHandler

The `NotFoundHandler` is added to generate a 404 for requests for resources that don't exist. The `ResourceHandler` lets requests that it cannot handle fall through to the next handler.

Developers Note: HttpHandlers ARE ORDER DEPENDANT!. If in the above example the `NotFoundHandler` had been added to the context before the `ResourceHandler`, then all requests would be 404'd and resources would not be served. It is a common mistake to put a `ResourceHandler` before a `ServletHandler` with the JSPServlet, so jsp source code is served rather than the dynamic content from the JSPServlet.

Putting It All Together

Finally, here is a fully worked code example to configure a server on port `8181` serving static content and a dump servlet at `"/mystuff/"` :

    import java.io.*;
    import java.net.*;
    import org.mortbay.util.*;
    import org.mortbay.http.*;
    import org.mortbay.jetty.servlet.*;
    import org.mortbay.http.handler.*;
    import org.mortbay.servlet.*;

    public class SimpleServer
    {
      public static void main (String[] args)
        throws Exception
      {
        // Create the server
        HttpServer server=new HttpServer();

        // Create a port listener
        SocketListener listener=new SocketListener();
        listener.setPort(8181);
        server.addListener(listener);

        // Create a context
        HttpContext context = new HttpContext();
        context.setContextPath("/mystuff/*");
        server.addContext(context);

        // Create a servlet container
        ServletHandler servlets = new ServletHandler();
        context.addHandler(servlets);

        // Map a servlet onto the container
        servlets.addServlet("Dump","/Dump/*","org.mortbay.servlet.Dump");

        // Serve static content from the context
        String home = System.getProperty("jetty.home",".");
        context.setResourceBase(home+"/demo/webapps/jetty/tut/");
        context.addHandler(new ResourceHandler());

        // Start the http server
        server.start ();
      }
    }
Code Example: Setting up an HttpServer

BACK | INDEX | EXIT | NEXT