Summary
When the schema-based client generator is enabled for smithy.protocols#rpcv2Cbor, a generated client can serialize a valid CBOR body but send the request to /.
The generated RPC v2 CBOR server expects the canonical route:
/service/PokemonService/operation/GetServerStatistics
The server therefore returns 404.
The legacy per-shape client generated from the same model sends the canonical route and successfully calls the same server. This isolates the problem to the schema-based client request path. It is not a general aws-smithy-cbor codec or server interoperability problem.
Environment
This was reproduced from PR #4721 at commit 043eae3c7.
git clone https://github.com/smithy-lang/smithy-rs.git
cd smithy-rs
gh pr checkout 4721
git checkout 043eae3c7
Reproduction branch
A complete reproduction, including the generated SDKs, adapted Pokémon server, and rpc-v2-cbor-cli, is available at: https://github.com/smithy-lang/smithy-rs/tree/fahadzub/4721-error
Change the Pokémon model to RPC v2 CBOR
codegen-core/common-test-models/pokemon.smithy
Replace the RestJson1 service protocol with RPC v2 CBOR and leave the service body unchanged:
-use aws.protocols#restJson1
+use smithy.protocols#rpcv2Cbor
-@restJson1
+@rpcv2Cbor
The existing operation-level @http traits can remain in the model. RPC v2 CBOR ignores those bindings and uses its canonical RPC route. Their presence is important to this reproduction because the schema request generator currently treats them as a reason to pass an empty endpoint to the runtime protocol.
Generate the client and server SDKs
The generated SDKs are copied to:
examples/pokemon-service-client
examples/pokemon-service-server-sdk
Required server example adaptations
1. Import runtime body types directly
The newly generated server SDK does not re-export ByteStream or SdkBody from pokemon_service_server_sdk::types.
Add this dependency to:
examples/pokemon-service-common/Cargo.toml
aws-smithy-types = { path = "../../rust-runtime/aws-smithy-types" }
Update the imports in:
examples/pokemon-service-common/src/lib.rs
use aws_smithy_types::{body::SdkBody, byte_stream::ByteStream};
use pokemon_service_server_sdk::{
error, input,
model::{self, CapturingPayload},
output,
server::Extension,
types::Blob,
};
2. Buffer the radio response into Blob
Replace the return construction in stream_pokemon_radio with:
let data = ByteStream::new(result.into_body())
.collect()
.await
.expect("failed to read radio stream")
.into_bytes();
output::StreamPokemonRadioOutput {
data: Blob::from_maybe_shared(data),
}
Confirm the server builds:
cd examples
cargo check --quiet -p pokemon-service-common
cargo check --quiet -p pokemon-service
Add the real RPC v2 CBOR CLI
Add the direct runtime protocol dependency to:
examples/pokemon-service-client-usage/Cargo.toml
aws-smithy-cbor = { path = "../../rust-runtime/aws-smithy-cbor" }
Create:
examples/pokemon-service-client-usage/examples/rpc-v2-cbor-cli.rs
use aws_smithy_cbor::protocol::RpcV2CborProtocol;
#[tokio::main]
async fn main() {
let config = pokemon_service_client::Config::builder()
.endpoint_url("http://localhost:13734")
.protocol(RpcV2CborProtocol::new())
.build();
let client = pokemon_service_client::Client::from_conf(config);
let result = client.get_server_statistics().send().await;
println!("result={result:#?}");
}
Confirm the CLI builds:
cd examples
cargo check -p pokemon-service-client-usage --example rpc-v2-cbor-cli
Start the server
Run the server in the first terminal:
cd examples
cargo run --bin pokemon-service
Leave this process running on 127.0.0.1:13734.
Invoke the server
Run the CLI in a second terminal:
cd examples
cargo run --quiet \
-p pokemon-service-client-usage \
--example rpc-v2-cbor-cli
Actual result
The request reaches the server, but the server returns 404:
result=Err(
ServiceError(
ServiceError {
source: Unhandled(...),
raw: Response {
status: StatusCode(
404,
),
headers: {
"content-type": "application/cbor",
"content-length": "0",
...
},
...
},
},
),
)
Expected result
result=Ok(
GetServerStatisticsOutput {
calls_count: 0,
},
)
The exact count can differ if the server has already handled requests.
Summary
When the schema-based client generator is enabled for
smithy.protocols#rpcv2Cbor, a generated client can serialize a valid CBOR body but send the request to/.The generated RPC v2 CBOR server expects the canonical route:
/service/PokemonService/operation/GetServerStatisticsThe server therefore returns
404.The legacy per-shape client generated from the same model sends the canonical route and successfully calls the same server. This isolates the problem to the schema-based client request path. It is not a general
aws-smithy-cborcodec or server interoperability problem.Environment
This was reproduced from PR
#4721at commit043eae3c7.git clone https://github.com/smithy-lang/smithy-rs.git cd smithy-rs gh pr checkout 4721 git checkout 043eae3c7Reproduction branch
A complete reproduction, including the generated SDKs, adapted Pokémon server, and
rpc-v2-cbor-cli, is available at: https://github.com/smithy-lang/smithy-rs/tree/fahadzub/4721-errorChange the Pokémon model to RPC v2 CBOR
codegen-core/common-test-models/pokemon.smithyReplace the RestJson1 service protocol with RPC v2 CBOR and leave the service body unchanged:
The existing operation-level
@httptraits can remain in the model. RPC v2 CBOR ignores those bindings and uses its canonical RPC route. Their presence is important to this reproduction because the schema request generator currently treats them as a reason to pass an empty endpoint to the runtime protocol.Generate the client and server SDKs
cd examples make codegenThe generated SDKs are copied to:
examples/pokemon-service-clientexamples/pokemon-service-server-sdkRequired server example adaptations
1. Import runtime body types directly
The newly generated server SDK does not re-export
ByteStreamorSdkBodyfrompokemon_service_server_sdk::types.Add this dependency to:
examples/pokemon-service-common/Cargo.tomlUpdate the imports in:
examples/pokemon-service-common/src/lib.rs2. Buffer the radio response into
BlobReplace the return construction in
stream_pokemon_radiowith:Confirm the server builds:
cd examples cargo check --quiet -p pokemon-service-common cargo check --quiet -p pokemon-serviceAdd the real RPC v2 CBOR CLI
Add the direct runtime protocol dependency to:
examples/pokemon-service-client-usage/Cargo.tomlCreate:
examples/pokemon-service-client-usage/examples/rpc-v2-cbor-cli.rsConfirm the CLI builds:
cd examples cargo check -p pokemon-service-client-usage --example rpc-v2-cbor-cliStart the server
Run the server in the first terminal:
cd examples cargo run --bin pokemon-serviceLeave this process running on
127.0.0.1:13734.Invoke the server
Run the CLI in a second terminal:
cd examples cargo run --quiet \ -p pokemon-service-client-usage \ --example rpc-v2-cbor-cliActual result
The request reaches the server, but the server returns
404:Expected result
The exact count can differ if the server has already handled requests.