fix: validate HTTPS binding limits and response ordering

This commit is contained in:
2026-09-30 06:43:02 +09:00
parent 56923c1160
commit beeffae9c5
5 changed files with 115 additions and 44 deletions
+49
View File
@@ -165,6 +165,55 @@ fn top_level_batch_errors_use_the_batch_allowed_code_set() {
));
}
#[test]
fn unsupported_batch_descriptor_waits_for_envelope_correlation() {
let duplicate = wip_https::http::Response::builder()
.status(StatusCode::OK)
.header("content-type", "application/json; charset=utf-8")
.body(
br#"{"responses":[{"id":"interface","result":{"interface":"interface-v1","descriptor":{"format":"wip-interface/2","future":true}}},{"id":"interface","result":{"interface":"interface-v1","descriptor":{"format":"wip-interface/2"}}}]}"#
.to_vec(),
)
.unwrap();
assert!(matches!(
decode_batch_response(&request(), &duplicate, limits()).unwrap_err(),
ClientResponseError::InvalidResponse {
kind: InvalidResponseKind::InvalidBatch,
..
}
));
let missing = wip_https::http::Response::builder()
.status(StatusCode::OK)
.header("content-type", "application/json; charset=utf-8")
.body(
br#"{"responses":[{"id":"interface","result":{"interface":"interface-v1","descriptor":{"format":"wip-interface/2"}}}]}"#
.to_vec(),
)
.unwrap();
assert!(matches!(
decode_batch_response(&request(), &missing, limits()).unwrap_err(),
ClientResponseError::InvalidResponse {
kind: InvalidResponseKind::InvalidBatch,
..
}
));
let request = BatchRequest {
requests: vec![BatchRequestItem {
id: "interface".into(),
request: BatchRequestKind::FetchInterface(FetchInterfaceRequest {
interface: "interface-v1".into(),
}),
}],
};
assert!(matches!(
decode_batch_response(&request, &missing, limits()).unwrap_err(),
ClientResponseError::UnsupportedDescriptorFormat { format }
if format == "wip-interface/2"
));
}
#[test]
fn batch_response_must_have_exactly_the_requested_ids() {
let request = request();
+40
View File
@@ -367,6 +367,27 @@ fn caller_limits_bound_bytes_and_nesting() {
let nested = br#"{"path":[[["/"]]]}"#;
let nesting_limited = Limits::new(1024, 1024, 2, 1).unwrap();
assert!(decode_fetch_request(nested, nesting_limited).is_err());
let outbound_limited = Limits::new(1_000_000, 1_000_000, 1, 10).unwrap();
assert!(
encode_call_operation_request(
&endpoint(),
&call_request(),
&descriptor(),
outbound_limited,
)
.is_err()
);
assert!(
encode_fetch_response(
&FetchRequest {
path: "/item".into(),
},
&object("item", b"validator"),
outbound_limited,
)
.is_err()
);
}
#[test]
@@ -400,6 +421,25 @@ fn unsupported_descriptor_format_is_client_local() {
ClientResponseError::UnsupportedDescriptorFormat { format }
if format == "wip-interface/2"
));
for malformed in [
br#"{"interface":"wrong","descriptor":{"format":"wip-interface/2"}}"#.as_slice(),
br#"{"interface":"interface-v1","descriptor":{"format":"wip-interface/2"},"validator":null}"#
.as_slice(),
] {
let response = wip_https::http::Response::builder()
.status(StatusCode::OK)
.header("content-type", "application/json; charset=utf-8")
.body(malformed.to_vec())
.unwrap();
assert!(matches!(
decode_fetch_interface_response(&request, &response, limits()).unwrap_err(),
ClientResponseError::InvalidResponse {
kind: InvalidResponseKind::InvalidSuccessBody,
..
}
));
}
}
#[test]