@@ -643,7 +643,12 @@ fn validate_required_protocol_meta(
643643 . into ( ) )
644644}
645645
646- fn jsonrpc_http_status ( message : & ServerJsonRpcMessage ) -> http:: StatusCode {
646+ /// `request_meta_malformed` marks a request missing required `_meta` fields;
647+ /// only then is `-32602` a malformed-request 400 rather than an in-band error.
648+ fn jsonrpc_http_status (
649+ message : & ServerJsonRpcMessage ,
650+ request_meta_malformed : bool ,
651+ ) -> http:: StatusCode {
647652 let ServerJsonRpcMessage :: Error ( error) = message else {
648653 return http:: StatusCode :: OK ;
649654 } ;
@@ -652,6 +657,7 @@ fn jsonrpc_http_status(message: &ServerJsonRpcMessage) -> http::StatusCode {
652657 ErrorCode :: UNSUPPORTED_PROTOCOL_VERSION
653658 | ErrorCode :: MISSING_REQUIRED_CLIENT_CAPABILITY
654659 | ErrorCode :: HEADER_MISMATCH => http:: StatusCode :: BAD_REQUEST ,
660+ ErrorCode :: INVALID_PARAMS if request_meta_malformed => http:: StatusCode :: BAD_REQUEST ,
655661 ErrorCode :: METHOD_NOT_FOUND => http:: StatusCode :: NOT_FOUND ,
656662 _ => http:: StatusCode :: OK ,
657663 }
@@ -674,31 +680,39 @@ mod jsonrpc_http_status_tests {
674680 #[ test]
675681 fn header_mismatch_maps_to_bad_request ( ) {
676682 assert_eq ! (
677- jsonrpc_http_status( & error_message( ErrorCode :: HEADER_MISMATCH ) ) ,
683+ jsonrpc_http_status( & error_message( ErrorCode :: HEADER_MISMATCH ) , false ) ,
678684 http:: StatusCode :: BAD_REQUEST
679685 ) ;
680686 }
681687
682688 #[ test]
683689 fn method_not_found_maps_to_not_found ( ) {
684690 assert_eq ! (
685- jsonrpc_http_status( & error_message( ErrorCode :: METHOD_NOT_FOUND ) ) ,
691+ jsonrpc_http_status( & error_message( ErrorCode :: METHOD_NOT_FOUND ) , false ) ,
686692 http:: StatusCode :: NOT_FOUND
687693 ) ;
688694 }
689695
690696 #[ test]
691- fn invalid_params_maps_to_ok ( ) {
697+ fn invalid_params_for_malformed_request_meta_maps_to_bad_request ( ) {
692698 assert_eq ! (
693- jsonrpc_http_status( & error_message( ErrorCode :: INVALID_PARAMS ) ) ,
699+ jsonrpc_http_status( & error_message( ErrorCode :: INVALID_PARAMS ) , true ) ,
700+ http:: StatusCode :: BAD_REQUEST
701+ ) ;
702+ }
703+
704+ #[ test]
705+ fn invalid_params_for_well_formed_request_meta_maps_to_ok ( ) {
706+ assert_eq ! (
707+ jsonrpc_http_status( & error_message( ErrorCode :: INVALID_PARAMS ) , false ) ,
694708 http:: StatusCode :: OK
695709 ) ;
696710 }
697711
698712 #[ test]
699713 fn unmapped_error_defaults_to_ok ( ) {
700714 assert_eq ! (
701- jsonrpc_http_status( & error_message( ErrorCode :: INTERNAL_ERROR ) ) ,
715+ jsonrpc_http_status( & error_message( ErrorCode :: INTERNAL_ERROR ) , false ) ,
702716 http:: StatusCode :: OK
703717 ) ;
704718 }
@@ -799,13 +813,8 @@ mod standard_header_init_tests {
799813
800814fn jsonrpc_message_response (
801815 message : ServerJsonRpcMessage ,
802- map_protocol_status : bool ,
816+ status : http :: StatusCode ,
803817) -> HttpResult < BoxResponse > {
804- let status = if map_protocol_status {
805- jsonrpc_http_status ( & message)
806- } else {
807- http:: StatusCode :: OK
808- } ;
809818 let body =
810819 serde_json:: to_vec ( & message) . map_err ( internal_error_response ( "serialize json response" ) ) ?;
811820 Ok ( Response :: builder ( )
@@ -1526,6 +1535,11 @@ where
15261535 mut request : crate :: model:: JsonRpcRequest < ClientRequest > ,
15271536 parts : http:: request:: Parts ,
15281537 ) -> HttpResult < BoxResponse > {
1538+ let request_meta_malformed = !request
1539+ . request
1540+ . get_meta ( )
1541+ . missing_required_keys ( & ProtocolVersion :: V_2026_07_28 )
1542+ . is_empty ( ) ;
15291543 let peer_info = Self :: peer_info_for_stateless_request ( & request, & parts. headers ) ;
15301544 request. request . extensions_mut ( ) . insert ( parts) ;
15311545 let ( transport, mut receiver) =
@@ -1570,17 +1584,16 @@ where
15701584 & first,
15711585 ServerJsonRpcMessage :: Response ( _) | ServerJsonRpcMessage :: Error ( _)
15721586 ) ;
1573- if terminal
1574- && ( self . config . json_response || jsonrpc_http_status ( & first) != http:: StatusCode :: OK )
1575- {
1587+ let status = jsonrpc_http_status ( & first, request_meta_malformed) ;
1588+ if terminal && ( self . config . json_response || status != http:: StatusCode :: OK ) {
15761589 // This message is the whole reply, so `receiver` is dropped here and
15771590 // anything the handler emits afterwards is undeliverable. Cancel it so
15781591 // a still-running handler stops instead of running on unobserved: its
15791592 // terminal `send` would otherwise fail before adding the termination
15801593 // permit, leaving the serve loop parked forever. A no-op when the
15811594 // handler already completed.
15821595 request_ct. cancel ( ) ;
1583- return jsonrpc_message_response ( first, true ) ;
1596+ return jsonrpc_message_response ( first, status ) ;
15841597 }
15851598
15861599 Ok ( self . stateless_sse_response ( Some ( first) , receiver, request_ct) )
0 commit comments