| // ======================================================================== |
| // Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. |
| // ======================================================================== |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // and Apache License v2.0 which accompanies this distribution. |
| // |
| // The Eclipse Public License is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| // |
| // The Apache License v2.0 is available at |
| // http://www.opensource.org/licenses/apache2.0.php |
| // |
| // You may elect to redistribute this code under either of these licenses. |
| // ======================================================================== |
| |
| [[writing-custom-handlers]] |
| === Writing Custom Handlers |
| |
| The Handler is the Jetty component that deals with received requests. |
| |
| Many users of Jetty never need to write a Jetty Handler, but instead use the link:{JXURL}/org/eclipse/jetty/servlet/package-summary.html[Servlet API.] |
| You can reuse the existing Jetty handlers for context, security, sessions and servlets without the need for extension. |
| However, some users might have special requirements or footprint concerns that prohibit the use of the full servlet API. |
| For them implementing a Jetty handler is a straight forward way to provide dynamic web content with a minimum of fuss. |
| |
| See the section on xref:basic-architecture[] to understand more about Handlers vs. Servlets. |
| |
| [[handler-api]] |
| ==== The Handler API |
| |
| The link:{JDURL}/org/eclipse/jetty/server/Handler.html[Handler] interface provides Jetty's core of content generation or manipulation. |
| Classes that implement this interface are used to coordinate requests, filter requests and generate content. |
| |
| The core API of the Handler interface is: |
| |
| [source, java, subs="{sub-order}"] |
| ---- |
| public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) |
| throws IOException, ServletException |
| ---- |
| |
| An implementation of this method can handle a request and pass the request onto another handler (or servlet), or it can modify and/or wrap the request before passing it on. |
| This gives three styles of handler: |
| |
| * Coordinating Handlers - Handlers that route requests to other handlers (`HandlerCollection`, `ContextHandlerCollection`) |
| * Filtering Handlers - Handlers that augment a request and pass it on to other handlers (`HandlerWrapper`, `ContextHandler`, `SessionHandler`) |
| * Generating Handlers - Handlers that produce content (`ResourceHandler` and `ServletHandler`) |
| |
| [[target]] |
| ===== The Target |
| |
| The target of a handler is an identifier for the resource that should handle the passed request. |
| This is normally the URI that is parsed from an HTTP Request. |
| However, in two key circumstances the target may differ from the URI of the passed request: |
| |
| * If the request has been dispatched to a named resource, such as a named servlet, the target is the name of that resource. |
| * If the request is being made by a call to link:http://docs.oracle.com/javaee/7/api/javax/servlet/RequestDispatcher.html[`RequestDispatcher`], the target is the URI of the included resource and is different to the URI of the actual request. |
| |
| [[request-and-response]] |
| ===== The Request and Response |
| |
| The request and response objects used in the signature of the handle method are |
| link:http://docs.oracle.com/javaee/7/api/javax/servlet/ServletRequest.html[`ServletRequest`] and link:http://docs.oracle.com/javaee/7/api/javax/servlet/ServletResponse.html[`ServletResponse`]. |
| These are the standard APIs and are moderately restricted in what they can do to the request and response. |
| More often than not, access to the Jetty implementations of these classes is required: link:{JDURL}/org/eclipse/jetty/server/Request.html[`Request`] and link:{JDURL}/org/eclipse/jetty/server/Response.html[`Response`]. |
| However, as the request and response may be wrapped by handlers, filters and servlets, it is not possible to pass the implementation directly. |
| The following mantra retrieves the core implementation objects from under any wrappers: |
| |
| [source, java, subs="{sub-order}"] |
| ---- |
| Request base_request = request instanceof Request ? (Request)request : HttpConnection.getCurrentConnection().getHttpChannel().getRequest(); |
| Response base_response = response instanceof Response ? (Response)response : HttpConnection.getCurrentConnection().getHttpChannel().getResponse(); |
| ---- |
| |
| Notice that if the handler passes the request on to another handler, it should use the Request/Response objects passed in, and not the base objects. |
| This is to preserve any wrapping done by up stream handlers. |
| |
| [[dispatch]] |
| ===== The Dispatch |
| |
| The dispatch argument indicates the state of the handling of the call and may be: |
| |
| * `REQUEST == 1` - An original request received from a connector. |
| * `FORWARD == 2` - A request being forwarded by a RequestDispatcher. |
| * `INCLUDE == 4` - A request being included by a RequestDispatcher. |
| * `ERROR == 8` - A request being forwarded to a error handler by the container. |
| |
| These mostly have significance for servlet and related handlers. |
| For example, the security handler only applies authentication and authorization to REQUEST dispatches. |
| |
| [[handling-requests]] |
| ==== Handling Requests |
| |
| A Handler may handle a request by: |
| |
| * xref:generating-response[] |
| * xref:filtering-request-or-response[] |
| * xref:passing-request-and-response[] |
| |
| [[generating-response]] |
| ===== Generating a Response |
| |
| The link:{JDURL}/org/eclipse/jetty/embedded/OneHandler.html[`OneHandler`] embedded example shows how a simple handler can generate a response. |
| |
| You can use the standard servlet response API, which will typically set some status, content headers and then write out the content: |
| |
| [source, java, subs="{sub-order}"] |
| ---- |
| response.setContentType("text/html"); |
| response.setStatus(HttpServletResponse.SC_OK); |
| response.getWriter().println("<h1>Hello OneHandler</h1>"); |
| ---- |
| |
| It is also very important that a handler indicate that it has completed handling the request and that the request should not be passed to other handlers: |
| |
| [source, java, subs="{sub-order}"] |
| ---- |
| Request base_request = (request instanceof Request) ? (Request)request:HttpConnection.getCurrentConnection().getHttpChannel().getRequest(); |
| base_request.setHandled(true); |
| ---- |
| |
| [[filtering-request-or-response]] |
| ===== Filtering the Request and/or Response |
| |
| Once the base request or response object is obtained, you can modify it. |
| Typically you would make modifications to accomplish: |
| |
| * Breaking the URI into contextPath, servletPath and pathInfo components. |
| * Associating a resource base with a request for static content. |
| * Associating a session with a request. |
| * Associating a security principal with a request. |
| * Changing the URI and paths during a request dispatch forward to another resource. |
| |
| You can also update the context of the request: |
| |
| * Setting the current threads context classloader. |
| * Setting thread locals to identify the current `ServletContext`. |
| |
| Typically Jetty passes a modified request to another handler and undoes modifications in a finally block afterwards: |
| |
| [source, java, subs="{sub-order}"] |
| ---- |
| try |
| { |
| base_request.setSession(a_session); |
| next_handler.handle(target,request,response,dispatch); |
| } |
| finally |
| { |
| base_request.setSession(old_session); |
| } |
| ---- |
| |
| The classes that implement the link:{JDURL}/org/eclipse/jetty/server/handler/HandlerWrapper.html[`HandlerWrapper`] class are typically handler filters of this style. |
| |
| [[passing-request-and-response]] |
| ===== Passing the Request and Response to Another Handler |
| |
| A handler might simply inspect the request and use the target, request URI or other information to select another handler to pass the request to. |
| These handlers typically implement the link:{JDURL}/org/eclipse/jetty/server/HandlerContainer.html[`HandlerContainer`] interface. |
| |
| Examples include: |
| |
| * link:{JDURL}/org/eclipse/jetty/server/handler/HandlerCollection.html[Class `HandlerCollection`] - |
| A collection of handlers, where each handler is called regardless of the state of the request. |
| This is typically used to pass a request to a link:{JDURL}/org/eclipse/jetty/server/handler/ContextHandlerCollection.html[`ContextHandlerCollection`,] and then the link:{JDURL}/org/eclipse/jetty/server/handler/RequestLogHandler.html[`RequestLogHandler`.] |
| * link:{JDURL}/org/eclipse/jetty/server/handler/HandlerList.html[`HandlerList`] - A list of handlers that are called in turn until the request state is set as handled. |
| * link:{JDURL}/org/eclipse/jetty/server/handler/ContextHandlerCollection.html[`ContextHandlerCollection`] - A collection of Handlers, of which one is selected by best match for the context path. |
| |
| [[more-about-handlers]] |
| ==== More About Handlers |
| |
| See the link:{JXURL}/[latest Jetty Source XRef] and the link:{JDURL}/[latest Jetty JavaDoc] for detailed information on each Jetty handler. |