-
Notifications
You must be signed in to change notification settings - Fork 146
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Bugfix] Add base64 decode on json mashaller #330
[Bugfix] Add base64 decode on json mashaller #330
Conversation
// When encoding json, BinaryValue([]byte) are automatically converted to base64. | ||
binary, _ := base64.StdEncoding.DecodeString(attr.Value.BinaryValue) | ||
m.MessageAttributes[attr.Name] = sqstypes.MessageAttributeValue{ | ||
DataType: &attr.Value.DataType, | ||
StringValue: &attr.Value.StringValue, | ||
BinaryValue: []byte(attr.Value.BinaryValue), | ||
StringValue: attr.Value.StringValue, | ||
BinaryValue: binary, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is the key change of this PR.
encoding/json
lib automatically applies base 64 encode if the arg type is slice
.
But our internal MessageAttributeValue.BinaryValue
is already base 64 encoded string.
So the base64 encode was done "twice".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need some more information about what's going on here. I don't really mind not encoding this, but I've gotten several complaints about the MessageAttributes in the last week or so and I need to be more careful about it.
Can you explain more about what the issue is that you found, and how this will solve it? Also the below if you know:
-
When did the
[]byte
get encoded to begin with? If we're doing it internally, let's just avoid doing it at all, and let the marshallers handle it. -
It's been a minute since I looked at this, but why did we have to do the override of
MarshalJSON
period here? I see your comment about the structure, but I can't see why we needed an array to begin with. It seems to me like it comes in as a map inSendMessage
why not maintain the map format and not kill ourselves going back and forth? Was this to be compatible with legacy code some how? I know there's all this "convert to old style" stuff, but I sense that's the essence of a lot of these problems.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error we faced was like below:
com.amazonaws.AmazonClientException: MD5 returned by SQS does not match the calculation on the original request. (MD5 calculated by the message attributes: "565a1514fba6a202b2f3e2de433300cf", MD5 checksum returned: "1dffa6b307b25550e81d62cf3377dacd")
When did the []byte get encoded to begin with?
The base 64 encoding was performed by AWS SDK Client, and goaws preserves the base 64 encoded string received over HTTP for internal processing. So the value was already encoded at here.
It's been a minute since I looked at this, but why did we have to do the override of MarshalJSON period here?
It's unclear whether we can completely get rid of MarshalJSON while supporting both xml and json, but as you say, tackling the below "old style" TODO will help simplify the MessageAttributes processing.
https://github.com/Admiral-Piett/goaws/blob/master/app/utils/utils.go#L95
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, thanks for the extra info here. I wonder if we marked the inbound BinaryValue
fields as type []byte
the Marshaller would decode them for us on the way in, and all this would be obscured from us. I've always been confused about why it's not that type anyway, but as you say, I assume it's because we just carried the value around and we don't care much about what it is.
Did you happen to test that approach? If it's reasonable to implement it might make a lot of this easier to consume in the long term.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I'm digging into this now a little more thoroughly as a result of this issue - #328. I think I understand what is going on in here now a little more.
I think the overriding of the MarshalJSON
method this way ties our hands, and there's a lot of different "ResultMessageAttribute" VS "ResultAttribute"
stuff that makes this hard to consume. I'm going to work on tweaking this a little and seeing if I can bring this piece more in line with the other end points. Stand by!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, ok - I take it back. 🙃 . The message attributes are a real mess and our flexibility is all tied up in this pattern, and to fix my issue I'll have to rebuild it all.
If you, want I'll merge this unblock you if you're ready with all this, but I'm going to refactor the Message Attributes stuff now. That will be my next order of business. So after I do that, I'd appreciate it if you could smoke test it to make sure it still works for your team?
Thoughts on that plan?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK! We'd be happy to apply this change to resolve our block.
And of course, let me help you on the test with your refactoring on MessageAttributes! 💪 We can use our app and AWS SDK for Java.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I look into #328, this PR won't resolve the issue with only itself. But it is related with jackson-ize process with empty map in go 🤔 We may need to add a condition somewhere to prevent map from being made carelessly.
// check client md5hash and received md5hash | ||
hasher := md5.New() | ||
addBytesToHash(hasher, []byte("someKey")) | ||
addBytesToHash(hasher, []byte(*messageAttribute.DataType)) | ||
hasher.Write([]byte{2}) | ||
addBytesToHash(hasher, messageAttribute.BinaryValue) | ||
clientHash := hex.EncodeToString(hasher.Sum(nil)) | ||
|
||
assert.Equal(t, clientHash, *receiveMessageResponse.Messages[0].MD5OfMessageAttributes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added md5 hash assertion.
assert.Equal(t, "YmFzZTY0LWVuY29kZWQtdmFsdWU=", attr1.Value.BinaryValue) // base64 encoded value | ||
assert.Equal(t, binaryValueString, attr1.Value.BinaryValue) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Through the AWS SDK we should receive the raw string instead of the base 64 encoded string.
Hi @Admiral-Piett we found another issue. Could you please check this? By the way, we found that this fix and the previous fix on nil check are all that is needed to be compatible with the latest AWS SDK for Java! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @kojisaikiAtSony - thanks for looking at this but I need some more info. See my response to your comment below.
Also, what's all this extra stuff if all we needed here was to make sure we're not double encoding something. Thanks!
// When encoding json, BinaryValue([]byte) are automatically converted to base64. | ||
binary, _ := base64.StdEncoding.DecodeString(attr.Value.BinaryValue) | ||
m.MessageAttributes[attr.Name] = sqstypes.MessageAttributeValue{ | ||
DataType: &attr.Value.DataType, | ||
StringValue: &attr.Value.StringValue, | ||
BinaryValue: []byte(attr.Value.BinaryValue), | ||
StringValue: attr.Value.StringValue, | ||
BinaryValue: binary, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need some more information about what's going on here. I don't really mind not encoding this, but I've gotten several complaints about the MessageAttributes in the last week or so and I need to be more careful about it.
Can you explain more about what the issue is that you found, and how this will solve it? Also the below if you know:
-
When did the
[]byte
get encoded to begin with? If we're doing it internally, let's just avoid doing it at all, and let the marshallers handle it. -
It's been a minute since I looked at this, but why did we have to do the override of
MarshalJSON
period here? I see your comment about the structure, but I can't see why we needed an array to begin with. It seems to me like it comes in as a map inSendMessage
why not maintain the map format and not kill ourselves going back and forth? Was this to be compatible with legacy code some how? I know there's all this "convert to old style" stuff, but I sense that's the essence of a lot of these problems.
StringValue string `xml:"StringValue,omitempty"` | ||
BinaryValue string `xml:"BinaryValue,omitempty"` | ||
DataType string `xml:"DataType,omitempty"` | ||
StringValue *string `xml:"StringValue,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry to miss the description of this change.
string
can't have "nil" value and it generates "StringValue": ""
definitely on JSON serialize.
AWS SDK for Java won't calculate "BinaryValue" if "StringValue" is not null on their md5 hash validation, so the validation will be failed definitely if a message attribute has "BinaryValue".
If you agree with all the above give us a rebase and we'll merge this? Then I think we can let this be the last thing to go into the |
Thank you for your accepting! We'll rebase soon 👍 |
9fd3026
to
b7a428e
Compare
b7a428e
to
8eae00f
Compare
Hi @Admiral-Piett , we rebased the branch and the tests passed in our local but Github action test looks failed. Could you please check it and merge this if there was no problem? |
@kojisaikiAtSony are you running your tests with a command like below? Make sure you try it with the
|
@Admiral-Piett We are using the below environments:
Do you have any thoughts on the difference with the Github Action? And, how is it on your local? |
@kojisaikiAtSony Sorry, I haven't had time to look into your test failings, but I will try to do that soon. As an alternative, and like I think we talked about, I finished what I think is a pretty good refactor on the MessageAttributes. I made a comment on PR for you to look at here - https://github.com/Admiral-Piett/goaws/pull/334/files#r1825116530, since I think that piece is the chunk that will really solve your issue. Essentially it gets us out of the business of needing it encoded or decoded and leaves all that to marshaller. It's pretty slick once we get the right type in place, and it just works. I also kind of flipped your MarshalJSON logic, to make the "special" handling for the XML only, hoping I can delete that some day. Let me know what you think about any or all of it! I'm happy to discuss. I can also build it for you if you want to test it before I merge it (and the model refactoring - they need to go together). Either way is fine with me, but if we don't decide to put it in v0.5.1 it'll definitely be in v0.5.2, so you'll get this sooner or later. :) |
@Admiral-Piett I confirmed #334 will be an alternative to this PR, so I will close this PR later. |
@kojisaikiAtSony Sounds good, if I missed some tests by all means let me know what you're thinking, or if you have tests handy I'm happy to include those too. Whatever works for you. Thanks again for working with me on all this! |
@kojisaikiAtSony 0.5.1 is out! Thanks again for all your help! |
I will add some tests for hash validation in separate PR. |
We found an issue with the binary handling of MessageAttributes.
It causes the md5 hash validation error with AWS SDK for Java. Surprisingly, AWS SDK for Go does not have the md5 hash validation...