refactor: Higher performance with trait static dispatch

This commit is contained in:
wisdgod
2025-08-03 04:59:15 +08:00
parent e8f03e42f4
commit 4e809ccfb3
21 changed files with 854 additions and 802 deletions

View File

@@ -7,7 +7,7 @@ WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends build-essential protobuf-compiler nodejs npm musl-tools && rm -rf /var/lib/apt/lists/* && case "$TARGETARCH" in amd64) rustup target add x86_64-unknown-linux-musl ;; arm64) rustup target add aarch64-unknown-linux-musl ;; *) echo "Unsupported architecture for rustup: $TARGETARCH" && exit 1 ;; esac
COPY . .
RUN case "$TARGETARCH" in amd64) TARGET_TRIPLE="x86_64-unknown-linux-musl"; TARGET_CPU="x86-64-v3" ;; arm64) TARGET_TRIPLE="aarch64-unknown-linux-musl"; TARGET_CPU="neoverse-n1" ;; *) echo "Unsupported architecture: $TARGETARCH" && exit 1 ;; esac && cargo build --bin cursor-api --release --target=$TARGET_TRIPLE -- -C link-arg=-s -C target-feature=+crt-static -C target-cpu=$TARGET_CPU -A unused && cp target/$TARGET_TRIPLE/release/cursor-api /app/cursor-api
RUN case "$TARGETARCH" in amd64) TARGET_TRIPLE="x86_64-unknown-linux-musl"; TARGET_CPU="x86-64-v3" ;; arm64) TARGET_TRIPLE="aarch64-unknown-linux-musl"; TARGET_CPU="neoverse-n1" ;; *) echo "Unsupported architecture: $TARGETARCH" && exit 1 ;; esac && RUSTFLAGS="-C link-arg=-s -C target-feature=+crt-static -C target-cpu=$TARGET_CPU -A unused" cargo build --bin cursor-api --release --target=$TARGET_TRIPLE && cp target/$TARGET_TRIPLE/release/cursor-api /app/cursor-api
# 运行阶段
FROM scratch

View File

@@ -229,7 +229,7 @@ pub fn init_thinking_tags() {
return;
}
let tag = crate::common::utils::parse_string_from_env("THINKING_TAG", DEFAULT_THINKING_TAG);
let tag = crate::common::utils::parse_from_env("THINKING_TAG", DEFAULT_THINKING_TAG);
if tag == DEFAULT_THINKING_TAG {
return;

View File

@@ -102,7 +102,7 @@ pub fn header_value_ua_cursor_latest() -> http::header::HeaderValue {
pub fn initialize_cursor_version() {
use ::core::ops::Deref as _;
let version = crate::common::utils::parse_string_from_env(
let version = crate::common::utils::parse_from_env(
ENV_CURSOR_CLIENT_VERSION,
DEFAULT_CLIENT_VERSION,
);

View File

@@ -1,5 +1,11 @@
pub mod log;
use ::std::{
borrow::Cow,
path::PathBuf,
sync::{LazyLock, OnceLock},
};
use super::{
constant::{
CURSOR_API2_HOST, CURSOR_API4_HOST, CURSOR_GCPP_ASIA_HOST, CURSOR_GCPP_EU_HOST,
@@ -7,12 +13,7 @@ use super::{
},
model::{DateTime, GcppHost},
};
use crate::common::utils::{parse_bool_from_env, parse_string_from_env, parse_usize_from_env};
use std::{
borrow::Cow,
path::PathBuf,
sync::{LazyLock, OnceLock},
};
use crate::common::utils::parse_from_env;
macro_rules! def_pub_static {
// 基础版本:直接存储 String
@@ -23,7 +24,7 @@ macro_rules! def_pub_static {
// 环境变量版本
($name:ident,env: $env_key:expr,default: $default:expr) => {
pub static $name: LazyLock<Cow<'static, str>> =
LazyLock::new(|| parse_string_from_env($env_key, $default));
LazyLock::new(|| parse_from_env($env_key, $default));
};
}
@@ -38,7 +39,7 @@ pub fn get_start_time() -> &'static chrono::NaiveDateTime {
pub static GENERAL_TIMEZONE: LazyLock<chrono_tz::Tz> = LazyLock::new(|| {
use std::str::FromStr as _;
let tz = parse_string_from_env("GENERAL_TIMEZONE", EMPTY_STRING);
let tz = parse_from_env("GENERAL_TIMEZONE", EMPTY_STRING);
if tz.is_empty() {
__eprintln!(
"未配置时区请在环境变量GENERAL_TIMEZONE中设置格式如'Asia/Shanghai'\n将使用默认时区: Asia/Shanghai"
@@ -64,7 +65,7 @@ pub fn get_default_instructions(now_with_tz: chrono::DateTime<chrono_tz::Tz>) ->
}
pub static GENERAL_GCPP_HOST: LazyLock<GcppHost> = LazyLock::new(|| {
let gcpp_host = parse_string_from_env("GENERAL_GCPP_HOST", EMPTY_STRING);
let gcpp_host = parse_from_env("GENERAL_GCPP_HOST", EMPTY_STRING);
let gcpp_host = gcpp_host.trim();
if gcpp_host.is_empty() {
__eprintln!(
@@ -276,7 +277,7 @@ def_cursor_api_url!(
);
static DATA_DIR: LazyLock<PathBuf> = LazyLock::new(|| {
let data_dir = parse_string_from_env("DATA_DIR", "data");
let data_dir = parse_from_env("DATA_DIR", "data");
let path = std::env::current_exe()
.ok()
.and_then(|exe_path| exe_path.parent().map(|p| p.to_path_buf()))
@@ -306,7 +307,7 @@ const DEFAULT_TCP_KEEPALIVE: usize = 90;
const MAX_TCP_KEEPALIVE: u64 = 600;
pub static TCP_KEEPALIVE: LazyLock<u64> = LazyLock::new(|| {
let keepalive = parse_usize_from_env("TCP_KEEPALIVE", DEFAULT_TCP_KEEPALIVE);
let keepalive = parse_from_env("TCP_KEEPALIVE", DEFAULT_TCP_KEEPALIVE);
u64::try_from(keepalive)
.map(|t| t.min(MAX_TCP_KEEPALIVE))
.unwrap_or(DEFAULT_TCP_KEEPALIVE as u64)
@@ -316,13 +317,13 @@ const DEFAULT_SERVICE_TIMEOUT: usize = 30;
const MAX_SERVICE_TIMEOUT: u64 = 600;
pub static SERVICE_TIMEOUT: LazyLock<u64> = LazyLock::new(|| {
let timeout = parse_usize_from_env("SERVICE_TIMEOUT", DEFAULT_SERVICE_TIMEOUT);
let timeout = parse_from_env("SERVICE_TIMEOUT", DEFAULT_SERVICE_TIMEOUT);
u64::try_from(timeout)
.map(|t| t.min(MAX_SERVICE_TIMEOUT))
.unwrap_or(DEFAULT_SERVICE_TIMEOUT as u64)
});
pub static REAL_USAGE: LazyLock<bool> = LazyLock::new(|| parse_bool_from_env("REAL_USAGE", true));
pub static REAL_USAGE: LazyLock<bool> = LazyLock::new(|| parse_from_env("REAL_USAGE", true));
// pub static TOKEN_VALIDITY_RANGE: LazyLock<TokenValidityRange> = LazyLock::new(|| {
// let short = if let Ok(Ok(validity)) = std::env::var("TOKEN_SHORT_VALIDITY")

View File

@@ -1,10 +1,6 @@
use std::{
borrow::Cow,
sync::{Arc, atomic::AtomicU64},
time::Duration,
};
use tokio::{
use ::core::{sync::atomic::AtomicU64, time::Duration};
use ::std::{borrow::Cow, sync::Arc};
use ::tokio::{
fs::File,
io::AsyncWriteExt as _,
sync::{
@@ -15,10 +11,7 @@ use tokio::{
task::JoinHandle,
};
use crate::{
common::utils::{parse_bool_from_env, parse_string_from_env},
leak::manually_init::ManuallyInit,
};
use crate::{common::utils::parse_from_env, leak::manually_init::ManuallyInit};
// --- 全局配置 ---
@@ -30,8 +23,8 @@ static DEBUG_LOG_FILE: ManuallyInit<Cow<'static, str>> = ManuallyInit::new();
#[forbid(unused)]
pub fn init() {
unsafe {
DEBUG.init(parse_bool_from_env("DEBUG", true));
DEBUG_LOG_FILE.init(parse_string_from_env("DEBUG_LOG_FILE", "debug.log"));
DEBUG.init(parse_from_env("DEBUG", true));
DEBUG_LOG_FILE.init(parse_from_env("DEBUG_LOG_FILE", "debug.log"));
}
}

View File

@@ -13,7 +13,7 @@ use crate::{
lazy::CONFIG_FILE_PATH,
model::FetchMode,
},
common::utils::{parse_bool_from_env, parse_string_from_env},
common::utils::parse_from_env,
leak::manually_init::ManuallyInit,
};
@@ -123,16 +123,15 @@ impl AppConfig {
let mut config = APP_CONFIG.write();
config.vision_ability =
VisionAbility::from_str(&parse_string_from_env("VISION_ABILITY", EMPTY_STRING));
config.slow_pool = parse_bool_from_env("ENABLE_SLOW_POOL", false);
config.long_context = parse_bool_from_env("ENABLE_LONG_CONTEXT", false);
config.usage_check =
UsageCheck::from_str(&parse_string_from_env("USAGE_CHECK", EMPTY_STRING));
config.dynamic_key = parse_bool_from_env("DYNAMIC_KEY", false);
config.share_token = parse_string_from_env("SHARED_TOKEN", EMPTY_STRING).into_owned();
config.web_refs = parse_bool_from_env("INCLUDE_WEB_REFERENCES", false);
VisionAbility::from_str(&parse_from_env("VISION_ABILITY", EMPTY_STRING));
config.slow_pool = parse_from_env("ENABLE_SLOW_POOL", false);
config.long_context = parse_from_env("ENABLE_LONG_CONTEXT", false);
config.usage_check = UsageCheck::from_str(&parse_from_env("USAGE_CHECK", EMPTY_STRING));
config.dynamic_key = parse_from_env("DYNAMIC_KEY", false);
config.share_token = parse_from_env("SHARED_TOKEN", EMPTY_STRING).into_owned();
config.web_refs = parse_from_env("INCLUDE_WEB_REFERENCES", false);
config.fetch_models =
FetchMode::from_str(&parse_string_from_env("FETCH_RAW_MODELS", EMPTY_STRING));
FetchMode::from_str(&parse_from_env("FETCH_RAW_MODELS", EMPTY_STRING));
}
config_methods! {

View File

@@ -1,16 +1,16 @@
use rand::{
use ::core::{fmt, str::FromStr};
use ::rand::{
RngCore as _,
distr::{Distribution, StandardUniform},
};
use sha2::Digest as _;
use std::{fmt, str::FromStr};
use ::sha2::Digest as _;
use crate::common::utils::hex::HEX_CHARS;
static mut SAFE_HASH: bool = false;
pub(super) fn init_hash() {
unsafe { SAFE_HASH = crate::common::utils::parse_bool_from_env("SAFE_HASH", true) }
unsafe { SAFE_HASH = crate::common::utils::parse_from_env("SAFE_HASH", true) }
}
#[derive(Debug)]

View File

@@ -79,7 +79,7 @@ impl LogManager {
/// 从存储中加载日志
#[inline(never)]
pub async fn load() -> Result<Self, Box<dyn std::error::Error>> {
let logs_limit = RequestLogsLimit::from_usize(crate::common::utils::parse_usize_from_env(
let logs_limit = RequestLogsLimit::from_usize(crate::common::utils::parse_from_env(
"REQUEST_LOGS_LIMIT",
100,
));

View File

@@ -1,11 +1,11 @@
use crate::{common::utils::parse_string_from_env, leak::manually_init::ManuallyInit};
use crate::{common::utils::parse_from_env, leak::manually_init::ManuallyInit};
pub static TZ: ManuallyInit<chrono_tz::Tz> = ManuallyInit::new();
#[inline(always)]
pub fn __init() {
use std::str::FromStr as _;
let tz = match chrono_tz::Tz::from_str(&parse_string_from_env("TZ", super::EMPTY_STRING)) {
let tz = match chrono_tz::Tz::from_str(&parse_from_env("TZ", super::EMPTY_STRING)) {
Ok(tz) => tz,
Err(_e) => chrono_tz::Tz::UTC,
};

View File

@@ -28,7 +28,7 @@ use reqwest::{
},
};
trait RequestBuilderExt {
trait RequestBuilderExt: Sized {
fn opt_header<K, V>(self, key: K, value: Option<V>) -> Self
where
http::HeaderName: TryFrom<K>,

4
src/common/impls.rs Normal file
View File

@@ -0,0 +1,4 @@
// pub trait ToBufStr: Copy {
// const BUF_SIZE: usize;
// fn to_str<'buf>(&self, buf: &'buf mut [u8; Self::BUF_SIZE]) -> &'buf mut str;
// }

File diff suppressed because it is too large Load Diff

View File

@@ -12,7 +12,7 @@ use ::std::borrow::Cow;
mod private {
use std::borrow::Cow;
pub trait Sealed {}
pub trait Sealed: Sized {}
impl Sealed for &str {}
impl Sealed for String {}
@@ -22,9 +22,9 @@ mod private {
/// A trait representing types that can be appended to a `StringBuilder`.
/// This is a sealed trait and cannot be implemented for types outside this crate.
pub trait StringPart<'a>: private::Sealed + Into<Cow<'a, str>> + Debug + Clone {}
pub trait StringPart<'a>: private::Sealed + Into<Cow<'a, str>> {}
impl<'a, T> StringPart<'a> for T where T: private::Sealed + Into<Cow<'a, str>> + Debug + Clone {}
impl<'a, T> StringPart<'a> for T where T: private::Sealed + Into<Cow<'a, str>> {}
/// Internal storage state for StringBuilder
///

View File

@@ -128,11 +128,11 @@ fn extract_web_references_info(text: &str) -> (String, Vec<WebReference>, bool)
}
}
const trait ToOpt: Copy {
trait ToOpt: Copy {
fn to_opt(self) -> Option<Self>;
}
impl const ToOpt for bool {
impl ToOpt for bool {
#[inline(always)]
fn to_opt(self) -> Option<Self> { if self { Some(true) } else { None } }
}

View File

@@ -9,7 +9,7 @@ static mut BYPASS_MODEL_VALIDATION: bool = false;
pub fn init_resolver() {
unsafe {
BYPASS_MODEL_VALIDATION =
crate::common::utils::parse_bool_from_env("BYPASS_MODEL_VALIDATION", false)
crate::common::utils::parse_from_env("BYPASS_MODEL_VALIDATION", false)
}
}

View File

@@ -18,7 +18,7 @@ use std::{
time::Instant,
};
pub trait InstantExt {
pub trait InstantExt: Sized {
fn duration_as_secs_f32(&mut self) -> f32;
}

View File

@@ -1,7 +1,8 @@
use ::bytes::{Buf as _, BytesMut};
use ::prost::Message as _;
use super::decompress_gzip;
use crate::core::{aiserver::v1::StreamCppResponse, error::StreamError};
use bytes::{Buf as _, BytesMut};
use prost::Message as _;
#[derive(::serde::Serialize, PartialEq, Clone)]
#[serde(tag = "type", rename_all = "snake_case")]

View File

@@ -1,6 +1,6 @@
// use bytes::{Buf as _, BytesMut};
// use ::bytes::{Buf as _, BytesMut};
use std::borrow::Cow;
use ::std::borrow::Cow;
use super::{
decompress_gzip,
@@ -45,7 +45,7 @@ use super::{
// if let Ok(msg) = T::decode(&self.buf[..]) {
// return Ok(Some(DecodedMessage::Protobuf(msg)));
// } else if let Some(text) = String::from_utf8(self.buf.to_vec()) {
// } else if let Ok(text) = String::from_utf8(self.buf.to_vec()) {
// return Ok(Some(DecodedMessage::Text(text)));
// }
// }
@@ -92,7 +92,7 @@ pub fn decode<T: ProtobufMessage>(data: &[u8]) -> Result<DecodedMessage<T>, Deco
if let Ok(msg) = T::decode(&*decompressed) {
return Ok(DecodedMessage::Protobuf(msg));
} else if let Some(text) = super::utils::string_from_utf8_cow(decompressed) {
} else if let Some(text) = super::utils::string_from_utf8(decompressed) {
return Ok(DecodedMessage::Text(text));
}
}

View File

@@ -1,4 +1,4 @@
use prost::Message;
use ::prost::Message;
/// 表示可以被Protobuf编解码并可创建默认实例的消息类型
pub trait ProtobufMessage: Message + Default {}
@@ -32,6 +32,7 @@ pub enum DecodedMessage<T: ProtobufMessage> {
}
// impl<T: ProtobufMessage> DecodedMessage<T> {
// #[inline]
// pub fn encode(&self) -> Vec<u8>
// where
// Self: Sized,
@@ -43,8 +44,8 @@ pub enum DecodedMessage<T: ProtobufMessage> {
// }
// }
// impl<T: ProtobufMessage> std::fmt::Debug for DecodedMessage<T> {
// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// impl<T: ProtobufMessage> ::core::fmt::Debug for DecodedMessage<T> {
// fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
// match self {
// Self::Protobuf(msg) => write!(f, "\n{msg:#?}"),
// Self::Text(s) => write!(f, "\n{s:?}"),
@@ -52,8 +53,8 @@ pub enum DecodedMessage<T: ProtobufMessage> {
// }
// }
// impl<T: ProtobufMessage + serde::Serialize> std::fmt::Display for DecodedMessage<T> {
// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// impl<T: ProtobufMessage + ::serde::Serialize> ::core::fmt::Display for DecodedMessage<T> {
// fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
// match self {
// Self::Protobuf(msg) => write!(f, "\n{}", serde_json::to_string(msg).unwrap()),
// Self::Text(s) => write!(f, "\n{s}"),

View File

@@ -1,17 +1,36 @@
use std::borrow::Cow;
#[allow(private_bounds)]
#[inline]
pub fn string_from_utf8(v: &[u8]) -> Option<String> {
match ::core::str::from_utf8(v) {
Ok(_) => Some(unsafe { String::from_utf8_unchecked(v.to_vec()) }),
pub fn string_from_utf8<V: StringFrom>(v: V) -> Option<String> {
match ::core::str::from_utf8(v.as_bytes()) {
Ok(_) => Some(unsafe { String::from_utf8_unchecked(v.into_vec()) }),
Err(_) => None,
}
}
#[inline]
pub fn string_from_utf8_cow(v: Cow<'_, [u8]>) -> Option<String> {
match ::core::str::from_utf8(&v) {
Ok(_) => Some(unsafe { String::from_utf8_unchecked(v.into_owned()) }),
Err(_) => None,
}
trait StringFrom: Sized {
fn as_bytes(&self) -> &[u8];
fn into_vec(self) -> Vec<u8>;
}
impl StringFrom for &[u8] {
#[inline(always)]
fn as_bytes(&self) -> &[u8] { *self }
#[inline(always)]
fn into_vec(self) -> Vec<u8> { self.to_vec() }
}
impl StringFrom for Cow<'_, [u8]> {
#[inline(always)]
fn as_bytes(&self) -> &[u8] { self }
#[inline(always)]
fn into_vec(self) -> Vec<u8> { self.into_owned() }
}
// mod private {
// pub trait Sealed: Sized {}
// impl Sealed for &[u8] {}
// impl Sealed for super::Cow<'_, [u8]> {}
// }

View File

@@ -5,7 +5,8 @@
hasher_prefixfree_extras,
const_trait_impl,
const_default,
core_intrinsics
core_intrinsics,
associated_type_defaults
)]
#![allow(clippy::redundant_static_lifetimes)]
@@ -18,6 +19,34 @@ mod core;
mod leak;
mod natural_args;
use ::axum::{
Router, middleware,
routing::{get, post},
};
use ::tokio::signal;
use ::tower_http::{cors::CorsLayer, limit::RequestBodyLimitLayer};
use app::{
config::handle_config_update,
constant::{
EMPTY_STRING, EXE_NAME, ROUTE_ABOUT_PATH, ROUTE_API_PATH, ROUTE_BUILD_KEY_PATH,
ROUTE_CONFIG_PATH, ROUTE_CONFIG_VERSION_GET_PATH, ROUTE_CPP_CONFIG_PATH,
ROUTE_CPP_MODELS_PATH, ROUTE_CPP_STREAM_PATH, ROUTE_ENV_EXAMPLE_PATH, ROUTE_FILE_SYNC_PATH,
ROUTE_FILE_UPLOAD_PATH, ROUTE_GEN_CHECKSUM, ROUTE_GEN_HASH, ROUTE_GEN_TOKEN,
ROUTE_GEN_UUID, ROUTE_GET_TIMESTAMP_HEADER, ROUTE_HEALTH_PATH, ROUTE_LOGS_GET_PATH,
ROUTE_LOGS_PATH, ROUTE_LOGS_TOKENS_GET_PATH, ROUTE_PROXIES_ADD_PATH,
ROUTE_PROXIES_DELETE_PATH, ROUTE_PROXIES_GET_PATH, ROUTE_PROXIES_PATH,
ROUTE_PROXIES_SET_GENERAL_PATH, ROUTE_PROXIES_SET_PATH, ROUTE_README_PATH, ROUTE_ROOT_PATH,
ROUTE_STATIC_PATH, ROUTE_TOKENS_ADD_PATH, ROUTE_TOKENS_ALIAS_SET_PATH,
ROUTE_TOKENS_CONFIG_VERSION_UPDATE_PATH, ROUTE_TOKENS_DELETE_PATH, ROUTE_TOKENS_GET_PATH,
ROUTE_TOKENS_PATH, ROUTE_TOKENS_PROFILE_UPDATE_PATH, ROUTE_TOKENS_PROXY_SET_PATH,
ROUTE_TOKENS_REFRESH_PATH, ROUTE_TOKENS_SET_PATH, ROUTE_TOKENS_STATUS_SET_PATH,
ROUTE_TOKENS_TIMEZONE_SET_PATH, VERSION,
},
lazy::AUTH_TOKEN,
model::{AppConfig, AppState},
};
use common::utils::parse_from_env;
use core::{
middleware::{admin_auth_middleware, cpp_auth_middleware, v1_auth_middleware},
route::{
@@ -40,34 +69,7 @@ use core::{
handle_chat_completions, handle_messages, handle_models, handle_raw_models,
},
};
use app::{
config::handle_config_update,
constant::{
EMPTY_STRING, EXE_NAME, ROUTE_ABOUT_PATH, ROUTE_API_PATH, ROUTE_BUILD_KEY_PATH,
ROUTE_CONFIG_PATH, ROUTE_CONFIG_VERSION_GET_PATH, ROUTE_CPP_CONFIG_PATH,
ROUTE_CPP_MODELS_PATH, ROUTE_CPP_STREAM_PATH, ROUTE_ENV_EXAMPLE_PATH, ROUTE_FILE_SYNC_PATH,
ROUTE_FILE_UPLOAD_PATH, ROUTE_GEN_CHECKSUM, ROUTE_GEN_HASH, ROUTE_GEN_TOKEN,
ROUTE_GEN_UUID, ROUTE_GET_TIMESTAMP_HEADER, ROUTE_HEALTH_PATH, ROUTE_LOGS_GET_PATH,
ROUTE_LOGS_PATH, ROUTE_LOGS_TOKENS_GET_PATH, ROUTE_PROXIES_ADD_PATH,
ROUTE_PROXIES_DELETE_PATH, ROUTE_PROXIES_GET_PATH, ROUTE_PROXIES_PATH,
ROUTE_PROXIES_SET_GENERAL_PATH, ROUTE_PROXIES_SET_PATH, ROUTE_README_PATH, ROUTE_ROOT_PATH,
ROUTE_STATIC_PATH, ROUTE_TOKENS_ADD_PATH, ROUTE_TOKENS_ALIAS_SET_PATH,
ROUTE_TOKENS_CONFIG_VERSION_UPDATE_PATH, ROUTE_TOKENS_DELETE_PATH, ROUTE_TOKENS_GET_PATH,
ROUTE_TOKENS_PATH, ROUTE_TOKENS_PROFILE_UPDATE_PATH, ROUTE_TOKENS_PROXY_SET_PATH,
ROUTE_TOKENS_REFRESH_PATH, ROUTE_TOKENS_SET_PATH, ROUTE_TOKENS_STATUS_SET_PATH,
ROUTE_TOKENS_TIMEZONE_SET_PATH, VERSION,
},
lazy::AUTH_TOKEN,
model::{AppConfig, AppState},
};
use axum::{
Router, middleware,
routing::{get, post},
};
use common::utils::{parse_string_from_env, parse_usize_from_env};
use natural_args::{DEFAULT_LISTEN_HOST, ENV_HOST, ENV_PORT};
use tokio::signal;
use tower_http::{cors::CorsLayer, limit::RequestBodyLimitLayer};
#[tokio::main]
async fn main() {
@@ -219,7 +221,6 @@ async fn main() {
route_chat_completions_path,
route_messages_path,
) = {
let route_prefix = parse_string_from_env("ROUTE_PREFIX", EMPTY_STRING);
define_typed_constants! {
&'static str => {
RAW_MODELS_PATH = "/raw/models",
@@ -228,9 +229,9 @@ async fn main() {
MESSAGES_PATH = "/v1/messages",
}
}
use ::std::borrow::Cow;
use std::borrow::Cow;
let route_prefix = parse_from_env("ROUTE_PREFIX", EMPTY_STRING);
if route_prefix.is_empty() {
(
Cow::Borrowed(RAW_MODELS_PATH),
@@ -361,7 +362,7 @@ async fn main() {
post(handle_get_config_version),
)
// .route(ROUTE_TOKEN_UPGRADE_PATH, post(handle_token_upgrade))
.layer(RequestBodyLimitLayer::new(parse_usize_from_env(
.layer(RequestBodyLimitLayer::new(parse_from_env(
"REQUEST_BODY_LIMIT",
2_000_000,
)))
@@ -379,7 +380,7 @@ async fn main() {
.unwrap_or(3000)
};
let addr = SocketAddr::new(
IpAddr::parse_ascii(parse_string_from_env(ENV_HOST, DEFAULT_LISTEN_HOST).as_bytes())
IpAddr::parse_ascii(parse_from_env(ENV_HOST, DEFAULT_LISTEN_HOST).as_bytes())
.unwrap_or_else(|e| {
__cold_path!(); // IP解析失败是错误路径
eprintln!("无法解析IP: {e}");