mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-29 06:33:28 +00:00
build(rust): upgrade reqwest to 0.13 and move MCP out of litellm-http
The workspace moves to reqwest 0.13, so litellm-http no longer carries a second reqwest just for rmcp. The mcp feature, its pool and its proxy conversion go away, and the gateway hands rmcp a pooled NoRedirect client that already carries the TLS, proxy and timeout settings The Client test helpers collapse into for_test, a no-redirect client without TLS or proxy settings, and wrap_for_test for the few tests that need a hand-built reqwest client Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
bc18e10f6b
commit
91d4db7d44
49 changed files with 151 additions and 371 deletions
108
litellm-rust/Cargo.lock
generated
108
litellm-rust/Cargo.lock
generated
|
|
@ -2329,7 +2329,7 @@ dependencies = [
|
|||
"hmac 0.13.0",
|
||||
"http 1.4.2",
|
||||
"jiff",
|
||||
"reqwest 0.13.5",
|
||||
"reqwest",
|
||||
"rustc_version",
|
||||
"rustls 0.23.42",
|
||||
"rustls-pki-types",
|
||||
|
|
@ -2387,7 +2387,7 @@ dependencies = [
|
|||
"pin-project",
|
||||
"prost",
|
||||
"prost-types",
|
||||
"reqwest 0.13.5",
|
||||
"reqwest",
|
||||
"rustc_version",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
@ -2883,7 +2883,6 @@ dependencies = [
|
|||
"tokio",
|
||||
"tokio-rustls 0.26.4",
|
||||
"tower-service",
|
||||
"webpki-roots",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3376,7 +3375,7 @@ dependencies = [
|
|||
"litellm-auth-types",
|
||||
"litellm-http",
|
||||
"moka",
|
||||
"reqwest 0.12.28",
|
||||
"reqwest",
|
||||
"rstest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
@ -3460,7 +3459,7 @@ dependencies = [
|
|||
"litellm-cache-response",
|
||||
"litellm-cache-testing",
|
||||
"litellm-http",
|
||||
"reqwest 0.12.28",
|
||||
"reqwest",
|
||||
"rstest",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
|
|
@ -3495,7 +3494,7 @@ dependencies = [
|
|||
"litellm-cache-testing",
|
||||
"litellm-http",
|
||||
"percent-encoding",
|
||||
"reqwest 0.12.28",
|
||||
"reqwest",
|
||||
"rstest",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
|
|
@ -3522,7 +3521,7 @@ dependencies = [
|
|||
"litellm-cache-testing",
|
||||
"litellm-http",
|
||||
"qdrant-client",
|
||||
"reqwest 0.12.28",
|
||||
"reqwest",
|
||||
"rstest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
@ -3598,7 +3597,7 @@ dependencies = [
|
|||
"litellm-cache",
|
||||
"litellm-cache-testing",
|
||||
"litellm-http",
|
||||
"reqwest 0.12.28",
|
||||
"reqwest",
|
||||
"rstest",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
|
|
@ -3945,9 +3944,7 @@ dependencies = [
|
|||
"hyper-util",
|
||||
"litellm-core-utils",
|
||||
"rcgen",
|
||||
"reqwest 0.12.28",
|
||||
"reqwest 0.13.5",
|
||||
"rmcp",
|
||||
"reqwest",
|
||||
"rstest",
|
||||
"rustls 0.23.42",
|
||||
"rustls-native-certs",
|
||||
|
|
@ -3980,7 +3977,7 @@ dependencies = [
|
|||
"litellm-llms",
|
||||
"litellm-secrets",
|
||||
"litellm-tracing",
|
||||
"reqwest 0.12.28",
|
||||
"reqwest",
|
||||
"rstest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
@ -4039,7 +4036,7 @@ dependencies = [
|
|||
"litellm-router-types",
|
||||
"litellm-secrets",
|
||||
"litellm-tracing",
|
||||
"reqwest 0.12.28",
|
||||
"reqwest",
|
||||
"rstest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
@ -4100,7 +4097,7 @@ dependencies = [
|
|||
"litellm-llms-types",
|
||||
"litellm-secrets",
|
||||
"litellm-tracing",
|
||||
"reqwest 0.12.28",
|
||||
"reqwest",
|
||||
"rstest",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
|
|
@ -4163,7 +4160,7 @@ dependencies = [
|
|||
"litellm-python-compat",
|
||||
"litellm-router-types",
|
||||
"litellm-secrets",
|
||||
"reqwest 0.12.28",
|
||||
"reqwest",
|
||||
"rstest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
@ -4245,7 +4242,7 @@ dependencies = [
|
|||
"pyo3",
|
||||
"pyo3-async-runtimes",
|
||||
"redis",
|
||||
"reqwest 0.12.28",
|
||||
"reqwest",
|
||||
"rstest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
@ -4316,7 +4313,7 @@ dependencies = [
|
|||
"litellm-secrets-hashicorp",
|
||||
"litellm-secrets-types",
|
||||
"moka",
|
||||
"reqwest 0.12.28",
|
||||
"reqwest",
|
||||
"rstest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
@ -4358,7 +4355,7 @@ dependencies = [
|
|||
"litellm-http",
|
||||
"litellm-secrets-types",
|
||||
"percent-encoding",
|
||||
"reqwest 0.12.28",
|
||||
"reqwest",
|
||||
"rstest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
@ -4381,7 +4378,7 @@ dependencies = [
|
|||
"moka",
|
||||
"percent-encoding",
|
||||
"rcgen",
|
||||
"reqwest 0.12.28",
|
||||
"reqwest",
|
||||
"rstest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
@ -4408,7 +4405,7 @@ dependencies = [
|
|||
"litellm-secrets-types",
|
||||
"moka",
|
||||
"percent-encoding",
|
||||
"reqwest 0.12.28",
|
||||
"reqwest",
|
||||
"rstest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
@ -4496,7 +4493,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"flate2",
|
||||
"futures-util",
|
||||
"reqwest 0.12.28",
|
||||
"reqwest",
|
||||
"rstest",
|
||||
"semver",
|
||||
"serde",
|
||||
|
|
@ -5869,49 +5866,6 @@ version = "1.9.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2"
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.12.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2 0.4.15",
|
||||
"http 1.4.2",
|
||||
"http-body 1.1.0",
|
||||
"http-body-util",
|
||||
"hyper 1.10.1",
|
||||
"hyper-rustls 0.27.9",
|
||||
"hyper-util",
|
||||
"js-sys",
|
||||
"log",
|
||||
"mime_guess",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"quinn",
|
||||
"rustls 0.23.42",
|
||||
"rustls-pki-types",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"sync_wrapper",
|
||||
"tokio",
|
||||
"tokio-rustls 0.26.4",
|
||||
"tokio-util",
|
||||
"tower",
|
||||
"tower-http",
|
||||
"tower-service",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-streams 0.4.2",
|
||||
"web-sys",
|
||||
"webpki-roots",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.13.5"
|
||||
|
|
@ -5933,6 +5887,7 @@ dependencies = [
|
|||
"js-sys",
|
||||
"log",
|
||||
"mime",
|
||||
"mime_guess",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"quinn",
|
||||
|
|
@ -5952,7 +5907,7 @@ dependencies = [
|
|||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-streams 0.5.0",
|
||||
"wasm-streams",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
|
|
@ -5999,7 +5954,7 @@ dependencies = [
|
|||
"pin-project-lite",
|
||||
"process-wrap",
|
||||
"rand 0.10.2",
|
||||
"reqwest 0.13.5",
|
||||
"reqwest",
|
||||
"schemars 1.2.2",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
@ -6122,7 +6077,7 @@ dependencies = [
|
|||
"async-trait",
|
||||
"bytes",
|
||||
"http 1.4.2",
|
||||
"reqwest 0.13.5",
|
||||
"reqwest",
|
||||
"rustify_derive",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
@ -7154,7 +7109,7 @@ dependencies = [
|
|||
"memchr",
|
||||
"parse-display",
|
||||
"pin-project-lite",
|
||||
"reqwest 0.13.5",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_with",
|
||||
|
|
@ -7793,7 +7748,7 @@ dependencies = [
|
|||
"futures",
|
||||
"pin-project",
|
||||
"rand 0.10.2",
|
||||
"reqwest 0.13.5",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"time",
|
||||
|
|
@ -8007,7 +7962,7 @@ dependencies = [
|
|||
"async-trait",
|
||||
"derive_builder",
|
||||
"http 1.4.2",
|
||||
"reqwest 0.13.5",
|
||||
"reqwest",
|
||||
"rustify",
|
||||
"rustify_derive",
|
||||
"serde",
|
||||
|
|
@ -8154,19 +8109,6 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-streams"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-streams"
|
||||
version = "0.5.0"
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ pyo3-async-runtimes = { version = "0.29.0", features = ["tokio-runtime"] }
|
|||
rand = "0.8"
|
||||
macro_rules_attribute = "0.2.3"
|
||||
schemars = "1"
|
||||
reqwest = { version = "0.12", default-features = false, features = ["json", "multipart", "rustls-tls", "http2", "stream"] }
|
||||
reqwest = { version = "0.13", default-features = false, features = ["json", "multipart", "rustls", "http2", "stream", "query"] }
|
||||
qdrant-client = { version = "1.19.0", default-features = false }
|
||||
uuid = { version = "1", features = ["v4"] }
|
||||
rstest = "0.26.1"
|
||||
|
|
|
|||
|
|
@ -10,8 +10,11 @@ disallowed-methods = [
|
|||
{ path = "reqwest::Client::new", reason = "take litellm_http::Client from HttpClientPool" },
|
||||
{ path = "reqwest::Client::builder", reason = "HttpClientConfig owns client construction" },
|
||||
{ path = "reqwest::ClientBuilder::danger_accept_invalid_certs", reason = "set HttpClientConfig::verify instead" },
|
||||
{ path = "reqwest::ClientBuilder::tls_danger_accept_invalid_certs", reason = "set HttpClientConfig::verify instead" },
|
||||
{ path = "reqwest::ClientBuilder::tls_danger_accept_invalid_hostnames", reason = "set HttpClientConfig::verify instead" },
|
||||
{ path = "reqwest::ClientBuilder::identity", reason = "set HttpClientConfig::client_certificate instead" },
|
||||
{ path = "reqwest::ClientBuilder::use_preconfigured_tls", reason = "HttpClientConfig owns the TLS configuration" },
|
||||
{ path = "reqwest::ClientBuilder::tls_backend_preconfigured", reason = "HttpClientConfig owns the TLS configuration" },
|
||||
{ path = "sqlx::query", reason = "use sqlx::query! or query_file! so the SQL is checked against the migrated schema" },
|
||||
{ path = "sqlx::query_as", reason = "use sqlx::query_as! or query_file_as! so the SQL is checked against the migrated schema" },
|
||||
{ path = "sqlx::query_scalar", reason = "use sqlx::query_scalar! so the SQL is checked against the migrated schema" },
|
||||
|
|
|
|||
|
|
@ -1080,7 +1080,7 @@ mod tests {
|
|||
&no_env,
|
||||
)
|
||||
.await?;
|
||||
let client = litellm_http::Client::plain_for_test();
|
||||
let client = litellm_http::Client::for_test();
|
||||
let mut failures = Vec::new();
|
||||
|
||||
for region in ["us-west-2", "us-east-1"] {
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ async fn connect(server: &MockServer) -> AzureBlobCache<JsonCodec<Value>> {
|
|||
None,
|
||||
ClientOptions {
|
||||
transport: Some(Transport::new(Arc::new(ReqwestTransport(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
)))),
|
||||
..ClientOptions::default()
|
||||
},
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ async fn cache_exposes_its_configuration(#[future(awt)] server: MockServer) {
|
|||
path_service_account: Some("/secrets/sa.json".into()),
|
||||
..support::config(&server, Some("folder"))
|
||||
},
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
litellm_cache::JsonCodec::<Value>::new(),
|
||||
);
|
||||
assert_eq!(cache.bucket_name(), "bucket");
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ pub fn cache_with_token(
|
|||
) -> JsonGcsCache {
|
||||
GcsCache::with_token_source(
|
||||
config(server, gcs_path),
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
JsonCodec::new(),
|
||||
token,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ fn config(base: String, timeout: Option<Duration>) -> OpenAiEmbedderConfig {
|
|||
async fn posts_embeddings_request_and_parses_vector() {
|
||||
let server = TestHttpServer::response("200 OK", r#"{"data":[{"embedding":[0.1,0.2]}]}"#).await;
|
||||
let embedder = OpenAiEmbedder::new(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
config(
|
||||
format!("{}/", server.base_url()),
|
||||
Some(Duration::from_secs(1)),
|
||||
|
|
@ -161,7 +161,7 @@ async fn status_timeout_and_body_errors_are_unavailable(
|
|||
let server =
|
||||
TestHttpServer::response_after(status, body, Duration::from_millis(delay_ms)).await;
|
||||
let embedder = OpenAiEmbedder::new(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
config(server.base_url(), timeout),
|
||||
);
|
||||
assert_eq!(embedder.async_embed("hello", None).await, expected);
|
||||
|
|
@ -170,7 +170,7 @@ async fn status_timeout_and_body_errors_are_unavailable(
|
|||
#[rstest]
|
||||
fn sync_embedding_is_unsupported() {
|
||||
let embedder = OpenAiEmbedder::new(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
config("http://127.0.0.1:9".to_owned(), None),
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
|
|||
|
|
@ -768,7 +768,7 @@ async fn gcs() -> (wiremock::MockServer, Gcs) {
|
|||
path_service_account: None,
|
||||
endpoint: server.uri(),
|
||||
},
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
litellm_cache_response::ResponseCacheCodec,
|
||||
Arc::new(litellm_cache_gcs::StaticTokenSource("token".into())),
|
||||
)));
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ pub fn config(endpoint: &str) -> S3CacheConfig {
|
|||
pub fn cache_with(config: S3CacheConfig, runtime: Handle) -> JsonS3Cache {
|
||||
S3Cache::new(
|
||||
config,
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
JsonCodec::new(),
|
||||
runtime,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ url.workspace = true
|
|||
moka.workspace = true
|
||||
sha2.workspace = true
|
||||
tower = { version = "0.5", features = ["util"] }
|
||||
rmcp = { version = "=3.4.1", default-features = false, features = ["server", "client", "elicitation", "transport-streamable-http-server", "transport-streamable-http-client", "transport-child-process"] }
|
||||
rmcp = { version = "=3.4.1", default-features = false, features = ["server", "client", "elicitation", "transport-streamable-http-server", "transport-streamable-http-client-reqwest", "transport-child-process"] }
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
thiserror.workspace = true
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ litellm-gateway-auth.workspace = true
|
|||
litellm-gateway-ui.workspace = true
|
||||
litellm-auth-types.workspace = true
|
||||
litellm-config.workspace = true
|
||||
litellm-http = { workspace = true, features = ["mcp"] }
|
||||
litellm-http.workspace = true
|
||||
litellm-llms.workspace = true
|
||||
litellm-secrets.workspace = true
|
||||
litellm-tracing.workspace = true
|
||||
|
|
|
|||
|
|
@ -101,11 +101,11 @@ pub async fn build_mcp(
|
|||
Auth::from_config(config, secrets.clone())
|
||||
.validate()
|
||||
.await?;
|
||||
let client = pool.mcp_client(http)?;
|
||||
let client = pool.client(http, ClientVariant::NoRedirect)?;
|
||||
Ok(Some(
|
||||
litellm_gateway_mcp::ConfiguredGateway::connect(
|
||||
&config.mcp_servers,
|
||||
client,
|
||||
(*client).clone(),
|
||||
secrets.as_ref(),
|
||||
shutdown,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -7,11 +7,8 @@ repository.workspace = true
|
|||
|
||||
[features]
|
||||
test-support = []
|
||||
mcp = ["dep:rmcp", "dep:reqwest-mcp"]
|
||||
|
||||
[dependencies]
|
||||
rmcp = { version = "=3.4.1", default-features = false, features = ["client", "transport-streamable-http-client-reqwest"], optional = true }
|
||||
reqwest-mcp = { package = "reqwest", version = "0.13.2", default-features = false, features = ["rustls-no-provider", "json", "stream", "http2"], optional = true }
|
||||
http.workspace = true
|
||||
litellm-core-utils.workspace = true
|
||||
hyper-util.workspace = true
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
/// Only `HttpClientPool` builds one, so every client carries the resolved TLS, proxy and timeout settings.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Client(reqwest::Client);
|
||||
|
||||
|
|
@ -9,17 +10,7 @@ impl Client {
|
|||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn for_test(client: reqwest::Client) -> Self {
|
||||
Self(client)
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn plain_for_test() -> Self {
|
||||
Self(reqwest::Client::new())
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn no_redirect_for_test() -> Self {
|
||||
pub fn for_test() -> Self {
|
||||
Self(
|
||||
reqwest::Client::builder()
|
||||
.redirect(reqwest::redirect::Policy::none())
|
||||
|
|
@ -27,6 +18,11 @@ impl Client {
|
|||
.expect("a client without TLS or proxy settings builds"),
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn wrap_for_test(client: reqwest::Client) -> Self {
|
||||
Self(client)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Client {
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ impl TryFrom<&HttpClientConfig> for reqwest::ClientBuilder {
|
|||
|
||||
fn try_from(config: &HttpClientConfig) -> Result<Self, Self::Error> {
|
||||
let base = reqwest::Client::builder()
|
||||
.use_preconfigured_tls(rustls::ClientConfig::try_from(config)?)
|
||||
.tls_backend_preconfigured(rustls::ClientConfig::try_from(config)?)
|
||||
.connect_timeout(config.connect_timeout)
|
||||
.pool_idle_timeout(config.pool_idle_timeout);
|
||||
let with_keepalive = match config.tcp_keepalive {
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@
|
|||
mod client;
|
||||
mod config;
|
||||
mod error;
|
||||
#[cfg(feature = "mcp")]
|
||||
mod mcp;
|
||||
pub mod media;
|
||||
pub mod outbound;
|
||||
mod pool;
|
||||
|
|
|
|||
|
|
@ -1,76 +0,0 @@
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
net::{IpAddr, Ipv4Addr},
|
||||
sync::{Mutex, PoisonError},
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use crate::{Error, HttpClientConfig};
|
||||
|
||||
struct Entry {
|
||||
client: reqwest_mcp::Client,
|
||||
built_at: Instant,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(super) struct Pool(Mutex<HashMap<HttpClientConfig, Entry>>);
|
||||
|
||||
impl Pool {
|
||||
pub fn client(
|
||||
&self,
|
||||
config: &HttpClientConfig,
|
||||
ttl: Duration,
|
||||
) -> Result<reqwest_mcp::Client, Error> {
|
||||
let mut clients = self.0.lock().unwrap_or_else(PoisonError::into_inner);
|
||||
if let Some(entry) = clients.get(config)
|
||||
&& entry.built_at.elapsed() < ttl
|
||||
{
|
||||
return Ok(entry.client.clone());
|
||||
}
|
||||
let client = build(config)?;
|
||||
clients.insert(
|
||||
config.clone(),
|
||||
Entry {
|
||||
client: client.clone(),
|
||||
built_at: Instant::now(),
|
||||
},
|
||||
);
|
||||
Ok(client)
|
||||
}
|
||||
}
|
||||
|
||||
fn build(config: &HttpClientConfig) -> Result<reqwest_mcp::Client, Error> {
|
||||
let base = reqwest_mcp::Client::builder()
|
||||
.tls_backend_preconfigured(rustls::ClientConfig::try_from(config)?)
|
||||
.connect_timeout(config.connect_timeout)
|
||||
.pool_idle_timeout(config.pool_idle_timeout)
|
||||
.redirect(reqwest_mcp::redirect::Policy::none());
|
||||
let keepalive = match config.tcp_keepalive {
|
||||
Some(value) => base
|
||||
.tcp_keepalive(value.idle)
|
||||
.tcp_keepalive_interval(value.interval)
|
||||
.tcp_keepalive_retries(value.retries),
|
||||
None => base,
|
||||
};
|
||||
let address = if config.force_ipv4 {
|
||||
keepalive.local_address(IpAddr::V4(Ipv4Addr::UNSPECIFIED))
|
||||
} else {
|
||||
keepalive
|
||||
};
|
||||
let protocol = if config.http2 {
|
||||
address
|
||||
} else {
|
||||
address.http1_only()
|
||||
};
|
||||
let agent = match &config.user_agent {
|
||||
Some(value) => protocol.user_agent(value),
|
||||
None => protocol,
|
||||
};
|
||||
config
|
||||
.proxies
|
||||
.mcp_proxies()
|
||||
.into_iter()
|
||||
.fold(agent.no_proxy(), reqwest_mcp::ClientBuilder::proxy)
|
||||
.build()
|
||||
.map_err(|error| Error::Client(error.without_url().to_string()))
|
||||
}
|
||||
|
|
@ -522,7 +522,7 @@ mod tests {
|
|||
b"HTTP/1.1 200 OK\r\nContent-Type: application/pdf; charset=binary\r\nContent-Length: 3\r\nConnection: close\r\n\r\nabc",
|
||||
)
|
||||
.await;
|
||||
let client = Client::no_redirect_for_test();
|
||||
let client = Client::for_test();
|
||||
let media = MediaFetcher::for_test(client)
|
||||
.fetch(url, policy(3, 0))
|
||||
.await
|
||||
|
|
@ -538,7 +538,7 @@ mod tests {
|
|||
b"HTTP/1.1 200 OK\r\nContent-Type: application/pdf\r\nContent-Length: 3\r\nConnection: close\r\n\r\nabc",
|
||||
)
|
||||
.await;
|
||||
let client = Client::no_redirect_for_test();
|
||||
let client = Client::for_test();
|
||||
let error = MediaFetcher::for_test(client)
|
||||
.fetch(url, policy(2, 0))
|
||||
.await
|
||||
|
|
@ -553,7 +553,7 @@ mod tests {
|
|||
b"HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\nConnection: close\r\n\r\n2\r\nab\r\n2\r\ncd\r\n0\r\n\r\n",
|
||||
)
|
||||
.await;
|
||||
let client = Client::no_redirect_for_test();
|
||||
let client = Client::for_test();
|
||||
let error = MediaFetcher::for_test(client)
|
||||
.fetch(url, policy(3, 0))
|
||||
.await
|
||||
|
|
|
|||
|
|
@ -29,8 +29,6 @@ pub struct HttpClientPool {
|
|||
media_resolver: Arc<dyn Resolve>,
|
||||
ttl: Duration,
|
||||
clients: Mutex<Clients>,
|
||||
#[cfg(feature = "mcp")]
|
||||
mcp: crate::mcp::Pool,
|
||||
}
|
||||
|
||||
impl HttpClientPool {
|
||||
|
|
@ -43,19 +41,9 @@ impl HttpClientPool {
|
|||
media_resolver,
|
||||
ttl,
|
||||
clients: Mutex::default(),
|
||||
#[cfg(feature = "mcp")]
|
||||
mcp: crate::mcp::Pool::default(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mcp")]
|
||||
pub fn mcp_client(
|
||||
&self,
|
||||
config: &HttpClientConfig,
|
||||
) -> Result<impl rmcp::transport::streamable_http_client::StreamableHttpClient, Error> {
|
||||
self.mcp.client(config, self.ttl)
|
||||
}
|
||||
|
||||
pub fn client(
|
||||
&self,
|
||||
config: &HttpClientConfig,
|
||||
|
|
@ -108,7 +96,7 @@ impl HttpClientPool {
|
|||
}
|
||||
ClientVariant::Media => builder
|
||||
.redirect(reqwest::redirect::Policy::none())
|
||||
.dns_resolver2(Arc::clone(&self.media_resolver)),
|
||||
.dns_resolver(Arc::clone(&self.media_resolver)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -390,56 +378,4 @@ mod tests {
|
|||
.is_err()
|
||||
);
|
||||
}
|
||||
#[cfg(feature = "mcp")]
|
||||
#[rstest::rstest]
|
||||
#[tokio::test]
|
||||
async fn mcp_clients_reuse_connections_and_apply_proxy_headers_without_redirects() {
|
||||
let (address, connections, requests) = serve("HTTP/1.1 302 Found").await;
|
||||
let pool = pool();
|
||||
let config = HttpClientConfig {
|
||||
proxies: proxied_through(&format!("http://{address}")),
|
||||
..config("mcp-pool-test")
|
||||
};
|
||||
for _ in 0..2 {
|
||||
let response = pool
|
||||
.mcp
|
||||
.client(&config, pool.ttl)
|
||||
.unwrap()
|
||||
.get("http://upstream.invalid/mcp")
|
||||
.timeout(Duration::from_secs(2))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(response.status(), 302);
|
||||
response.bytes().await.unwrap();
|
||||
}
|
||||
assert_eq!(connections.load(Ordering::SeqCst), 1);
|
||||
let requests = requests.lock().unwrap();
|
||||
assert_eq!(requests.len(), 2);
|
||||
assert!(
|
||||
requests
|
||||
.iter()
|
||||
.all(|request| request.starts_with("GET http://upstream.invalid/mcp HTTP/1.1"))
|
||||
);
|
||||
assert!(
|
||||
requests
|
||||
.iter()
|
||||
.all(|request| request.contains("user-agent: mcp-pool-test"))
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "mcp")]
|
||||
#[rstest::rstest]
|
||||
#[tokio::test]
|
||||
async fn mcp_client_uses_host_tls_configuration() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let config = HttpClientConfig {
|
||||
verify: Verify::CaBundle(directory.path().join("missing.pem")),
|
||||
..config("mcp-test")
|
||||
};
|
||||
assert!(matches!(
|
||||
pool().mcp_client(&config),
|
||||
Err(Error::Read { .. })
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,19 +63,6 @@ impl EnvironmentProxies {
|
|||
.map(|proxy| proxy.no_proxy(no_proxy.clone()))
|
||||
.collect()
|
||||
}
|
||||
#[cfg(feature = "mcp")]
|
||||
pub(crate) fn mcp_proxies(&self) -> Vec<reqwest_mcp::Proxy> {
|
||||
let no_proxy = reqwest_mcp::NoProxy::from_string(&self.no);
|
||||
[
|
||||
reqwest_mcp::Proxy::http(self.http.as_str()),
|
||||
reqwest_mcp::Proxy::https(self.https.as_str()),
|
||||
reqwest_mcp::Proxy::all(self.all.as_str()),
|
||||
]
|
||||
.into_iter()
|
||||
.filter_map(Result::ok)
|
||||
.map(|proxy| proxy.no_proxy(no_proxy.clone()))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ mod tests {
|
|||
|
||||
let (provider, config, request) = prepared(&upstream.uri());
|
||||
execute(
|
||||
&Client::plain_for_test(),
|
||||
&Client::for_test(),
|
||||
&AuthServices::default(),
|
||||
config,
|
||||
provider,
|
||||
|
|
@ -328,7 +328,7 @@ mod tests {
|
|||
|
||||
let (provider, config, request) = prepared(&upstream.uri());
|
||||
let error = execute(
|
||||
&Client::plain_for_test(),
|
||||
&Client::for_test(),
|
||||
&AuthServices::default(),
|
||||
config,
|
||||
provider,
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ async fn chat_cache_identity_follows_resolved_configuration_and_request_callback
|
|||
.store(usize::from(call >= 2), Ordering::SeqCst);
|
||||
let cache = ScopedCache::new(cache.clone(), CacheScope::Shared);
|
||||
ChatCompletionsRoute::new(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
Arc::new(Default::default()),
|
||||
secrets.clone(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -888,7 +888,7 @@ mod tests {
|
|||
.respond_with(ResponseTemplate::new(200).set_body_raw(body, "text/event-stream"))
|
||||
.mount(&upstream)
|
||||
.await;
|
||||
let response = litellm_http::Client::plain_for_test()
|
||||
let response = litellm_http::Client::for_test()
|
||||
.get(upstream.uri())
|
||||
.send()
|
||||
.await
|
||||
|
|
|
|||
|
|
@ -121,11 +121,7 @@ mod tests {
|
|||
};
|
||||
|
||||
fn client() -> OcrClient {
|
||||
OcrClient::for_test(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::no_redirect_for_test(),
|
||||
)
|
||||
.with_secrets(litellm_inference_testing::no_secrets())
|
||||
OcrClient::for_test().with_secrets(litellm_inference_testing::no_secrets())
|
||||
}
|
||||
|
||||
fn request(model: &str, base: &str, document: Value, options: Value) -> LiteLLMOcrRequest {
|
||||
|
|
|
|||
|
|
@ -190,16 +190,14 @@ mod tests {
|
|||
clippy::disallowed_types,
|
||||
reason = "the pool has no default-header setting to stand in for provider credentials"
|
||||
)]
|
||||
let provider_http = litellm_http::Client::for_test(
|
||||
let provider_http = litellm_http::Client::wrap_for_test(
|
||||
reqwest::Client::builder()
|
||||
.default_headers(provider_headers)
|
||||
.build()
|
||||
.unwrap(),
|
||||
);
|
||||
let client = crate::base_llm::ocr::handler::OcrClient::for_test(
|
||||
provider_http,
|
||||
litellm_http::Client::no_redirect_for_test(),
|
||||
);
|
||||
let client =
|
||||
crate::base_llm::ocr::handler::OcrClient::for_test().with_provider_http(provider_http);
|
||||
let converted = inline_remote_document(
|
||||
client.document_fetcher(),
|
||||
OcrDocument::ImageUrl {
|
||||
|
|
|
|||
|
|
@ -86,21 +86,27 @@ impl OcrClient {
|
|||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn for_test(provider_http: Client, no_redirect_http: Client) -> Self {
|
||||
pub fn for_test() -> Self {
|
||||
Self {
|
||||
secrets: Arc::new(
|
||||
litellm_secrets::source::EnvironmentSecrets::python_compatible(
|
||||
provider_http.clone(),
|
||||
),
|
||||
litellm_secrets::source::EnvironmentSecrets::python_compatible(Client::for_test()),
|
||||
),
|
||||
provider_http,
|
||||
polling_http: no_redirect_http.clone(),
|
||||
document_fetcher: MediaFetcher::for_test(no_redirect_http),
|
||||
provider_http: Client::for_test(),
|
||||
polling_http: Client::for_test(),
|
||||
document_fetcher: MediaFetcher::for_test(Client::for_test()),
|
||||
auth: Arc::new(AuthServices::default()),
|
||||
settings: OcrSettings::default(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn with_provider_http(self, provider_http: Client) -> Self {
|
||||
Self {
|
||||
provider_http,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn with_settings(self, settings: OcrSettings) -> Self {
|
||||
Self { settings, ..self }
|
||||
|
|
@ -322,7 +328,7 @@ mod tests {
|
|||
let _connection = listener.accept().await.unwrap();
|
||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||
});
|
||||
let error = litellm_http::Client::plain_for_test()
|
||||
let error = litellm_http::Client::for_test()
|
||||
.get(format!("http://{address}"))
|
||||
.timeout(Duration::from_millis(10))
|
||||
.send()
|
||||
|
|
@ -347,7 +353,7 @@ mod tests {
|
|||
socket.write_all(response.as_bytes()).await.unwrap();
|
||||
std::future::pending::<()>().await;
|
||||
});
|
||||
let response = litellm_http::Client::plain_for_test()
|
||||
let response = litellm_http::Client::for_test()
|
||||
.get(format!("http://{address}"))
|
||||
.send()
|
||||
.await
|
||||
|
|
|
|||
|
|
@ -566,10 +566,7 @@ mod tests {
|
|||
let params = ReductoParseV3Config
|
||||
.map_ocr_params(&overrides, "parse-v3")
|
||||
.unwrap();
|
||||
let client = OcrClient::for_test(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::no_redirect_for_test(),
|
||||
);
|
||||
let client = OcrClient::for_test();
|
||||
let connection = OcrConnection::default();
|
||||
let document = serde_json::from_value(
|
||||
json!({"type":"document_url","document_url":"reducto://ready.pdf"}),
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ handler.get_secret_from_manager = get_secret_from_manager
|
|||
KeyManagementSettings::default(),
|
||||
)),
|
||||
Arc::new(move |_: &str| fallback.map(str::to_owned)),
|
||||
OidcResolver::new(litellm_http::Client::plain_for_test()),
|
||||
OidcResolver::new(litellm_http::Client::for_test()),
|
||||
)
|
||||
.with_failure_policy(FailurePolicy::EnvironmentFallback);
|
||||
(resolver, locals, handler)
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ mod tests {
|
|||
}
|
||||
|
||||
async fn resolve(state: Arc<SecretManagerState>, name: &'static str) -> Option<String> {
|
||||
ResolvedSecrets::from_state(state, litellm_http::Client::plain_for_test())
|
||||
ResolvedSecrets::from_state(state, litellm_http::Client::for_test())
|
||||
.resolve(&[name])
|
||||
.await
|
||||
.unwrap()
|
||||
|
|
@ -182,7 +182,7 @@ mod tests {
|
|||
.await;
|
||||
let source = ResolvedSecrets::from_state(
|
||||
state(&server, KeyManagementSettings::default()),
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
);
|
||||
let snapshot = source.resolve(&[declared]).await.unwrap();
|
||||
assert_eq!(snapshot.get(undeclared), None);
|
||||
|
|
@ -248,7 +248,7 @@ mod tests {
|
|||
async fn oidc_failures_are_not_converted_to_missing_secrets() {
|
||||
let result = ResolvedSecrets::from_state(
|
||||
Arc::new(SecretManagerState::default()),
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
)
|
||||
.resolve(&["oidc/"])
|
||||
.await;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use wiremock::{
|
|||
|
||||
fn manager(server: &MockServer) -> AzureKeyVault {
|
||||
AzureKeyVault::with_client(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
server.uri().parse().unwrap(),
|
||||
Arc::new(|name: &str| (name == "AZURE_AD_TOKEN").then(|| "fake".to_owned())),
|
||||
)
|
||||
|
|
@ -131,7 +131,7 @@ fn new_validates_vault_environment(
|
|||
#[case] missing_environment: bool,
|
||||
) {
|
||||
let result = AzureKeyVault::new(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
Arc::new(move |name: &str| {
|
||||
(name == "AZURE_KEY_VAULT_URI")
|
||||
.then(|| uri.map(str::to_owned))
|
||||
|
|
@ -158,7 +158,7 @@ fn new_validates_vault_environment(
|
|||
#[case::local("http://localhost:8080", "https://localhost/.default")]
|
||||
fn derives_scope_from_vault_host(#[case] uri: &str, #[case] expected: &str) {
|
||||
let manager = AzureKeyVault::with_client(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
uri.parse().unwrap(),
|
||||
Arc::new(|_: &str| None),
|
||||
)
|
||||
|
|
@ -187,7 +187,7 @@ async fn missing_credentials_do_not_request_vault() {
|
|||
|
||||
fn manager_without_credentials(server: &MockServer) -> AzureKeyVault {
|
||||
AzureKeyVault::with_client(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
server.uri().parse().unwrap(),
|
||||
Arc::new(|name: &str| {
|
||||
(name == "AZURE_CREDENTIAL").then(|| "ClientSecretCredential".to_owned())
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use rstest::rstest;
|
|||
#[ignore]
|
||||
async fn reads_a_real_secret() {
|
||||
let environment = Arc::new(ProcessEnvironment);
|
||||
let manager = AzureKeyVault::new(litellm_http::Client::plain_for_test(), environment).unwrap();
|
||||
let manager = AzureKeyVault::new(litellm_http::Client::for_test(), environment).unwrap();
|
||||
let name = std::env::var("AZURE_KEY_VAULT_LIVE_SECRET_NAME").unwrap();
|
||||
let secret = manager.get_secret(&name).await.unwrap().unwrap();
|
||||
assert!(matches!(&secret, Secret::String(_)));
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ async fn authentication_encodes_login(#[case] username: &str, #[case] expected_p
|
|||
.mount(&server)
|
||||
.await;
|
||||
let manager = CyberArkSecretManager::with_client(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
server.uri().parse().unwrap(),
|
||||
"acct".into(),
|
||||
username.into(),
|
||||
|
|
@ -433,7 +433,7 @@ async fn trailing_slash_endpoint_preserves_base_path() {
|
|||
.await;
|
||||
let endpoint = format!("{}/prefix/", server.uri()).parse().unwrap();
|
||||
let manager = CyberArkSecretManager::with_client(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
endpoint,
|
||||
"acct".into(),
|
||||
"admin".into(),
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ pub(super) fn from_environment(
|
|||
|
||||
pub(super) fn manager(server: &MockServer, ttl: Duration) -> CyberArkSecretManager {
|
||||
CyberArkSecretManager::with_client(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
server.uri().parse().unwrap(),
|
||||
"acct".into(),
|
||||
"admin".into(),
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ async fn writes_match_python_parity_fixture(parity_fixture: ParityFixture) {
|
|||
.mount(&server)
|
||||
.await;
|
||||
let manager = CyberArkSecretManager::with_client(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
server.uri().parse().unwrap(),
|
||||
parity_fixture.account,
|
||||
parity_fixture.username,
|
||||
|
|
@ -297,7 +297,7 @@ async fn live_conjur_round_trip() {
|
|||
.as_nanos()
|
||||
);
|
||||
let manager = CyberArkSecretManager::with_client(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
endpoint.clone(),
|
||||
account.clone(),
|
||||
username.clone(),
|
||||
|
|
@ -312,7 +312,7 @@ async fn live_conjur_round_trip() {
|
|||
.await
|
||||
.unwrap();
|
||||
let verifier = CyberArkSecretManager::with_client(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
endpoint.clone(),
|
||||
account.clone(),
|
||||
username.clone(),
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use wiremock::{
|
|||
|
||||
fn manager(server: &MockServer, always_read: bool, ttl: Duration) -> GoogleSecretManager {
|
||||
GoogleSecretManager::with_client(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
server.uri().parse().unwrap(),
|
||||
"project".into(),
|
||||
Arc::new(|name: &str| (name == "VERTEX_AI_API_KEY").then(|| "token".into())),
|
||||
|
|
@ -215,7 +215,7 @@ async fn always_read_and_expired_cache_fetch_again(
|
|||
fn google_manager_requires_host_license_and_project_configuration() {
|
||||
assert!(matches!(
|
||||
GoogleSecretManager::new(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
Arc::new(|_: &str| None),
|
||||
false
|
||||
),
|
||||
|
|
@ -223,7 +223,7 @@ fn google_manager_requires_host_license_and_project_configuration() {
|
|||
));
|
||||
assert!(matches!(
|
||||
GoogleSecretManager::new(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
Arc::new(|_: &str| None),
|
||||
true
|
||||
),
|
||||
|
|
@ -244,7 +244,7 @@ fn google_manager_rejects_invalid_refresh_intervals(#[case] variable: &'static s
|
|||
});
|
||||
|
||||
assert!(matches!(
|
||||
GoogleSecretManager::new(litellm_http::Client::plain_for_test(), environment, true),
|
||||
GoogleSecretManager::new(litellm_http::Client::for_test(), environment, true),
|
||||
Err(Error::RefreshInterval)
|
||||
));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ async fn read_results_follow_the_selected_failure_policy(
|
|||
},
|
||||
)),
|
||||
Arc::new(move |_: &str| environment.map(str::to_owned)),
|
||||
OidcResolver::new(litellm_http::Client::plain_for_test()),
|
||||
OidcResolver::new(litellm_http::Client::for_test()),
|
||||
)
|
||||
.with_failure_policy(policy);
|
||||
let result = resolver
|
||||
|
|
@ -97,7 +97,7 @@ async fn primary_secret_values_other_than_strings_resolve_to_none(
|
|||
let resolver = SecretResolver::new_python_compatible(
|
||||
Arc::new(state(&server, settings)),
|
||||
Arc::new(|_: &str| Some("fallback".into())),
|
||||
OidcResolver::new(litellm_http::Client::plain_for_test()),
|
||||
OidcResolver::new(litellm_http::Client::for_test()),
|
||||
);
|
||||
let text = value.as_str();
|
||||
assert_eq!(
|
||||
|
|
@ -157,7 +157,7 @@ async fn gating_prediction_matches_actual_lookup(
|
|||
let resolver = SecretResolver::new_python_compatible(
|
||||
Arc::new(state),
|
||||
Arc::new(|_: &str| Some("environment".into())),
|
||||
OidcResolver::new(litellm_http::Client::plain_for_test()),
|
||||
OidcResolver::new(litellm_http::Client::for_test()),
|
||||
);
|
||||
assert_eq!(
|
||||
resolver
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ async fn azure_handler_reads_missing_and_failed_secrets() {
|
|||
.await;
|
||||
let manager = SecretManager::AzureKeyVault(
|
||||
AzureKeyVault::with_client(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
server.uri().parse().unwrap(),
|
||||
std::sync::Arc::new(|name: &str| (name == "AZURE_AD_TOKEN").then(|| "fake".to_owned())),
|
||||
)
|
||||
|
|
@ -81,7 +81,7 @@ async fn successful_azure_responses_do_not_fall_back_when_the_value_is_empty_or_
|
|||
.mount(&server)
|
||||
.await;
|
||||
let manager = AzureKeyVault::with_client(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
server.uri().parse().unwrap(),
|
||||
Arc::new(|name: &str| (name == "AZURE_AD_TOKEN").then(|| "token".into())),
|
||||
)
|
||||
|
|
@ -92,7 +92,7 @@ async fn successful_azure_responses_do_not_fall_back_when_the_value_is_empty_or_
|
|||
Default::default(),
|
||||
)),
|
||||
Arc::new(|_: &str| Some("environment".into())),
|
||||
OidcResolver::new(litellm_http::Client::plain_for_test()),
|
||||
OidcResolver::new(litellm_http::Client::for_test()),
|
||||
);
|
||||
assert_eq!(
|
||||
resolver
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ fn manager(provider: Provider, server: &MockServer) -> SecretManager {
|
|||
),
|
||||
Provider::Azure => SecretManager::AzureKeyVault(
|
||||
AzureKeyVault::with_client(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
server.uri().parse().unwrap(),
|
||||
environment,
|
||||
)
|
||||
|
|
@ -67,7 +67,7 @@ fn manager(provider: Provider, server: &MockServer) -> SecretManager {
|
|||
),
|
||||
Provider::Google => SecretManager::GoogleSecretManager(
|
||||
GoogleSecretManager::with_client(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
server.uri().parse().unwrap(),
|
||||
"project".into(),
|
||||
environment,
|
||||
|
|
@ -84,7 +84,7 @@ fn manager(provider: Provider, server: &MockServer) -> SecretManager {
|
|||
.unwrap(),
|
||||
),
|
||||
Provider::Cyberark => SecretManager::Cyberark(CyberArkSecretManager::with_client(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
server.uri().parse().unwrap(),
|
||||
"acct".into(),
|
||||
"admin".into(),
|
||||
|
|
@ -240,7 +240,7 @@ async fn python_read_failures_preserve_provider_fallback_rules(
|
|||
KeyManagementSettings::default(),
|
||||
)),
|
||||
Arc::new(move |_: &str| environment_value.map(str::to_owned)),
|
||||
OidcResolver::new(litellm_http::Client::plain_for_test()),
|
||||
OidcResolver::new(litellm_http::Client::for_test()),
|
||||
);
|
||||
let expected = if matches!(provider, Provider::Aws) {
|
||||
None
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ async fn cyberark_handler_reads_values_and_surfaces_errors() {
|
|||
.mount(&server)
|
||||
.await;
|
||||
let manager = SecretManager::Cyberark(CyberArkSecretManager::with_client(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
server.uri().parse().unwrap(),
|
||||
"acct".into(),
|
||||
"admin".into(),
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ async fn google_resolver_distinguishes_absence_from_failure(#[case] status: u16)
|
|||
_ => None,
|
||||
});
|
||||
let manager = GoogleSecretManager::with_client(
|
||||
litellm_http::Client::plain_for_test(),
|
||||
litellm_http::Client::for_test(),
|
||||
server.uri().parse().unwrap(),
|
||||
"project".into(),
|
||||
environment.clone(),
|
||||
|
|
@ -40,7 +40,7 @@ async fn google_resolver_distinguishes_absence_from_failure(#[case] status: u16)
|
|||
let resolver = SecretResolver::new_python_compatible(
|
||||
Arc::new(state),
|
||||
environment,
|
||||
OidcResolver::new(litellm_http::Client::plain_for_test()),
|
||||
OidcResolver::new(litellm_http::Client::for_test()),
|
||||
)
|
||||
.with_failure_policy(FailurePolicy::Propagate);
|
||||
let result = resolver.get_secret_str("KEY", None).await;
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ async fn hashicorp_handler_resolves_found_missing_and_failed_values() {
|
|||
},
|
||||
)),
|
||||
Arc::new(|_: &str| None),
|
||||
litellm_secrets::OidcResolver::new(litellm_http::Client::plain_for_test()),
|
||||
litellm_secrets::OidcResolver::new(litellm_http::Client::for_test()),
|
||||
);
|
||||
assert_eq!(
|
||||
found_resolver
|
||||
|
|
@ -131,7 +131,7 @@ async fn hashicorp_handler_resolves_found_missing_and_failed_values() {
|
|||
let failed_resolver = SecretResolver::new_python_compatible(
|
||||
Arc::new(failed_state),
|
||||
Arc::new(|_: &str| None),
|
||||
litellm_secrets::OidcResolver::new(litellm_http::Client::plain_for_test()),
|
||||
litellm_secrets::OidcResolver::new(litellm_http::Client::for_test()),
|
||||
)
|
||||
.with_failure_policy(FailurePolicy::Propagate);
|
||||
assert!(matches!(
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ async fn environment_sources_resolve_expected_value(
|
|||
("CIRCLE_OIDC_TOKEN_V2", "circle-v2"),
|
||||
]);
|
||||
assert_eq!(
|
||||
OidcResolver::new(litellm_http::Client::plain_for_test())
|
||||
OidcResolver::new(litellm_http::Client::for_test())
|
||||
.resolve(reference, env.as_ref())
|
||||
.await
|
||||
.unwrap()
|
||||
|
|
@ -43,7 +43,7 @@ async fn environment_sources_resolve_expected_value(
|
|||
#[tokio::test]
|
||||
async fn environment_sources_bypass_boolean_conversion_and_defaults() {
|
||||
let env = environment(&[("TOKEN", "true")]);
|
||||
let oidc = OidcResolver::new(litellm_http::Client::plain_for_test());
|
||||
let oidc = OidcResolver::new(litellm_http::Client::for_test());
|
||||
let resolver = SecretResolver::new(Arc::new(SecretManagerState::default()), env, oidc);
|
||||
assert_eq!(
|
||||
resolver
|
||||
|
|
@ -94,7 +94,7 @@ async fn github_requests_are_authenticated_cached_and_revalidate_environment() {
|
|||
),
|
||||
("ACTIONS_ID_TOKEN_REQUEST_TOKEN", "request-token"),
|
||||
]);
|
||||
let oidc = OidcResolver::new(litellm_http::Client::plain_for_test());
|
||||
let oidc = OidcResolver::new(litellm_http::Client::for_test());
|
||||
for _ in 0..2 {
|
||||
assert_eq!(
|
||||
oidc.resolve("oidc/github/https://service/oidc/path", env.as_ref())
|
||||
|
|
@ -131,7 +131,7 @@ async fn file_allowlist_resolves_symlinks_while_environment_paths_remain_explici
|
|||
("PATH_TOKEN", private.to_str().unwrap()),
|
||||
("AZURE_FEDERATED_TOKEN_FILE", token.to_str().unwrap()),
|
||||
]);
|
||||
let oidc = OidcResolver::new(litellm_http::Client::plain_for_test());
|
||||
let oidc = OidcResolver::new(litellm_http::Client::for_test());
|
||||
assert_eq!(
|
||||
oidc.resolve(&format!("oidc/file/{}", token.display()), env.as_ref())
|
||||
.await
|
||||
|
|
@ -213,7 +213,7 @@ async fn google_expiry_caps_cache_and_preserves_audience(
|
|||
.expect(calls)
|
||||
.mount(&server)
|
||||
.await;
|
||||
let oidc = OidcResolver::new(litellm_http::Client::plain_for_test())
|
||||
let oidc = OidcResolver::new(litellm_http::Client::for_test())
|
||||
.with_google_identity_endpoint(server.uri().parse().unwrap())
|
||||
.with_clock(now);
|
||||
for _ in 0..2 {
|
||||
|
|
@ -235,7 +235,7 @@ async fn google_expiry_caps_cache_and_preserves_audience(
|
|||
#[tokio::test]
|
||||
async fn google_oidc_requires_its_build_feature() {
|
||||
assert!(matches!(
|
||||
OidcResolver::new(litellm_http::Client::plain_for_test())
|
||||
OidcResolver::new(litellm_http::Client::for_test())
|
||||
.resolve("oidc/google/audience", environment(&[]).as_ref())
|
||||
.await,
|
||||
Err(Error::UnsupportedOidc)
|
||||
|
|
@ -246,7 +246,7 @@ async fn google_oidc_requires_its_build_feature() {
|
|||
#[tokio::test]
|
||||
async fn azure_oidc_without_a_token_file_requires_its_build_feature() {
|
||||
assert!(matches!(
|
||||
OidcResolver::new(litellm_http::Client::plain_for_test())
|
||||
OidcResolver::new(litellm_http::Client::for_test())
|
||||
.resolve("oidc/azure/scope", environment(&[]).as_ref())
|
||||
.await,
|
||||
Err(Error::UnsupportedOidc)
|
||||
|
|
@ -262,7 +262,7 @@ async fn invalid_references_fail_before_environment_lookup(
|
|||
#[case] reference: &str,
|
||||
#[case] unsupported: bool,
|
||||
) {
|
||||
let error = OidcResolver::new(litellm_http::Client::plain_for_test())
|
||||
let error = OidcResolver::new(litellm_http::Client::for_test())
|
||||
.resolve(reference, &|_: &str| {
|
||||
panic!("invalid reference reached environment lookup")
|
||||
})
|
||||
|
|
@ -284,7 +284,7 @@ async fn unreadable_expiry_keeps_python_cache_fallback(#[case] token: &str) {
|
|||
.expect(1)
|
||||
.mount(&server)
|
||||
.await;
|
||||
let resolver = OidcResolver::new(litellm_http::Client::plain_for_test())
|
||||
let resolver = OidcResolver::new(litellm_http::Client::for_test())
|
||||
.with_google_identity_endpoint(server.uri().parse().unwrap());
|
||||
for _ in 0..2 {
|
||||
assert_eq!(
|
||||
|
|
@ -336,7 +336,7 @@ async fn azure_oidc_acquires_the_requested_scope_and_preserves_failures(#[case]
|
|||
})
|
||||
}
|
||||
}
|
||||
let oidc = OidcResolver::new(litellm_http::Client::plain_for_test())
|
||||
let oidc = OidcResolver::new(litellm_http::Client::for_test())
|
||||
.with_azure_token_provider(Arc::new(Provider(failed)));
|
||||
let resolver = SecretResolver::new_python_compatible(
|
||||
Arc::new(SecretManagerState::default()),
|
||||
|
|
@ -364,7 +364,7 @@ async fn azure_oidc_acquires_the_requested_scope_and_preserves_failures(#[case]
|
|||
#[tokio::test]
|
||||
async fn missing_oidc_environment_is_an_error(#[case] reference: &str) {
|
||||
assert!(matches!(
|
||||
OidcResolver::new(litellm_http::Client::plain_for_test())
|
||||
OidcResolver::new(litellm_http::Client::for_test())
|
||||
.resolve(reference, environment(&[]).as_ref())
|
||||
.await,
|
||||
Err(Error::MissingEnvironment)
|
||||
|
|
@ -383,7 +383,7 @@ async fn google_oidc_failures_are_not_cached_or_hidden_by_defaults() {
|
|||
let resolver = SecretResolver::new_python_compatible(
|
||||
Arc::new(SecretManagerState::default()),
|
||||
environment(&[]),
|
||||
OidcResolver::new(litellm_http::Client::plain_for_test())
|
||||
OidcResolver::new(litellm_http::Client::for_test())
|
||||
.with_google_identity_endpoint(server.uri().parse().unwrap()),
|
||||
);
|
||||
for _ in 0..2 {
|
||||
|
|
@ -424,7 +424,7 @@ async fn google_tokens_expire_at_the_python_cache_deadline(
|
|||
.expect(2)
|
||||
.mount(&server)
|
||||
.await;
|
||||
let resolver = OidcResolver::new(litellm_http::Client::plain_for_test())
|
||||
let resolver = OidcResolver::new(litellm_http::Client::for_test())
|
||||
.with_google_identity_endpoint(server.uri().parse().unwrap())
|
||||
.with_clock(|| UNIX_EPOCH + Duration::from_secs(1000));
|
||||
assert_eq!(
|
||||
|
|
@ -477,7 +477,7 @@ async fn google_cache_uses_payload_expiry_without_requiring_a_jwt_header() {
|
|||
.expect(2)
|
||||
.mount(&server)
|
||||
.await;
|
||||
let resolver = OidcResolver::new(litellm_http::Client::plain_for_test())
|
||||
let resolver = OidcResolver::new(litellm_http::Client::for_test())
|
||||
.with_google_identity_endpoint(server.uri().parse().unwrap())
|
||||
.with_clock(|| UNIX_EPOCH + Duration::from_secs(1000));
|
||||
for _ in 0..2 {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ fn resolver(value: Option<&str>) -> SecretResolver {
|
|||
SecretResolver::new_python_compatible(
|
||||
Arc::new(SecretManagerState::default()),
|
||||
Arc::new(move |_: &str| value.clone()),
|
||||
OidcResolver::new(litellm_http::Client::plain_for_test()),
|
||||
OidcResolver::new(litellm_http::Client::for_test()),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ async fn native_reads_preserve_strings_and_report_conversion_errors(#[case] mana
|
|||
let resolver = SecretResolver::new(
|
||||
Arc::new(state),
|
||||
Arc::new(move |_: &str| Some(raw.to_owned())),
|
||||
OidcResolver::new(litellm_http::Client::plain_for_test()),
|
||||
OidcResolver::new(litellm_http::Client::for_test()),
|
||||
);
|
||||
assert_eq!(
|
||||
resolver
|
||||
|
|
@ -75,7 +75,7 @@ async fn native_defaults_apply_to_absence_but_never_hide_provider_failures() {
|
|||
KeyManagementSettings::default(),
|
||||
)),
|
||||
Arc::new(|_: &str| None),
|
||||
OidcResolver::new(litellm_http::Client::plain_for_test()),
|
||||
OidcResolver::new(litellm_http::Client::for_test()),
|
||||
);
|
||||
let result = resolver
|
||||
.get_secret_str("key", Some(SecretValue::new("default")))
|
||||
|
|
@ -189,7 +189,7 @@ fn managed(reply: Result<Option<Secret>, ()>, environment: Option<&'static str>)
|
|||
KeyManagementSettings::default(),
|
||||
)),
|
||||
Arc::new(move |_: &str| environment.map(str::to_owned)),
|
||||
OidcResolver::new(litellm_http::Client::plain_for_test()),
|
||||
OidcResolver::new(litellm_http::Client::for_test()),
|
||||
)
|
||||
.with_failure_policy(FailurePolicy::EnvironmentFallback)
|
||||
}
|
||||
|
|
@ -281,7 +281,7 @@ async fn prefix_is_removed_once_and_resolved_from_environment() {
|
|||
let resolver = SecretResolver::new_python_compatible(
|
||||
Arc::new(state),
|
||||
Arc::new(|name: &str| (name == "os.environ/KEY").then(|| "value".into())),
|
||||
OidcResolver::new(litellm_http::Client::plain_for_test()),
|
||||
OidcResolver::new(litellm_http::Client::for_test()),
|
||||
);
|
||||
assert_eq!(
|
||||
resolver
|
||||
|
|
@ -340,7 +340,7 @@ async fn excluded_hosted_keys_keep_the_python_manager_conversion_path(
|
|||
},
|
||||
)),
|
||||
Arc::new(move |_: &str| Some(raw.to_owned())),
|
||||
OidcResolver::new(litellm_http::Client::plain_for_test()),
|
||||
OidcResolver::new(litellm_http::Client::for_test()),
|
||||
);
|
||||
assert_eq!(
|
||||
resolver.get_secret("KEY", None).await.unwrap(),
|
||||
|
|
@ -373,7 +373,7 @@ async fn azure_callback_absence_preserves_none_but_errors_fall_back(
|
|||
KeyManagementSettings::default(),
|
||||
)),
|
||||
Arc::new(|_: &str| Some("environment".into())),
|
||||
OidcResolver::new(litellm_http::Client::plain_for_test()),
|
||||
OidcResolver::new(litellm_http::Client::for_test()),
|
||||
);
|
||||
assert_eq!(
|
||||
resolver
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ mod tests {
|
|||
#[case] expected: Option<&str>,
|
||||
) {
|
||||
unsafe { std::env::set_var(name, value) };
|
||||
let secret = EnvironmentSecrets::python_compatible(litellm_http::Client::plain_for_test())
|
||||
let secret = EnvironmentSecrets::python_compatible(litellm_http::Client::for_test())
|
||||
.resolve(&[name])
|
||||
.await
|
||||
.unwrap()
|
||||
|
|
@ -42,7 +42,7 @@ async fn dynamic_names_use_the_same_resolver_and_snapshots_never_do_fresh_lookup
|
|||
reads.fetch_add(1, Ordering::SeqCst);
|
||||
(name != "missing").then(|| name.to_owned())
|
||||
}),
|
||||
OidcResolver::new(litellm_http::Client::plain_for_test()),
|
||||
OidcResolver::new(litellm_http::Client::for_test()),
|
||||
);
|
||||
let snapshot = source.resolve(&["declared", "missing"]).await.unwrap();
|
||||
let name = format!("runtime-{}", "key");
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ async fn database() -> Database {
|
|||
7,
|
||||
)
|
||||
.unwrap(),
|
||||
client: Client::no_redirect_for_test(),
|
||||
client: Client::for_test(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ async fn spend_insert_controls_target_and_retry_settings() {
|
|||
.mount(&server)
|
||||
.await;
|
||||
let config = Config::new("spend_test".into(), &format!("{}?query=DROP&async_insert=0&wait_for_async_insert=0&input_format_skip_unknown_fields=1&database=wrong&readonly=1", server.uri()), 7).unwrap();
|
||||
let client = Client::no_redirect_for_test();
|
||||
let client = Client::for_test();
|
||||
let row = BTreeMap::from([
|
||||
("request_id".into(), json!("request")),
|
||||
("start_time".into(), json!(1234)),
|
||||
|
|
@ -77,7 +77,7 @@ async fn spend_insert_preserves_storage_failure(#[case] status: u16) {
|
|||
.await;
|
||||
let config = Config::new("spend_test".into(), &server.uri(), 7).unwrap();
|
||||
let error = insert_rows(
|
||||
&Client::no_redirect_for_test(),
|
||||
&Client::for_test(),
|
||||
config.storage().writer(),
|
||||
"spend_test",
|
||||
vec![BTreeMap::from([("request_id".into(), json!("request"))])],
|
||||
|
|
@ -95,7 +95,7 @@ async fn empty_spend_insert_does_not_contact_storage() {
|
|||
let server = MockServer::start().await;
|
||||
let config = Config::new("spend_test".into(), &server.uri(), 7).unwrap();
|
||||
insert_rows(
|
||||
&Client::no_redirect_for_test(),
|
||||
&Client::for_test(),
|
||||
config.storage().writer(),
|
||||
"spend_test",
|
||||
vec![],
|
||||
|
|
@ -116,7 +116,7 @@ async fn failed_schema_setup_is_reported() {
|
|||
.await;
|
||||
let config = Config::new("spend_test".into(), &server.uri(), 7).unwrap();
|
||||
assert!(matches!(
|
||||
ensure_schema(&Client::no_redirect_for_test(), &config).await,
|
||||
ensure_schema(&Client::for_test(), &config).await,
|
||||
Err(Error::Storage(
|
||||
litellm_storage_clickhouse::Error::SchemaFailed(403)
|
||||
))
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ async fn database() -> TestResult<ClickHouseDatabase> {
|
|||
Ok(ClickHouseDatabase {
|
||||
_container: container,
|
||||
url,
|
||||
client: Client::no_redirect_for_test(),
|
||||
client: Client::for_test(),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -244,7 +244,7 @@ async fn failed_migration_is_not_recorded_and_retains_storage_error(
|
|||
|
||||
#[rstest]
|
||||
fn invalid_database_identifier_is_rejected() {
|
||||
let client = Client::no_redirect_for_test();
|
||||
let client = Client::for_test();
|
||||
let connection = Connection::writer("http://127.0.0.1:1").expect("valid URL");
|
||||
assert!(matches!(
|
||||
ClickHouseMigrate::new(
|
||||
|
|
@ -327,7 +327,7 @@ async fn duplicate_ledger_rows_are_tolerated(
|
|||
#[rstest]
|
||||
#[tokio::test]
|
||||
async fn revert_reports_forward_only_error() {
|
||||
let client = Client::no_redirect_for_test();
|
||||
let client = Client::for_test();
|
||||
let connection = Connection::writer("http://127.0.0.1:1").expect("valid URL");
|
||||
let migration = migration(
|
||||
1,
|
||||
|
|
@ -369,7 +369,7 @@ async fn applied_int64_versions_accept_numeric_and_quoted_json(
|
|||
)
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
let client = Client::no_redirect_for_test();
|
||||
let client = Client::for_test();
|
||||
let connection = Connection::writer(&mock_server.uri()).expect("valid URL");
|
||||
let migrator = migrator(vec![]);
|
||||
let mut adapter = ClickHouseMigrate::new(
|
||||
|
|
@ -406,7 +406,7 @@ async fn schema_requests_override_unsafe_connection_settings(
|
|||
mock_server.uri()
|
||||
);
|
||||
execute_statement(
|
||||
&Client::no_redirect_for_test(),
|
||||
&Client::for_test(),
|
||||
&Connection::writer(&url).expect("valid URL"),
|
||||
"CREATE DATABASE IF NOT EXISTS trace_test",
|
||||
REQUEST_TIMEOUT,
|
||||
|
|
@ -445,7 +445,7 @@ async fn oversized_ledger_response_is_rejected_before_migrations(
|
|||
)
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
let client = Client::no_redirect_for_test();
|
||||
let client = Client::for_test();
|
||||
let connection = Connection::writer(&mock_server.uri()).expect("valid URL");
|
||||
let migrator = migrator(vec![]);
|
||||
let mut adapter = ClickHouseMigrate::new(
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ async fn insert_rejects_invalid_identifiers(
|
|||
#[case] table: &str,
|
||||
#[case] invalid_database: bool,
|
||||
) {
|
||||
let client = Client::no_redirect_for_test();
|
||||
let client = Client::for_test();
|
||||
let connection = Connection::writer("http://localhost:8123").expect("valid URL");
|
||||
let result = insert_encoded_rows(&client, &connection, database, table, "token", "{}").await;
|
||||
|
||||
|
|
@ -24,7 +24,7 @@ async fn insert_rejects_invalid_identifiers(
|
|||
#[rstest]
|
||||
#[tokio::test]
|
||||
async fn read_rejects_empty_sql() {
|
||||
let client = Client::no_redirect_for_test();
|
||||
let client = Client::for_test();
|
||||
let connection = Connection::reader("http://localhost:8123", "litellm").expect("valid URL");
|
||||
|
||||
assert!(matches!(
|
||||
|
|
@ -87,7 +87,7 @@ async fn typed_fetch_encodes_parameters_and_validates_rows(
|
|||
.expect(2)
|
||||
.mount(&server)
|
||||
.await;
|
||||
let client = Client::no_redirect_for_test();
|
||||
let client = Client::for_test();
|
||||
let connection = Connection::parse(&server.uri()).unwrap();
|
||||
let params = QueryParams {
|
||||
signed: i64::MIN,
|
||||
|
|
@ -131,7 +131,7 @@ async fn server_result_limits_allow_smaller_pages_without_retrying_other_failure
|
|||
.await;
|
||||
let connection = Connection::parse(&server.uri()).unwrap();
|
||||
let error = execute_read(
|
||||
&Client::no_redirect_for_test(),
|
||||
&Client::for_test(),
|
||||
&connection,
|
||||
"SELECT 1",
|
||||
&BTreeMap::new(),
|
||||
|
|
@ -174,7 +174,7 @@ async fn insert_timeout_environment_child() {
|
|||
.mount(&server)
|
||||
.await;
|
||||
let result = insert_encoded_rows(
|
||||
&Client::no_redirect_for_test(),
|
||||
&Client::for_test(),
|
||||
&Connection::parse(&server.uri()).unwrap(),
|
||||
"traces",
|
||||
"otel_traces",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue