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

Support binary passed in GRPC metadata #3234

Merged
merged 6 commits into from Aug 25, 2023
Merged

Support binary passed in GRPC metadata #3234

merged 6 commits into from Aug 25, 2023

Conversation

sapphire-janrain
Copy link
Contributor

Use Uint8Array type in metadata declaration to avoid any reencoding issues in goja.

What?

Changes k6's GRPC client to accept Uint8Array types passed as metadata values.

Why?

Currently k6 does not support adding binary data in the metadata. The suggestion seems to have been to convert it to a string of some sort but there are issues therein:

  • Attempting to just cast bytes into a string via String.fromCharCode or String.fromCodePoint seems to have issues on the goja side. Whenever a byte is >= 0x80 (presumably) another byte is inserted before it by the time it makes it to k6 and protobuf.
  • We cannot base64 the data on the JS side because protobuf will re-encode any -bin metadata fields itself.

As such, it would be best for k6 to properly accept Uint8Arrays in metadata.

Checklist

  • I have performed a self-review of my code.
  • I have added tests for my changes.
  • I have run linter locally (make ci-like-lint) and all checks pass.
  • I have run tests locally (make tests) and all tests pass.
  • I have commented on my code, particularly in hard-to-understand areas.

Caveats

You cannot store Uint8Array in the returned data object from setup (possibly related to #2579 ) as it's converted to a base64'd string before it's passed to the scenario. I'm not sure why exactly and didn't investigate, I assume that's expected behavior (though it was surprising to me). I'm not inclined to fix it here as it's simple to work around for my use case, but happy to create a ticket if it does happen to be unexpected.

@CLAassistant
Copy link

CLAassistant commented Jul 28, 2023

CLA assistant check
All committers have signed the CLA.

@codecov-commenter
Copy link

codecov-commenter commented Aug 7, 2023

Codecov Report

Merging #3234 (26786b5) into master (63a1fdd) will decrease coverage by 0.05%.
Report is 5 commits behind head on master.
The diff coverage is 62.50%.

❗ Current head 26786b5 differs from pull request most recent head fb373ca. Consider uploading reports for the commit fb373ca to get more accurate results

@@            Coverage Diff             @@
##           master    #3234      +/-   ##
==========================================
- Coverage   73.19%   73.15%   -0.05%     
==========================================
  Files         258      256       -2     
  Lines       19884    19885       +1     
==========================================
- Hits        14555    14546       -9     
- Misses       4405     4409       +4     
- Partials      924      930       +6     
Flag Coverage Δ
ubuntu 73.15% <62.50%> (+0.01%) ⬆️
windows ?

Flags with carried forward coverage won't be shown. Click here to find out more.

Files Changed Coverage Δ
js/modules/k6/grpc/client.go 84.35% <62.50%> (-0.34%) ⬇️

... and 8 files with indirect coverage changes

@olegbespalov
Copy link
Collaborator

@sapphire-janrain Thanks for the contribution 🙇 left a few comments

@olegbespalov olegbespalov added the documentation-needed A PR which will need a separate PR for documentation label Aug 8, 2023
Copy link
Collaborator

@codebien codebien left a comment

Choose a reason for hiding this comment

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

Hey @sapphire-janrain, thanks for your contribution 🙇

LGTM, just a minor comment. Note: You have to rebase the branch on top of master for fixing the xk6 steps of the CI.

js/modules/k6/grpc/client.go Outdated Show resolved Hide resolved
@mstoykov mstoykov added this to the v0.47.0 milestone Aug 16, 2023
Copy link
Collaborator

@codebien codebien left a comment

Choose a reason for hiding this comment

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

LGTM, thanks @sapphire-janrain!

Comment on lines 464 to 469
// The spec defines that Binary-valued keys end in -bin
// https://grpc.io/docs/what-is-grpc/core-concepts/#metadata
if strings.HasSuffix(hk, "-bin") {
binval, ok := kv.([]byte)
if !ok {
return result, fmt.Errorf("metadata %q value must be a string or binary", hk)
}
strval = string(binval)
} else {
return result, fmt.Errorf("metadata %q value must be a string", hk)
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

A passing comment without much knowledge about gRPC:

  1. I find it strange that we do not check the suffix before we try to make it into a string.
  2. I find it strange that after we get something that isn't as string as per it's definition we just cast it into a string.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I find it strange that we do not check the suffix before we try to make it into a string.

I agree, good suggestion

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I find it strange that we do not check the suffix before we try to make it into a string.

My main motivation for this is that more often than not it's going to be a string, so I was avoiding this change causing any impact. Happy to change if that's preferred.

I find it strange that after we get something that isn't as string as per it's definition we just cast it into a string.

This is all the GRPC go library does too. If you're expecting some kind of encoding, that wouldn't be desirable. It's just an unfortunate side-effect of the GRPC library having no means of accepting binary data directly.

Copy link
Collaborator

@codebien codebien left a comment

Choose a reason for hiding this comment

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

I agree w @mstoykov' suggestion (and @olegbespalov now 🎉), so marking as Request changes again.

@olegbespalov olegbespalov removed the request for review from imiric August 16, 2023 08:48
@olegbespalov
Copy link
Collaborator

@sapphire-janrain looks good to me 👍 let's resolve the linter issue:

shadow: declaration of "ok" shadows declaration at line 456 (govet)

and I'll approve that. Thanks for the contribution! 🙇

if !ok {
return result, fmt.Errorf("metadata %q value must be binary", hk)
}
strval = string(binval)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we link to https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md#storing-binary-data-in-metadata so that whoever comes after us knows why this is how it is done instead of keeping it in binary and giving it to the grpc library as binary

mstoykov
mstoykov previously approved these changes Aug 24, 2023
Copy link
Collaborator

@mstoykov mstoykov left a comment

Choose a reason for hiding this comment

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

LGTM! Thanks for the work 🙇

I will still like a comment as I had to go on a wide goose chase to figure out that the grpc library actually wants string and that it is supposed to work like that.
Which I still find strange, but at least is what is expect so 🤷

Additionally this brings the question of how do we handle it if we get binary metadata back 🤔

@sapphire-janrain
Copy link
Contributor Author

I made it a more permanent link in case future docs changes on their end rename or reorganize it.

Copy link
Collaborator

@olegbespalov olegbespalov left a comment

Choose a reason for hiding this comment

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

LGTM! Thanks for the contribution! 🙇

@codebien will postpone merging action to you 😅

Copy link
Collaborator

@codebien codebien left a comment

Choose a reason for hiding this comment

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

LGTM, thanks again for your contribution @sapphire-janrain 🎉 I will merge as soon as the CI will be green.

@codebien codebien merged commit aea09c9 into grafana:master Aug 25, 2023
22 checks passed
olegbespalov added a commit to grafana/xk6-grpc that referenced this pull request Aug 31, 2023
Add support for binary metadata (postfixed with `-bin`).

This ports changes from the grafana/k6#3234
@sapphire-janrain sapphire-janrain deleted the feature/bin-metadata branch August 31, 2023 17:34
olegbespalov added a commit to grafana/xk6-grpc that referenced this pull request Sep 4, 2023
Add support for binary metadata (postfixed with `-bin`).

This ports changes from the grafana/k6#3234
oleiade pushed a commit that referenced this pull request Sep 8, 2023
Support binary data for Metadata following the specification that requires a -bin suffix.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: grpc documentation-needed A PR which will need a separate PR for documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants