@@ -660,15 +660,23 @@ def _get_error_message(self, error: Exception) -> str | None:
660660 def _get_error_status_code (
661661 self , error : ServiceException , headers : Headers , service_model : ServiceModel
662662 ) -> int :
663- return error .status_code
663+ # by default, some protocols (namely `json` and `smithy-rpc-v2-cbor`) might not define exception status code in
664+ # their specs, so they are not defined in the `ServiceException` object and will use the default value of `400`
665+ # But Query compatible service always do define them, so we get the wrong code for service that are
666+ # multi-protocols like CloudWatch
667+ # we need to verify if the service is compatible, and if the client has requested the query compatible error
668+ # code to return the right value
669+ if not service_model .is_query_compatible :
670+ return error .status_code
664671
665- def _get_error_code (
666- self ,
667- error : ServiceException ,
668- shape : StructureShape | None = None ,
669- is_query_compatible : bool = False ,
670- ) -> str :
671- return error .code
672+ if self ._is_request_query_compatible (headers ):
673+ return error .status_code
674+
675+ # we only want to override status code 4XX
676+ if 400 < error .status_code <= 499 :
677+ return 400
678+
679+ return error .status_code
672680
673681 def _is_request_query_compatible (self , headers : Headers ) -> bool :
674682 return headers .get ("x-amzn-query-mode" ) == "true"
@@ -1238,6 +1246,11 @@ def _prepare_additional_traits_in_xml(self, root: ETree.Element | None, request_
12381246 request_id_element = ETree .SubElement (response_metadata , "RequestId" )
12391247 request_id_element .text = request_id
12401248
1249+ def _get_error_status_code (
1250+ self , error : ServiceException , headers : Headers , service_model : ServiceModel
1251+ ) -> int :
1252+ return error .status_code
1253+
12411254
12421255class EC2ResponseSerializer (QueryResponseSerializer ):
12431256 """
@@ -1326,11 +1339,18 @@ def _serialize_error(
13261339 # com.amazon.coral.service#ExceptionName
13271340 # if json-1.1, it should only be the name
13281341
1329- # if the operation is query compatible, we need to add to use shape name
1330- # when we create `CommonServiceException` and they don't exist in the spec, we give already give the error name
1331- # as the exception code.
13321342 is_query_compatible = operation_model .service_model .is_query_compatible
1333- code = self ._get_error_code (error , shape , is_query_compatible )
1343+ # if the operation is query compatible, we need to add to use shape name
1344+ if is_query_compatible :
1345+ if shape :
1346+ code = shape .name
1347+ else :
1348+ # if the shape is not defined, we are using the Exception named to derive the `Code`, like you would
1349+ # from the shape. This allows us to have Exception that are valid in multi-protocols by defining its
1350+ # code and its name to be different
1351+ code = error .__class__ .__name__
1352+ else :
1353+ code = error .code
13341354
13351355 response .headers ["X-Amzn-Errortype" ] = code
13361356
@@ -1504,44 +1524,6 @@ def _prepare_additional_traits_in_response(
15041524 )
15051525 return response
15061526
1507- def _get_error_code (
1508- self ,
1509- error : ServiceException ,
1510- shape : StructureShape | None = None ,
1511- is_query_compatible : bool = False ,
1512- ) -> str :
1513- # TODO: explain
1514- if is_query_compatible :
1515- if shape :
1516- code = shape .name
1517- else :
1518- code = error .__class__ .__name__
1519- else :
1520- code = error .code
1521-
1522- return code
1523-
1524- def _get_error_status_code (
1525- self , error : ServiceException , headers : Headers , service_model : ServiceModel
1526- ) -> int :
1527- # by default, `json` services might not define exception status code, so they are not defined in the exception
1528- # object and will use the default value of `400`
1529- # But Query compatible service always do define them, so we get the wrong code for service that are
1530- # multi-protocols like CloudWatch
1531- # we need to verify if the service is compatible, and if the client has requested the query compatible error
1532- # code
1533- if not service_model .is_query_compatible :
1534- return error .status_code
1535-
1536- if self ._is_request_query_compatible (headers ):
1537- return error .status_code
1538-
1539- # we only want to override status code 4XX
1540- if 400 < error .status_code <= 499 :
1541- return 400
1542-
1543- return error .status_code
1544-
15451527
15461528class RestJSONResponseSerializer (BaseRestResponseSerializer , JSONResponseSerializer ):
15471529 """
@@ -1987,7 +1969,17 @@ def _serialize_error(
19871969 # Responses for the rpcv2Cbor protocol SHOULD NOT contain the X-Amzn-ErrorType header.
19881970 # Type information is always serialized in the payload. This is different from the `json` protocol
19891971 is_query_compatible = operation_model .service_model .is_query_compatible
1990- code = self ._get_error_code (error , shape , is_query_compatible )
1972+ # if the operation is query compatible, we need to add to use shape name
1973+ if is_query_compatible :
1974+ if shape :
1975+ code = shape .name
1976+ else :
1977+ # if the shape is not defined, we are using the Exception named to derive the `Code`, like you would
1978+ # from the shape. This allows us to have Exception that are valid in multi-protocols by defining its
1979+ # code and its name to be different
1980+ code = error .__class__ .__name__
1981+ else :
1982+ code = error .code
19911983
19921984 if not shape :
19931985 shape_copy = DEFAULT_ERROR_STRUCTURE_SHAPE
@@ -2034,44 +2026,6 @@ def _prepare_additional_traits_in_response(
20342026 )
20352027 return response
20362028
2037- def _get_error_code (
2038- self ,
2039- error : ServiceException ,
2040- shape : StructureShape | None = None ,
2041- is_query_compatible : bool = False ,
2042- ) -> str :
2043- # TODO: explain
2044- if is_query_compatible :
2045- if shape :
2046- code = shape .name
2047- else :
2048- code = error .__class__ .__name__
2049- else :
2050- code = error .code
2051-
2052- return code
2053-
2054- def _get_error_status_code (
2055- self , error : ServiceException , headers : Headers , service_model : ServiceModel
2056- ) -> int :
2057- # by default, `json` services might not define exception status code, so they are not defined in the exception
2058- # object and will use the default value of `400`
2059- # But Query compatible service always do define them, so we get the wrong code for service that are
2060- # multi-protocols like CloudWatch
2061- # we need to verify if the service is compatible, and if the client has requested the query compatible error
2062- # code
2063- if not service_model .is_query_compatible :
2064- return error .status_code
2065-
2066- if self ._is_request_query_compatible (headers ):
2067- return error .status_code
2068-
2069- # we only want to override status code 4XX
2070- if 400 < error .status_code <= 499 :
2071- return 400
2072-
2073- return error .status_code
2074-
20752029
20762030class S3ResponseSerializer (RestXMLResponseSerializer ):
20772031 """
0 commit comments