Using Caddy in front of iocaine

Getting started

In here, we’ll assume that iocaine has already been set up, and is accepting HTTP connections on port 42069 of 127.0.0.1. See the Getting Started guides to get there quickly!

Lets also assume that we have a site running at [::1]:8080, and we want to serve that with Caddy. Normally, that would look something like this:

blog.example.com {
  reverse_proxy [::1]:8080
}

Or perhaps even:

blog.example.com {
  root * /srv/www/blog.example.com
  file_server
}

Integrating iocaine

iocaine expects us to pipe everything through it, and it will send back a result: either a HTTP 421 Misdirected Request response to signal that we should serve real contents, or any other status, which we should serve as is.

As such, we’ll have to wrap the above example to match this expectation:

blog.example.com {
  @read method GET HEAD
  reverse_proxy @read 127.0.0.1:42069 {
    @fallback status 421
    handle_response @fallback
  }
  reverse_proxy [::1]:8080
}

The handle_response directive is essentially a fallthrough, so we can conveniently place the iocaine filter before any handlers that respond, and we’re good to go. If serving files directly, we’ll have to adjust this wrapping accordingly:

blog.example.com {
  @read method GET HEAD
  reverse_proxy @read 127.0.0.1:42069 {
    @fallback status 421
    handle_response @fallback
  }
  root * /srv/www/blog.example.com
  file_server
}

As you can see, we’re only proxying GET and HEAD requests to iocaine - most unwanted bots don’t send a body anyway, nor requests other than GET and HEAD, so for now, this will do.

A reusable snippet

Chances are, there’s more than one site we wish to protect with iocaine. Repeating the above boilerplate over and over again would be both mindnumbingly boring, entirely pointless, and also completely unnecessary, because Caddy lets us set up reusable snippets. Like this:

(iocaine) {
  @read method GET HEAD
  reverse_proxy @read 127.0.0.1:42069 {
    @fallback status 421
    handle_response @fallback
  }
}

Rewriting the blog.example.com site’s declaration to use this makes it look like so:

blog.example.com {
  import iocaine
  reverse_proxy [::1]:8000
}

Similarly, for a static blog:

blog.example.com {
  import iocaine
  root * /srv/www/blog.example.com
  file_server
}

The only thing you need to pay attention to is directive ordering: some directives, such as respond are ordered before reverse_proxy by default. If you use those directives, they will not go through iocaine, unless you reorder them:

{
  order respond after reverse_proxy
}