1pub mod error;
12pub mod handler;
13pub mod middleware;
14#[allow(clippy::needless_for_each)]
15pub mod openapi;
16pub mod router;
17pub mod usage;
18pub(crate) mod util;
19
20pub use byokey_provider::VersionStore;
21pub use error::ApiError;
22pub use openapi::ApiDoc;
23pub use router::make_router;
24pub use usage::{UsageRecorder, UsageStats};
25
26use arc_swap::ArcSwap;
27use byokey_auth::AuthManager;
28use byokey_provider::DeviceProfileCache;
29use byokey_types::{RateLimitStore, UsageStore};
30use std::sync::Arc;
31
32pub struct AppState {
34 pub config: Arc<ArcSwap<byokey_config::Config>>,
37 pub auth: Arc<AuthManager>,
39 pub http: wreq::Client,
41 pub usage: Arc<UsageRecorder>,
43 pub ratelimits: Arc<RateLimitStore>,
45 pub device_profiles: Arc<DeviceProfileCache>,
47 pub versions: VersionStore,
49}
50
51impl AppState {
52 pub fn new(
57 config: Arc<ArcSwap<byokey_config::Config>>,
58 auth: Arc<AuthManager>,
59 usage_store: Option<Arc<dyn UsageStore>>,
60 versions: VersionStore,
61 ) -> Arc<Self> {
62 let snapshot = config.load();
63 let http = build_http_client(snapshot.proxy_url.as_deref());
64 Arc::new(Self {
65 config,
66 auth,
67 http,
68 usage: Arc::new(UsageRecorder::new(usage_store)),
69 ratelimits: Arc::new(RateLimitStore::new()),
70 device_profiles: Arc::new(DeviceProfileCache::new()),
71 versions,
72 })
73 }
74}
75
76fn build_http_client(proxy_url: Option<&str>) -> wreq::Client {
78 if let Some(url) = proxy_url {
79 match wreq::Proxy::all(url) {
80 Ok(proxy) => {
81 return wreq::Client::builder()
82 .proxy(proxy)
83 .build()
84 .unwrap_or_else(|_| wreq::Client::new());
85 }
86 Err(e) => {
87 tracing::warn!(url = url, error = %e, "invalid proxy_url, using direct connection");
88 }
89 }
90 }
91 wreq::Client::new()
92}