Skip to main content

objectiveai_api/ctx/
default_ctx_ext.rs

1use crate::chat;
2use axum::http::HeaderMap;
3
4/// Default context extension that extracts OpenRouter BYOK from request headers.
5#[derive(Clone)]
6pub struct DefaultContextExt {
7    /// OpenRouter API key from the `authorization_openrouter` header.
8    /// None if the header was not provided.
9    pub openrouter_byok: Option<String>,
10}
11
12impl DefaultContextExt {
13    /// Extracts the OpenRouter BYOK from request headers.
14    ///
15    /// Looks for the `authorization_openrouter` header and strips the "Bearer " prefix
16    /// if present.
17    pub fn from_headers(headers: &HeaderMap) -> Self {
18        let openrouter_byok = headers
19            .get("authorization_openrouter")
20            .and_then(|v| v.to_str().ok())
21            .map(|s| {
22                if let Some(stripped) = s.strip_prefix("Bearer ") {
23                    stripped.to_string()
24                } else {
25                    s.to_string()
26                }
27            });
28
29        Self { openrouter_byok }
30    }
31}
32
33#[async_trait::async_trait]
34impl super::ContextExt for DefaultContextExt {
35    async fn get_byok(
36        &self,
37        upstream: chat::completions::upstream::Upstream,
38    ) -> Result<Option<String>, objectiveai::error::ResponseError> {
39        match upstream {
40            chat::completions::upstream::Upstream::OpenRouter => {
41                Ok(self.openrouter_byok.clone())
42            }
43        }
44    }
45}