fix(https): align canonical binding semantics

This commit is contained in:
2026-09-30 07:50:51 +09:00
parent beeffae9c5
commit 625f4c148d
9 changed files with 669 additions and 109 deletions
+48 -7
View File
@@ -9,11 +9,12 @@ use wip_https::wip_protocol::{
TypeDeclaration, TypeExpr, UnionCase, Value,
};
use wip_https::{
ClientResponseError, DecodedResponse, Endpoint, InvalidResponseKind, Limits,
decode_call_operation_metadata, decode_call_operation_request, decode_call_operation_response,
decode_fetch_interface_request, decode_fetch_interface_response, decode_fetch_request,
decode_fetch_response, decode_fetch_tree_request, decode_fetch_tree_response,
encode_call_operation_request, encode_call_operation_response, encode_fetch_interface_request,
ClientResponseError, CodecError, DecodedResponse, Endpoint, InvalidResponseKind, Limits,
ResourceLimitKind, decode_call_operation_metadata, decode_call_operation_request,
decode_call_operation_response, decode_fetch_interface_request,
decode_fetch_interface_response, decode_fetch_request, decode_fetch_response,
decode_fetch_tree_request, decode_fetch_tree_response, encode_call_operation_request,
encode_call_operation_response, encode_fetch_interface_request,
encode_fetch_interface_response, encode_fetch_request, encode_fetch_response,
encode_fetch_tree_request, encode_fetch_tree_response,
};
@@ -193,6 +194,36 @@ fn call_request() -> CallOperationRequest {
}
}
#[test]
fn every_single_interaction_request_accepts_json() {
let fetch =
encode_fetch_request(&endpoint(), &FetchRequest { path: "/".into() }, limits()).unwrap();
let fetch_tree = encode_fetch_tree_request(
&endpoint(),
&FetchTreeRequest {
path: "/".into(),
depth: 1,
limit: 1,
},
limits(),
)
.unwrap();
let fetch_interface = encode_fetch_interface_request(
&endpoint(),
&FetchInterfaceRequest {
interface: "interface-v1".into(),
},
limits(),
)
.unwrap();
let call = encode_call_operation_request(&endpoint(), &call_request(), &descriptor(), limits())
.unwrap();
for request in [fetch, fetch_tree, fetch_interface, call] {
assert_eq!(request.headers()["accept"], "application/json");
}
}
#[test]
fn fetch_round_trips_direct_body_and_body_validator() {
let request = FetchRequest {
@@ -362,11 +393,21 @@ fn malformed_unknown_null_and_noncanonical_base64_are_rejected() {
#[test]
fn caller_limits_bound_bytes_and_nesting() {
let tiny = Limits::new(8, 8, 2, 1).unwrap();
assert!(decode_fetch_request(br#"{"path":"/long"}"#, tiny).is_err());
let too_large = decode_fetch_request(br#"{"path":"/long"}"#, tiny).unwrap_err();
assert!(matches!(&too_large, CodecError::BodyTooLarge { .. }));
assert_eq!(
too_large.resource_limit_kind(),
Some(ResourceLimitKind::RepresentationBytes)
);
let nested = br#"{"path":[[["/"]]]}"#;
let nesting_limited = Limits::new(1024, 1024, 2, 1).unwrap();
assert!(decode_fetch_request(nested, nesting_limited).is_err());
let too_deep = decode_fetch_request(nested, nesting_limited).unwrap_err();
assert!(matches!(&too_deep, CodecError::NestingTooDeep { .. }));
assert_eq!(
too_deep.resource_limit_kind(),
Some(ResourceLimitKind::Logical)
);
let outbound_limited = Limits::new(1_000_000, 1_000_000, 1, 10).unwrap();
assert!(