Skip to content
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

Properly encode Uint8Array fields #23

Merged

Conversation

Unix4ever
Copy link
Contributor

Fixes: #22

Binary data should be represented as base64 encoded string in the JSON
encoded body.
Use replacer to return base64 encoded string when Uint8Array type is
detected.

Signed-off-by: Artem Chernyshev artem.0xD2@gmail.com

@google-cla
Copy link

google-cla bot commented Jul 8, 2021

Thanks for your pull request. It looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

📝 Please visit https://cla.developers.google.com/ to sign.

Once you've signed (or fixed any issues), please reply here with @googlebot I signed it! and we'll verify it.


What to do if you already signed the CLA

Individual signers
Corporate signers

ℹ️ Googlers: Go here for more info.

@Unix4ever
Copy link
Contributor Author

@googlebot I signed it!

@lyonlai lyonlai self-requested a review July 19, 2021 05:53
Copy link
Collaborator

@lyonlai lyonlai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the replacer idea. It helps base64 encoded the uint8array before transfer. It does cover the data going up to the server, however I believe the data coming back down from the server are also base64 encoded. It would be nice to have the other side covered too.

For this case I would like to see an integration test to ensure the encoding/decoding logic. Could you please add a test into the integration_test folder? A simple bytes echo case should suffice. There's a README.md file in the folder to get you started.

Again, your contribution is much appreciated.

@lyonlai
Copy link
Collaborator

lyonlai commented Jul 19, 2021

Sorry for the late reply as well.

@Unix4ever
Copy link
Contributor Author

For this case I would like to see an integration test to ensure the encoding/decoding logic. Could you please add a test into the integration_test folder? A simple bytes echo case should suffice. There's a README.md file in the folder to get you started.

Yep, sure.

@Unix4ever Unix4ever force-pushed the properly-encode-uint8array branch from de8dd72 to a0406df Compare July 27, 2021 13:27
@Unix4ever
Copy link
Contributor Author

Unix4ever commented Jul 27, 2021

I've added the tests, sorry for the delay.

Regarding the server -> client bytes flow: I've tried to get it done, but couldn't get it right due to my limited TypeScript knowledge.
While it's straightforward how to check the field type and see if it's Uint8Array and encode it to base64, it's not that clear how to detect base64 encoded string and convert it back to Uint8Array, given that it's just a simple string.

I was looking at how you can get type fields at the compile time and got lost in typeof keyof.
Another option is to generate object factories for each type and then run something like Factory<O>(r.json()) in fetchReq.

So I won't make this change in this PR. At least server -> client bytes flow works somehow (if you use any as a response receiver).

@Unix4ever
Copy link
Contributor Author

Ugh, well. I was testing that more in my code and looks like btoa doesn't work for all cases. If the string does not consist only of Latin1symbols it'll throw the error.
I switched it to protobufjs/minimal util.base64.encode function in my code with the workaround, but I'm not sure how to fix it here.
Maybe embed proper base64 encoder right into the fetch module...

@lyonlai
Copy link
Collaborator

lyonlai commented Jul 28, 2021

I see where you could stuck when the information coming down from the server, it's hard to tell as you said it's a string. And even if you use some test library to test if it was a base64 encoded string, you couldn't tell whether the field was an uint8array or not.

In this case you'll be looking for the compiler to generate some information to feed in the fetch call so that when the response comes back you can tell which field needs to be properly translate back to uint8array.

Doing just on the way up it is fine for this PR but if the problem on the way down is not properly solved it might need the user to do some type casting or ts-ignore as the typescript is expecting the field to be an uint8array, which is not that nice.

@lyonlai
Copy link
Collaborator

lyonlai commented Jul 28, 2021

btoa has problem with non latin characters seems to be a common issue on the internet. protobufjs' base64 doesn't seems to be too big to embed in.

https://github.com/protobufjs/protobuf.js/blob/master/lib/base64/index.js#L42

@Unix4ever Unix4ever force-pushed the properly-encode-uint8array branch from a0406df to 4cb959e Compare July 30, 2021 11:13
integration_tests/integration_test.ts Outdated Show resolved Hide resolved
integration_tests/integration_test.ts Outdated Show resolved Hide resolved
generator/template.go Show resolved Hide resolved
Fixes: grpc-ecosystem#22

Binary data should be represented as `base64` encoded string in the JSON
encoded body.
Use replacer to return `base64` encoded string when `Uint8Array` type is
detected.

Signed-off-by: Artem Chernyshev <artem.0xD2@gmail.com>
@Unix4ever Unix4ever force-pushed the properly-encode-uint8array branch from 4cb959e to f6cb5af Compare August 3, 2021 13:49
Copy link
Collaborator

@lyonlai lyonlai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you for your contribution

@lyonlai
Copy link
Collaborator

lyonlai commented Aug 5, 2021

I won't be making a release just yet until the receiver side's fixed. if you are interested to pick it up, let me know.

@lyonlai lyonlai merged commit f3ef8ab into grpc-ecosystem:master Aug 5, 2021
@Unix4ever
Copy link
Contributor Author

Unix4ever commented Aug 11, 2021

I have plenty of other stuff on my plate already. The fix for the receiver side doesn't look simple while using typescript types. I tried to read more and check how it can be done but I've run out of ideas. 🤔

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Send bytes in a message
2 participants