Spray Transparent Head Requests and Testing
Recently I've been using Spray for API work. While doing so I've written a few posts like JSON and Generic Class Serialization and Logging with Spray, but the other day I ran into a weird bit of a nonsense and ended up raising an issue about it on the spray-can repo.
It may just be my own poor reading comprehension, but I was quite confused
that the feature Transparent Head Request can cause an untestable situation.
As I documented in my example repository that reproduces the error, you can
head directive within your code and it will never actually check out
against the Transparent Head Request behavior.
The issue is that if you have a route which only supports
spray.can.server.transparent-head-requests="on" line in your
application.conf file will result in an error. Why? Because the transparent
head request doesn't enhance the request or handle it like a rejection catcher
of some kind (my initial assumption), but rather replaces the actual
request with a
You can see this in the code here that it's just copying the request into a
GET. This is handy when you have a route that responds to
GET it now also
HEAD. But if you head a route that is only meant for a
request than it will reject any
HEAD request sent to it while you have the
transparent requests on! In order to fix that, you need to set the transparent
requests off, and now if you want to support
HEAD on each of those
routes of yours, you need to code them yourself manually.
The extra labour isn't really my issue, after all, if you're supporting
requests, there's a chance that you probably don't want the same logic to be
applied (for example if you don't want to hit your database on every
so you might be coding your
head directives anyway. The reason why I raised
this as a bug on the spray-can repository was because there is absolutely
no way to test this behavior.
"That's because tests built with the testkit are executed without spray-can and so transparent-head-request handling isn't available. I agree that this is unfortunate as it prevents proper testing of the behavior." -jrudolph
So while you can test your code and
head directives and the tests will tell
you they pass, when you actually run the server and send a
HEAD request to
one of your endpoints to check that it works. BAM Whatever code you're
expecting to run on a
HEAD-only endpoint isn't running. And there's probably
no way you're going to know that.*
Best part is that transparent head requests is
on by default. So if you're not
aware of this by reading the Transparent Head Request documentation, you'll get
hit by this!
*At least not until your DBA asks why all your health checks against database intensive endpoints are triggering the database when you assured him the
HEAD requests wouldn't do that ;)