To create endpoints that support both authenticated and anonymous requests (e.g., a personalized GET /me), use an enum with a variant marked #[oai(fallback)].
If the security extractor fails, the fallback variant is used. If you require a 401 Unauthorized response for invalid credentials, use a standard SecurityScheme instead of a fallback variant.
use poem::Request;
use poem_openapi::{OpenApi, SecurityScheme};
use poem_openapi::auth::ApiKey;
use poem_openapi::payload::PlainText;
struct User {
username: String,
}
#[derive(SecurityScheme)]
#[oai(
ty = "api_key",
key_name = "session",
key_in = "cookie",
checker = "session_checker"
)]
struct SessionAuthorization(User);
async fn session_checker(_req: &Request, api_key: ApiKey) -> Option<User> {
match api_key.key.as_str() {
"demo-token" => Some(User {
username: "demo".to_string(),
}),
_ => None,
}
}
#[derive(SecurityScheme)]
enum OptionalSessionAuthorization {
Session(SessionAuthorization),
#[oai(fallback)]
Anonymous,
}
struct MyApi;
#[OpenApi]
impl MyApi {
#[oai(path = "/hello", method = "get")]
async fn hello(&self, auth: OptionalSessionAuthorization) -> PlainText<String> {
match auth {
OptionalSessionAuthorization::Session(auth) => {
PlainText(format!("hello, {}", auth.0.username))
}
OptionalSessionAuthorization::Anonymous => {
PlainText("hello, anonymous".to_string())
}
}
}
}