{ match upstream_result { Ok(Ok(mut response)) => { if let Some(fallback) = execute_error_fallback( state.clone(), peer, local, &snapshot, &host, tls, route, response.status(), &fallback_request, &fallback_body, ).await { return fallback; } let (origin_validation_headers, origin_plan, origin_reason, mut response) = include!("success_prepare.rs"); include!("success_finish.rs") } Ok(Err(cause)) => { if let Some(session) = h2_direct_session.take() { session.cancellation().cancel(); } let elapsed = upstream_started.elapsed(); let connect_failure = cause.is_connect(); let detail = upstream_failure_detail(&cause, &active_backend, elapsed, connect_failure); let failure_class = upstream_health_error_class(&cause, connect_failure, &active_backend); let graceful_h2_close = matches!( failure_class, "h2_graceful_goaway" | "h2_graceful_close" ); if let Some(exchange) = &exchange { exchange.websocket_error("upstream_request_failed", "upstream_http_error"); *exchange.upstream_error.lock().unwrap_or_else(|e| e.into_inner()) = Some(detail.clone()); } if let Some(lease) = &active_lease { lease.error_detail(failure_class, &detail, final_attempt_elapsed); } if connect_failure { tracing::warn!( backend = %active_backend.id, origin = %active_backend.origin, request_origin = %active_backend.request_origin, tls_verify = active_backend.tls_verify, elapsed_ms = elapsed.as_millis(), error = %detail, "upstream connection failed" ); } else if graceful_h2_close { tracing::trace!( backend = %active_backend.id, origin = %active_backend.origin, elapsed_ms = elapsed.as_millis(), error = %detail, "upstream H2 graceful close left an unrecovered request" ); } else { tracing::debug!( backend = %active_backend.id, origin = %active_backend.origin, elapsed_ms = elapsed.as_millis(), error = %detail, "upstream HTTP request failed" ); } let status = if connect_failure { StatusCode::SERVICE_UNAVAILABLE } else { StatusCode::BAD_GATEWAY }; let stale_class = classify_stale_error(&cause); if cache_settings.allows_stale_error_class(stale_class) { if let Some(stale) = serve_stale("cache_stale_if_error", elapsed, &active_backend.id, None) { return stale; } } if let Some(fallback) = execute_error_fallback( state.clone(), peer, local, &snapshot, &host, tls, route, status, &fallback_request, &fallback_body, ).await { return fallback; } let mut response = error( status, if status == StatusCode::SERVICE_UNAVAILABLE { "RustProxy: upstream unavailable (DNS, TCP or TLS connection failed)\n" } else { "RustProxy: upstream did not provide a valid HTTP response\n" }, ); response .headers_mut() .insert("cache-control", HeaderValue::from_static("no-store")); if status == StatusCode::SERVICE_UNAVAILABLE { response .headers_mut() .insert("retry-after", HeaderValue::from_static("1")); } response } Err(_) => { if let Some(session) = h2_direct_session.take() { session.cancellation().cancel(); } if let Some(exchange) = &exchange { exchange.websocket_error("upstream_timeout", "header_timeout"); *exchange.upstream_error.lock().unwrap_or_else(|e| e.into_inner()) = Some("response_header_timeout".into()); } if let Some(lease) = &active_lease { lease.error_detail( "response_header_timeout", "response_header_timeout", final_attempt_elapsed, ); } if cache_settings .allows_stale_error_class(crate::cache::StaleErrorClass::Timeout) { if let Some(stale) = serve_stale("cache_stale_if_error", upstream_started.elapsed(), &active_backend.id, None) { return stale; } } if let Some(fallback) = execute_error_fallback( state.clone(), peer, local, &snapshot, &host, tls, route, StatusCode::GATEWAY_TIMEOUT, &fallback_request, &fallback_body, ).await { return fallback; } error( StatusCode::GATEWAY_TIMEOUT, "RustProxy: upstream response deadline exceeded\n", ) } } }