Execute a fully-built streaming request body (sets `stream: true`).
(
&self,
mut request_body: serde_json::Value,
cancel_token: CancellationToken,
)
| 325 | impl AnthropicClient { |
| 326 | /// Execute a fully-built streaming request body (sets `stream: true`). |
| 327 | async fn send_streaming( |
| 328 | &self, |
| 329 | mut request_body: serde_json::Value, |
| 330 | cancel_token: CancellationToken, |
| 331 | ) -> Result<mpsc::Receiver<StreamEvent>> { |
| 332 | { |
| 333 | let request_started_at = Instant::now(); |
| 334 | request_body["stream"] = serde_json::json!(true); |
| 335 | |
| 336 | let url = format!("{}/v1/messages", self.base_url); |
| 337 | |
| 338 | let headers = vec![ |
| 339 | ("x-api-key", self.api_key.expose()), |
| 340 | ("anthropic-version", "2023-06-01"), |
| 341 | ("anthropic-beta", "prompt-caching-2024-07-31"), |
| 342 | ]; |
| 343 | |
| 344 | let streaming_resp = crate::retry::with_retry(&self.retry_config, |_attempt| { |
| 345 | let http = &self.http; |
| 346 | let url = &url; |
| 347 | let headers = headers.clone(); |
| 348 | let request_body = &request_body; |
| 349 | let cancel_token = cancel_token.clone(); |
| 350 | async move { |
| 351 | let resp = tokio::select! { |
| 352 | _ = cancel_token.cancelled() => { |
| 353 | return AttemptOutcome::Fatal(anyhow::anyhow!("HTTP request cancelled")); |
| 354 | } |
| 355 | result = http.post_streaming(url, headers, request_body, cancel_token.clone()) => { |
| 356 | match result { |
| 357 | Ok(r) => r, |
| 358 | Err(e) => { |
| 359 | // A transient network error (timeout, reset, |
| 360 | // mid-flight drop — common on throttled |
| 361 | // endpoints) carries no HTTP status. Retry it |
| 362 | // with backoff like 429/5xx instead of failing |
| 363 | // the turn; a real fatal error still bails. |
| 364 | return if crate::retry::is_transient_error(&e) { |
| 365 | AttemptOutcome::Retryable { |
| 366 | status: reqwest::StatusCode::SERVICE_UNAVAILABLE, |
| 367 | body: format!("network error: {e}"), |
| 368 | retry_after: None, |
| 369 | } |
| 370 | } else { |
| 371 | AttemptOutcome::Fatal(anyhow::anyhow!( |
| 372 | "HTTP request failed: {}", |
| 373 | e |
| 374 | )) |
| 375 | }; |
| 376 | } |
| 377 | } |
| 378 | } |
| 379 | }; |
| 380 | let status = reqwest::StatusCode::from_u16(resp.status) |
| 381 | .unwrap_or(reqwest::StatusCode::INTERNAL_SERVER_ERROR); |
| 382 | if status.is_success() { |
| 383 | AttemptOutcome::Success(resp) |
| 384 | } else { |
no test coverage detected