From f28e33dc48cd96f9d7a28c6aeba40459545c73fe Mon Sep 17 00:00:00 2001 From: Andrew Yuan Date: Wed, 13 May 2026 13:11:16 -0400 Subject: [PATCH 1/2] random change to run CI... --- .github/workflows/per-pr.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/per-pr.yml b/.github/workflows/per-pr.yml index 6dc34be07..775d54622 100644 --- a/.github/workflows/per-pr.yml +++ b/.github/workflows/per-pr.yml @@ -6,6 +6,7 @@ on: # rebuild any PRs and main branch changes branches: - master + permissions: contents: read actions: write From 7d35649465c8f948f596d3e7845633b596448beb Mon Sep 17 00:00:00 2001 From: Andrew Yuan Date: Tue, 12 May 2026 17:18:18 -0400 Subject: [PATCH 2/2] Add grpc-status trailers to fake gRPC responses (#1257) --- crates/client/src/callback_based.rs | 5 ++++- .../sdk-core/tests/integ_tests/client_tests.rs | 18 +++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/crates/client/src/callback_based.rs b/crates/client/src/callback_based.rs index 364b7dc14..b0e0db5b4 100644 --- a/crates/client/src/callback_based.rs +++ b/crates/client/src/callback_based.rs @@ -4,7 +4,7 @@ use anyhow::anyhow; use bytes::{BufMut, BytesMut}; use futures_util::{future::BoxFuture, stream}; -use http::{HeaderMap, Request, Response}; +use http::{HeaderMap, HeaderValue, Request, Response}; use http_body_util::{BodyExt, StreamBody, combinators::BoxBody}; use hyper::body::{Bytes, Frame}; use std::{ @@ -104,9 +104,12 @@ impl Service> for CallbackBasedGrpcService { let mut body_prepend = BytesMut::with_capacity(5); body_prepend.put_u8(0); // 0 means no compression body_prepend.put_u32(success.proto.len() as u32); + let mut trailers = HeaderMap::new(); + trailers.insert("grpc-status", HeaderValue::from_static("0")); let stream = stream::iter(vec![ Ok::<_, Status>(Frame::data(Bytes::from(body_prepend))), Ok::<_, Status>(Frame::data(Bytes::from(success.proto))), + Ok::<_, Status>(Frame::trailers(trailers)), ]); let stream_body = StreamBody::new(stream); let full_body = BoxBody::new(stream_body).boxed(); diff --git a/crates/sdk-core/tests/integ_tests/client_tests.rs b/crates/sdk-core/tests/integ_tests/client_tests.rs index 259ca2ff4..020a80dae 100644 --- a/crates/sdk-core/tests/integ_tests/client_tests.rs +++ b/crates/sdk-core/tests/integ_tests/client_tests.rs @@ -5,8 +5,12 @@ use crate::common::{ http_proxy::HttpProxy, }; use assert_matches::assert_matches; -use futures_util::FutureExt; -use http_body_util::Full; +use futures_util::{FutureExt, stream}; +use http_body_util::{BodyExt, StreamBody, combinators::BoxBody}; +use hyper::{ + body::{Bytes, Frame}, + http::{HeaderMap, HeaderValue}, +}; use prost::Message; use std::{ collections::HashMap, @@ -452,14 +456,18 @@ where .encode(&mut buf) .expect("failed to encode response message"); - // Props to o3-mini for giving me a cheap way to make a grpc response let mut frame = Vec::with_capacity(5 + buf.len()); frame.push(0); let len = buf.len() as u32; frame.extend_from_slice(&len.to_be_bytes()); frame.extend_from_slice(&buf); - let full_body = Full::new(frame.into()); - let body = Body::new(full_body); + let mut trailers = HeaderMap::new(); + trailers.insert("grpc-status", HeaderValue::from_static("0")); + let stream = stream::iter(vec![ + Ok::<_, Status>(Frame::data(Bytes::from(frame))), + Ok::<_, Status>(Frame::trailers(trailers)), + ]); + let body = Body::new(BoxBody::new(StreamBody::new(stream)).boxed()); // Build the HTTP response with the required gRPC headers. Response::builder()