softwaremill / elasticmq

In-memory message queue with an Amazon SQS-compatible interface. Runs stand-alone or embedded.
https://softwaremill.com/open-source/
Apache License 2.0
2.53k stars 193 forks source link

"MD5 returned by SQS does not match the calculation on the original request" when using AWS JSON protocol and message attributes with custom data types #947

Closed mgocd closed 8 months ago

mgocd commented 8 months ago

Description

When receiving a SQS message from ElasticMQ with an attribute with a custom data type (docs) using AWS JSON protocol (AWS Java SDK v1 >= 1.12.584 / v2 >= 2.21.19), the following exception is thrown:

com.amazonaws.AmazonClientException: MD5 returned by SQS does not match the calculation on the original request. (MD5 calculated by the message attributes: "b6ba7933bdd4077bb2cc8686b0146cfa", MD5 checksum returned: "6735a2d7fe7f0e962a51db579c2d92cb")
    at com.amazonaws.services.sqs.MessageMD5ChecksumHandler.receiveMessageResultMd5Check(MessageMD5ChecksumHandler.java:146)
    at com.amazonaws.services.sqs.MessageMD5ChecksumHandler.afterResponse(MessageMD5ChecksumHandler.java:87)
    at com.amazonaws.handlers.RequestHandler2Adaptor.afterResponse(RequestHandler2Adaptor.java:49)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.afterResponse(AmazonHttpClient.java:1070)
...
        at com.amazonaws.services.sqs.AmazonSQSClient.receiveMessage(AmazonSQSClient.java:2339)

An example message with a custom data type when the error occurs:

var request = new SendMessageRequest(
                getQueueUrl(endpoint),
                "msg"
        );
request.setMessageAttributes(Map.of(
        "timestamp", new MessageAttributeValue()
                .withStringValue("1")
                .withDataType("Number.java.lang.Long")

Minimal reproducible example (Java): https://github.com/mgocd/elasticmq-custom-attribute-data-type-issue ElasticMQ version: 1.5.4

Analysis

This happens because MessageAttributeSupport ignores custom data types when serializing to JSON (so Number.java.lang.Long becomes Number), while SQSRestServerBuilder#md5AttributeDigest calculates MD5 digest correctly using the custom data type (Number.java.lang.Long).

Proposed solution

MessageAttributesSupport should use the custom data type when serializing to JSON.

A pull request has been proposed to fix the issue.

micossow commented 8 months ago

Released in v1.5.5