headerValue and related directives reject with an empty rejection list when the header can't be found. I'd like to add an explicit MissingHeaderRejection if the header isn't there.
(In my example I'm using the clientIP directive, which is a headerValuePF checking three related headers, but it's the same idea.)
I came up with this:
val clientIPAddr = mapRejections(r => if (r.isEmpty) List(MissingHeaderRejection(`X-Forwarded-For`.name)) else r) & clientIP.map {
_.toOption.map(_.getHostAddress).getOrElse("unknown")
}
This works, but is not perfect. If I understand it correctly, the "mapRejections" directive will apply to the entire inner route, so even if the clientIP matches, if something nested down below it in the routing tree also rejects with an empty list, then this will spuriously add the MissingHeaderRejection.
e.g:
clientIPAddr { ip =>
reject // MissingHeaderRejection(`X-Forwarded-For`.name) will be added if we get here. do not want.
}
It seems like this should be pretty trivial to do, but I can't figure it out. None of the following will work (they don't compile):
val clientIPAddr = clientIP.map {
_.toOption.map(_.getHostAddress).getOrElse("unknown")
}.recover { _ => reject(MissingHeaderRejection(`X-Forwarded-For`.name))}
val clientIPAddr = clientIP.map {
_.toOption.map(_.getHostAddress).getOrElse("unknown")
} | reject(MissingHeaderRejection(`X-Forwarded-For`.name))