Date: 2005-01-16T01:56:43
Editor: MarkLundquist
Wiki: Cocoon Wiki
Page: SimpleModProxy
URL: http://wiki.apache.org/cocoon/SimpleModProxy
Created.
New Page:
= Intro =
ApacheModProxy is an excellent, in-depth article about why and how to use
Apache HTTPD as a reverse-proxy front-end to Cocoon applications. It's also
rather ''long'', so I'll summarize it here and encourage you to read it if
you're interested in the long version.
So, by way of summary... you want to run Apache in front of your servlet
container. The reasons:
* "Zero port 80 downtime" � the user ''always'' gets some page served, even if
the application is down (rather than having their browser say, "could not
connect");
* Much faster serving of static resources (e.g. images, CSS, client-side
javascript, flash pieces etc.);
* Security ��Apache can start as root, bind to (the privileged) port 80, and
then switch to a non-privileged uid.
There's another compelling reason not discussed in ApacheModProxy, which is the
ability to run multiple servlet engines. I'll discuss that later, but for now,
let's get right to the good stuff!
The ApacheModProxy article gives several examples, starting from a simple
set-up and working its way up to a gnarly, hairy one, just to show how
elaborate it can be. You might be left with the impression that it really
needs to be that involved. Beyond recapitulating the reasons for running
Apache in front of Cocoon, the purpose of this article is to show how simple it
can be.
= A simpler way =
A common feature of the examples in ApacheModProxy is that they all set
Document``Root to the path of the webapp root directory. Then, some measures
are taken to prevent the client from accessing the contents of WEB-INF/ (in
accordance with the servlet spec). But that's really not all we want to do.
We really don't want the sitemap, XML source documents, XSLT stylesheets, etc.
accessible to the client, either. Fortunately, there's a really simple way to
sequester all the static content and set things up so only the static content
is directly visible to Apache.
My standard project layout includes this structure:
{{{
httpd/
static # symlink to... ----
webapp/ |
static/ <----------------------
}}}
...and the Document``Root is set to ''project_root''/httpd, not to the webapp
directory.
''All'' the static content is contained in {{{static}}}. That way,
* Apache can serve it up with one simple rule, instead of a bunch of
Rewrite``Rules matching filename suffixes, etc.;
* Cocoon can still serve up all the static content without Apache, so I can do
development on my laptop where I do not want to have to screw around with
Apache ��I just point my browser at localhost:''port'' and talk directly to the
Cocoon instance (see "Serving Static Content" below).
So, all you might really need in your Apache configuration is
{{{
ProxyPass /static/ !
ProxyPass / http://localhost:8080
ProxyPassReverse / http://localhost:8080
}}}
{{{httpd}}} contains ''nothing'' except for the {{{static}}} symbolic link.
= Multiple instances of Cocoon =
Here's another reason run Apache in front of Cocoon: in production, it's a good
idea to run each web application in a dedicated servlet container (Jetty is
well-suited to this approach). Benefits:
* you can do things that require restarting the servlet container without
affecting any other application
* you can crash the JVM without affecting any other application
* heavy load demands on one application don't (directly) affect applications
running in other servlet container instances (i.e., on separate JVMs).
I use [http://cr.yp.to/daemontools.html daemontools] to start up (at boot time)
and supervise all the Jetty+Cocoon instances (so that if one goes down, it's
automatically restarted), and to log jetty's console output (using
[http://cr.yp.to/daemontools/multilog.html multilog]).
= Serving Static Content =
As I mentioned, I want to be able to do development on my laptop without
Apache, and that means the Cocoon app has to know how to serve static content
by itself. Here's the sitemap snippet that does that:
{{{
<!--
++ Static content
-->
<map:match pattern="static/**.css">
<map:read src="{0}" mime-type="text/css"/>
</map:match>
<map:match pattern="static/**.js">
<map:read src="{0}" mime-type="application/x-javascript"/>
</map:match>
<map:match pattern="static/**.gif">
<map:read src="{0}" mime-type="image/gif"/>
</map:match>
<map:match pattern="static/**.jpg">
<map:read src="{0}" mime-type="image/jpeg"/>
</map:match>
<map:match pattern="static/**.png">
<map:read src="{0}" mime-type="image/png"/>
</map:match>
<map:match pattern="static/**.tiff">
<map:read src="{0}" mime-type="image/tiff"/>
</map:match>
<map:match pattern="static/**.swf">
<map:read src="{0}" mime-type="application/x-shockwave-flash"/>
</map:match>
}}}
See SimpleContentModel for one approach to structuring the {{{static/}}}
directory!
----
Author: MarkLundquist