Customizing mod_dav_svn’s output

It’s one of those things I’m pretty sure I’ve done before and couldn’t put my hands on anymore, so I’ll just leave it here. Hopefully it serves someone else, or myself, at some point.

I was looking for a way to add a “warning” banner, such as the one which is now up at http://svn.magnolia-cms.com/svn.

mod_dav_svn, the Apache mod used to serve Subversion repositories over HTTP, can also be used as a minimal front-end for html-based browsing of repositories. Unfortunately, its output is not very customizable, if at all: all you get is a directive that lets you specify an xslt sheet (yuck) for transforming the output; and if you do decide to go down that route, the transformation happens on the client side.

So I thought about using another Apache mod to modify the content served by mod_dav_svn. At first, I was going to go for a crude User-Agent detection, but realized that, when requested via a browser, the content was sent as text/html, while when requested via a proper SVN client, it was sent as text/xml. Good, then all I needed was provided by mod_ext_filter. All that was left to do was figure out the command I’d want to run with this filter…

Well, in hindsight, next time, I’ll probably go and use Perl or some other scripting language, but I started with sed, and, being anal, I decided to get that working. I knew I had seen a way to output the contents of a file as a replacement for a match. I also knew there was a little trick with that command and the filename it took. Lastly, I vaguely knew about multi-line sed scripts, but had never used nor needed one until now. So all it took was some experimenting, and putting it all together. These two links helped: The Sed FAQ and in particular this page, as well as this Sed Introduction and Tutorial page.

So here’s a sed command that does what I want:
sed -e '/<body>/{
p
r /var/www/svn/migration-banner.inc' \
-e ';d;}'

Each -e provides a (piece of) script for sed. We want to replace <body> in mod_dav_svn’s output: we then proceed and execute 3 sed commands: p prints the pattern space (i.e ‘<body>‘), r /path/to/some/file outputs the given file, and d deletes the pattern space and starts the next cycle. There are two things you shouldn’t really ask me (but you are totally invited to tell me!): what the “pattern space” is (I gather it’s the part of the input we’ve read which matches our regex, … or something), and why we have to split the commands in two bits of script with the -e parameters(it’s explained here and kind of seems to be because that’s the only way to write our whole command in one single line)

So now we can translate that into our Apache configuration:
# First, we define our filter - give it a name, and use intype to make sure we only process text/html documents.
# It seems no environment exists when the filter runs the command, so we need to pass the full path to the sed binary - which makes this a little unportable, but oh well.
ExtFilterDefine svnMigrationBanner mode=output intype=text/html cmd="/bin/sed -e '/<body>/{p;r /var/www/svn/migration-banner.inc' -e 'd;}'"
# Eh, push any error to stderr, that might help. Otherwise the filter is completely silent, even if the command you're trying to execute doesn't exist.
ExtFilterOptions LogStderr DebugLevel=0
# And finally, we enable our filter.
SetOutputFilter svnMigrationBanner
# In fact, I've declared the filter for the complete virtual host, but only enabled it in certain <Location>s.

Voilà !

Oh and one last thing, if you need to do something similar since it might look like I went ahead and configured Apache like this directly: don’t waste your time configuring and reloading Apache all the time. First make sure your complete sed command works from a terminal

One thought on “Customizing mod_dav_svn’s output

  1. Pingback: Customizing mod_dav_svn’s output | CMS Radar

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>