mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-06 02:48:13 +00:00
* refactor(rust): standardize Azure Messages module path * docs(rust): define shared types crate boundaries * refactor(rust): share request helpers and type Anthropic blocks * docs(rust): format shared type invariants as bullets * test(rust): parameterize repeated cases with rstest * refactor(rust): move Responses transform result into llms * fix(anthropic): validate chat and batch responses * docs(rust): clarify API format ownership boundaries * docs: clarify Rust error message construction * refactor(auth): keep shared Rust errors provider-neutral * refactor(rust): separate format contracts from provider policy * fix(rust): type Anthropic chat response text collection * fix(rust): pass audio secret sources through hosts * fix(rust): unblock batch lint and OCR error assertions * test(rust): assert response failures at the adapter boundary * refactor(rust): declare error messages with typed context * wip * fix(rust): adapt Bedrock error details * style(rust): cargo fmt bedrock audio transcription Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix(rust): adapt tests and dead code to typed error details Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix(rust): keep converse error contracts and read env secrets without litellm Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * ci(rust): raise the native wheel size gate to 45 MB Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix(rust): tolerate missing usage in converse responses on the transcription route Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: Yujong Lee <yujong@berri.ai> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
59 lines
2 KiB
Rust
59 lines
2 KiB
Rust
use futures_util::{SinkExt, StreamExt};
|
|
use litellm_http::websocket::connect_upstream;
|
|
use rstest::rstest;
|
|
use tokio::net::TcpListener;
|
|
use tokio_tungstenite::{
|
|
accept_hdr_async,
|
|
tungstenite::{
|
|
Message,
|
|
client::IntoClientRequest,
|
|
handshake::server::{Request, Response},
|
|
},
|
|
};
|
|
|
|
#[rstest]
|
|
#[case::without_query("/responses")]
|
|
#[case::with_query("/responses?model=test-model")]
|
|
#[tokio::test]
|
|
async fn connects_with_caller_headers_and_exchanges_frames(#[case] path: &'static str) {
|
|
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
|
|
let address = listener.local_addr().unwrap();
|
|
let server = tokio::spawn(async move {
|
|
let (stream, _) = listener.accept().await.unwrap();
|
|
#[expect(
|
|
clippy::result_large_err,
|
|
reason = "tungstenite requires an unboxed handshake error response"
|
|
)]
|
|
let mut socket = accept_hdr_async(stream, move |request: &Request, response: Response| {
|
|
assert_eq!(request.uri().path_and_query().unwrap().as_str(), path);
|
|
assert_eq!(request.headers()["authorization"], "Bearer test-key");
|
|
Ok(response)
|
|
})
|
|
.await
|
|
.unwrap();
|
|
assert_eq!(
|
|
socket.next().await.unwrap().unwrap(),
|
|
Message::Text("request".into())
|
|
);
|
|
socket.send(Message::Text("response".into())).await.unwrap();
|
|
socket.close(None).await.unwrap();
|
|
});
|
|
let mut request = format!("ws://{address}{path}")
|
|
.into_client_request()
|
|
.unwrap();
|
|
request
|
|
.headers_mut()
|
|
.insert("authorization", "Bearer test-key".parse().unwrap());
|
|
let (mut socket, response) = connect_upstream(request).await.unwrap();
|
|
assert_eq!(response.status(), 101);
|
|
socket.send(Message::Text("request".into())).await.unwrap();
|
|
assert_eq!(
|
|
socket.next().await.unwrap().unwrap(),
|
|
Message::Text("response".into())
|
|
);
|
|
assert!(matches!(
|
|
socket.next().await.unwrap().unwrap(),
|
|
Message::Close(_)
|
|
));
|
|
server.await.unwrap();
|
|
}
|