自定义Directive调用extractCredentials报错:UserContext无map方法
Fixing the Compilation Error in Your Akka HTTP Authenticated Directive
Let's break down why your code is failing and fix it step by step:
The Root Cause
In Akka HTTP's Directive for-comprehensions, every step must return a Directive type—but your match expression is returning raw values (UserContext or None) instead of wrapping them in a Directive. The compiler complains about map not being a member of UserContext because it expects a Directive (which has a map method) after the <- arrow, not a plain object.
Corrected Code
Here's how to adjust your directive to properly adhere to Akka HTTP's Directive rules:
import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.AuthenticationFailedRejection import akka.http.scaladsl.server.directives.Credentials case class UserContext(username: String) def authenticated: Directive1[Option[UserContext]] = for { credentials <- extractCredentials userContext <- credentials match { // Wrap valid UserContext in a Directive using `provide` case Some(Credentials.Bearer(token)) => // Replace with your actual authentication logic to resolve username from token provide(Some(UserContext(token))) // For invalid/missing credentials, return a rejection Directive case _ => reject(AuthenticationFailedRejection(AuthenticationFailedRejection.CredentialsMissing, None)) } } yield userContext
Key Fixes Explained
- Wrap values in Directives: Use
provide(Some(UserContext(...)))to convert your authenticated user context into aDirective1[Option[UserContext]]—this makes it compatible with the for-comprehension. - Proper rejection handling: Instead of returning
None, usereject(...)to send an authentication failure rejection back to the client. This is the standard way to handle unauthenticated requests in Akka HTTP. - Cleaner pattern matching: Use
Credentials.Bearer(token)directly instead of manually checking the scheme, which makes the code more readable and idiomatic.
Usage Example
Now you can use your directive as intended, with access to the UserContext (if authenticated):
val routes = authenticated { uc => post { uc match { case Some(user) => complete(s"Authenticated request for user: ${user.username}") case None => complete("No user context found (this branch won't trigger due to rejection logic)") } } }
内容的提问来源于stack exchange,提问作者Blankman
相关产品推荐
相关产品推荐

