Search code examples
akkaakka-http

Unable to combine two directives using the | operator on Akka-Http


I want to extract a token either from the query parameter or the Authorization header.

For that, I created this directive:

(parameter("token".optional) | optionalHeaderValueByName("Authorization")).flatMap { _ match {
    case Some(token) =>
      // authenticate it
      complete(...)
    case None =>
      reject(AuthenticationFailedRejection)
  }
}

The issue is that requests with a "token" query parameter work, but requests that have the "Authorization" header (and no query parameter) don't. The optionalHeaderValueByName is skipped.

I believe it is because when parameter("token".optional) is rejected, it automatically returns a 401 Unauthorized response.

If that is indeed the case, is there a way I can make it so it also checks the optionalHeaderValueByName?

I thought that the | operator was made for this.

Maybe it works when returning a route? And not when flatMapping?

This post covers the same use-case: How do I use two Directives with OR in Akka-HTTP?

But for some reason, I can't replicate it.

Thanks.


Solution

  • I believe it is because when parameter("token".optional) is rejected, it automatically returns a 401 Unauthorized response.

    I believe it's the opposite. You made "token" parameter optional, that means when it's absent it still will be accepted and the directive after | never evaluated. If you drop the .optional and token parameter is not there it will be rejected and directive after | will be evaluated.