Danube's HTTP server is actually a combination of implementations of Connection and ConnectionHandler . Interface HTTPConnection (extension of Connection ) and its implementation HTTPConnectionImpl represent both HTTP request and response (similarily to java.net.HttpURLConnection).
An object of class HTTPServerConnectionHandler creates HTTPConnections and invokes the processing of headers and parameters. This class handles HTTP/1.1 and HTTP/1.0 requests. It sets a minimal set of required headers.
Selector goes through a supplied list of Matcher s that in turn inspect HTTPConnection (mostly for request URI) and decide whether or not to pass control to the ConnectionHandler they are pointing to.
There are two supplied important implementations of the Matcher interface: Prefix and Pattern .
Prefix checks if the supplied string is a prefix of the current request URI and, if it is, the case then removes it from current request URI in HTTPConnection and passes control to the ConnectionHandler it points to.
Pattern uses regular expressions to match against the current request URI. If it matches it passes control to the ConnectionHandler it points to.
The Matcher
interface
supplies one more pieces of information to the
Selector
class to enable it to
determine whether it should stop on the first match or alternatively continue with the list even if a match is
found. The default value is true
, which prevents the
Selector
going further down the list. Setting that value to false
would
provide filter-like functionality, where
ConnectionHandler
can act as a filter and enable the
Selector
to continue with other matches.
When using Selector with Prefix matchers it is possible for standard J2EE application behaviour to be simulated: Firstly, a Selector (HTTPServerConnectionHandler ) and its Prefix matchers are like applications. Prefix matchers should in this case point to their instances of Selector with Prefix matchers that serve as servlet paths.
For more complex matching, Pattern matchers should be used. However, care must be taken to ensure that changes are not made to the current request URI (which is what a Prefix matcher would do). Also, it is posible for custom (dynamically assigned) Prefix implementations to be introduced for more complex logic involving the matching of incoming URIs.
There is one more, special, case of the Matcher
interface implementation:
WelcomeFile
. This matcher
matches only "/" paths. Also, when matched it adds value of welcomeFile
property
as componentResourcePath
of current connection. If, for instance, linked with
ReadOnlyFileConnectionHandler
it acts as would welcome files in some web servers.
As already mentioned, ConnectionHandler implementations are actually handling the requests. There are only handful of such implementations supplied with this distribution:
Implementing own ConnectionHandler . is simple as there is only one method to be implemented: handleConnection . To obtain HTTPConnection use:
HTTPConnection httpConnection = (HTTPConnection)connection.adapt(HTTPConnection.class);
Apart from these basic implementations there is one important, "integration" implementation of ConnectionHandler : MVCConnectionHandler . It is a very simple implementation. It passes requests (Connection ) to an implementation of the Controller interface that is intended to return a ModelAndView object. Following this an implementation of a View interface is invoked with a Connection and ModelAndView object.
Note: This way of modelling the MVC is inspired by the Spring framework.
The ModelAndView object contains two fields only: the name of the view to be selected by the View implementation and the Map that represents the model. Various view layer technologies (Velocity , Freemarker , etc) have adopted such an approach. Even the JSTL tag library for JSP s can use this as the subset of scopes it caters for.