Skip to main content
Glama
services.rs6.03 kB
use axum::{ RequestPartsExt as _, async_trait, extract::{ FromRequestParts, Host, OriginalUri, }, http::{ Uri, request::Parts, }, }; use dal::{ ChangeSetId, DalContext, WorkspacePk, }; use derive_more::{ Deref, Into, }; use sdf_core::app_state::AppState; use super::{ ErrorResponse, internal_error, request::RawAccessToken, }; #[derive(Clone, Debug, Deref, Into)] pub struct HandlerContext(pub dal::DalContextBuilder); #[async_trait] impl FromRequestParts<AppState> for HandlerContext { type Rejection = ErrorResponse; async fn from_request_parts( _parts: &mut Parts, state: &AppState, ) -> Result<Self, Self::Rejection> { let builder = state .services_context() .clone() .into_inner() .into_builder(state.for_tests()); Ok(Self(builder)) } } #[derive(Clone, Debug, Deref, Into)] pub struct PosthogClient(pub sdf_core::app_state::PosthogClient); #[async_trait] impl FromRequestParts<AppState> for PosthogClient { type Rejection = ErrorResponse; async fn from_request_parts( _parts: &mut Parts, state: &AppState, ) -> Result<Self, Self::Rejection> { Ok(Self(state.posthog_client().clone())) } } #[derive(Clone, Debug, Deref, Into)] pub struct Nats(pub si_data_nats::NatsClient); #[async_trait] impl FromRequestParts<AppState> for Nats { type Rejection = ErrorResponse; async fn from_request_parts( _parts: &mut Parts, state: &AppState, ) -> Result<Self, Self::Rejection> { let services_context = state.services_context(); Ok(Self(services_context.nats_conn().clone())) } } /// /// Provides a DalContext and a track() method to log the endpoint call. /// /// Always used as part of an Authorization object (cannot be constructed). /// #[derive(Clone)] pub struct PosthogEventTracker { // These last three are so endpoints can do request tracking (they all do it the same way) pub posthog_client: sdf_core::app_state::PosthogClient, pub original_uri: Uri, pub host: String, } impl PosthogEventTracker { pub fn track( &self, ctx: &DalContext, event_name: impl AsRef<str>, properties: serde_json::Value, ) { sdf_core::tracking::track( &self.posthog_client, ctx, &self.original_uri, &self.host, event_name, properties, ) } pub fn track_no_ctx( &self, workspace_id: WorkspacePk, change_set_id: ChangeSetId, event_name: impl AsRef<str>, properties: serde_json::Value, ) { sdf_core::tracking::track_no_ctx( &self.posthog_client, &self.original_uri, &self.host, "anonymous".to_string(), workspace_id, change_set_id, event_name, properties, ) } pub fn track_no_ctx_workspace( &self, workspace_id: WorkspacePk, event_name: impl AsRef<str>, properties: serde_json::Value, ) { sdf_core::tracking::track_no_ctx_workspace( &self.posthog_client, &self.original_uri, &self.host, "anonymous".to_string(), workspace_id, event_name, properties, ) } } #[async_trait] impl FromRequestParts<AppState> for PosthogEventTracker { type Rejection = ErrorResponse; async fn from_request_parts( parts: &mut Parts, state: &AppState, ) -> Result<Self, Self::Rejection> { // Grab a few other things everybody needs (for tracking) let OriginalUri(original_uri) = parts.extract().await.map_err(internal_error)?; let Host(host) = parts.extract().await.map_err(internal_error)?; let PosthogClient(posthog_client) = parts.extract_with_state(state).await?; Ok(Self { posthog_client, original_uri, host, }) } } /// An Auth API client using the same token we got from the request. #[derive(Clone, Debug, Deref, Into)] pub struct AuthApiClient(pub auth_api_client::client::AuthApiClient); #[async_trait] impl FromRequestParts<AppState> for AuthApiClient { type Rejection = ErrorResponse; async fn from_request_parts( parts: &mut Parts, state: &AppState, ) -> Result<Self, Self::Rejection> { let RawAccessToken(raw_access_token) = parts.extract().await?; let client = auth_api_client::client::AuthApiClient::from_raw_token( state.auth_api_url(), raw_access_token, ) .map_err(internal_error)?; Ok(Self(client)) } } #[derive(Clone, Debug, Deref, Into)] pub struct FriggStore(pub frigg::FriggStore); #[async_trait] impl FromRequestParts<AppState> for FriggStore { type Rejection = ErrorResponse; async fn from_request_parts( _parts: &mut Parts, state: &AppState, ) -> Result<Self, Self::Rejection> { Ok(Self(state.frigg().clone())) } } #[derive(Clone, Debug, Deref, Into)] pub struct EddaClient(pub edda_client::EddaClient); #[async_trait] impl FromRequestParts<AppState> for EddaClient { type Rejection = ErrorResponse; async fn from_request_parts( _parts: &mut Parts, state: &AppState, ) -> Result<Self, Self::Rejection> { Ok(Self(state.edda_client().clone())) } } #[derive(Clone, Debug, Deref, Into)] pub struct ComputeExecutor(pub dal::DedicatedExecutor); #[async_trait] impl FromRequestParts<AppState> for ComputeExecutor { type Rejection = ErrorResponse; async fn from_request_parts( _parts: &mut Parts, state: &AppState, ) -> Result<Self, Self::Rejection> { let compute_executor = state.services_context().compute_executor().clone(); Ok(Self(compute_executor)) } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systeminit/si'

If you have feedback or need assistance with the MCP directory API, please join our Discord server