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

Add Message Headers #394

Merged
merged 18 commits into from
Aug 13, 2020
Merged

Add Message Headers #394

merged 18 commits into from
Aug 13, 2020

Conversation

ColinSullivan1
Copy link
Member

Adding NATS message headers to parallel nats-io/nats.go#560.

Also see https://github.com/nats-io/nats-server/blob/master/doc/adr/0004-nats-headers.md

This also includes a change in CI testing to pull the NATS server from a dependency repository. This allows for testing against unreleased edge features.

Signed-off-by: Colin Sullivan <[email protected]>
Signed-off-by: Colin Sullivan <[email protected]>
Signed-off-by: Colin Sullivan <[email protected]>
Signed-off-by: Colin Sullivan <[email protected]>
Signed-off-by: Colin Sullivan <[email protected]>
@ColinSullivan1 ColinSullivan1 changed the title Add Message Headers Add Message Headers - WIP Jul 10, 2020
Copy link
Collaborator

@watfordgnf watfordgnf left a comment

Choose a reason for hiding this comment

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

A few suggestions and comments.

src/NATS.Client/Info.cs Outdated Show resolved Hide resolved
src/NATS.Client/Info.cs Outdated Show resolved Hide resolved
internal static readonly string Header = "NATS/1.0\r\n";
internal static readonly byte[] HeaderBytes = Encoding.UTF8.GetBytes(Header);
internal static readonly int HeaderLen = HeaderBytes.Length;
internal static readonly int MinimalValidHeaderLen = Encoding.UTF8.GetBytes(Header + "k:v\r\n\r\n").Length;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does this mean there is always a value?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point... while there's some debate it looks like some HTTP header implementations will support empty values - we should as well. I'll update and test for that. Thanks.

src/NATS.Client/Msg.cs Outdated Show resolved Hide resolved
src/NATS.Client/Msg.cs Outdated Show resolved Hide resolved
@@ -21,6 +21,7 @@ internal sealed class MsgArg
internal string subject;
internal string reply;
internal long sid;
internal int hdr;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
internal int hdr;
internal int hdr;

* Performance updates
* Avoid warning in test API usage
* Upgrade test packages
* Require .NET 4.6 to use the latest NameValueCollection class

Signed-off-by: Colin Sullivan <[email protected]>
Signed-off-by: Colin Sullivan <[email protected]>
Signed-off-by: Colin Sullivan <[email protected]>
Signed-off-by: Colin Sullivan <[email protected]>
Signed-off-by: Colin Sullivan <[email protected]>
Signed-off-by: Colin Sullivan <[email protected]>
Signed-off-by: Colin Sullivan <[email protected]>
Signed-off-by: Colin Sullivan <[email protected]>
Signed-off-by: Colin Sullivan <[email protected]>
@ColinSullivan1 ColinSullivan1 changed the title Add Message Headers - WIP Add Message Headers Jul 19, 2020
@ColinSullivan1
Copy link
Member Author

I think this should be good to go, would appreciate another quick pass @watfordgnf.

I also addressed the performance issues with Splits. Had to move up to .NET 4.6 to use the NameValueCollection class - while documentation says it's supported in 4.5, the assembly requires 4.6.

IMO it should be OK to move to 4.6 as the oldest supported framework version.

Copy link
Member

@kozlovic kozlovic left a comment

Choose a reason for hiding this comment

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

I don't think you can get away with a simple map. You need to extend to make sure that keys are stored/retried in their canonical form.
Support for multiple values also means that key "Foo" may return an array of ["value1", "value2"] and not a single string of "value1, value2".
Finally, it is possible to receive a multiple line value. So this:

NATS/1.0\r\nTwo-Lines: this is\r\n a multilines value\r\n\r\n

needs to become "Tow-Lines": "this is a multilines value". Notice that the value spreads on 2 lines and start with a space:" a multilines..." the space will then be removed a concatenated to the previous line.

mh.Add("foo", "bar");
mh.Add("foo", "baz");

Assert.Equal("bar,baz", mh["foo"]);
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this is correct. If there are 2 keys in the headers, you should return an array of strings, not a concatenated, comma separated, string.

Copy link
Member Author

Choose a reason for hiding this comment

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

I've updated the example documentation and tests, look for string[] values = mh.GetValues("foo");

src/NATS.Client/Msg.cs Outdated Show resolved Hide resolved
@ColinSullivan1
Copy link
Member Author

@kozlovic , great points - thanks!

Because MsgHeader is a subclass of NameValueCollection, one could use the public virtual string[] GetValues (string name); API to return the values as a string array. The NameValueCollection class is a superclass for the .NET HTTP header classes - the string accessor returning comma separated values is an interesting feature that I used as a shortcut in testing.

I'll add tests for the GetValues APIs to be sure it works and will make sure multiline keys and values are handled correctly.

@ColinSullivan1
Copy link
Member Author

I can also add checks to make sure the keys are in canonical form. The server handled the tests fine though...

@kozlovic
Copy link
Member

I can also add checks to make sure the keys are in canonical form. The server handled the tests fine though...

Because in most cases it does not do anything with the headers. But there is currently 1 case where the server will read headers, it is for JS publish de-dup and in that case it will look for "Msg-Id" and so if the user sets to "msg-id" and library doesn't use canonical form, then server won't de-dup.

@ripienaar
Copy link

ripienaar commented Jul 20, 2020

yeah, server doesnt follow http spec, so gotta be careful. Also soon hopefully we'll add headers for tracing. I dont know .net but since you mentioned a hash map I'll also say that order of headers cant change - technically only the order of the same header more than once - but in general its probably a good idea not to tweak order

Signed-off-by: Colin Sullivan <[email protected]>
@ColinSullivan1
Copy link
Member Author

FYI, I've made various updates to cover what HTTP headers do, improve performance, and demonstrate multiple values in the documentation example and tests.

@jasper-d jasper-d mentioned this pull request Aug 3, 2020
Signed-off-by: Colin Sullivan <[email protected]>
@ColinSullivan1
Copy link
Member Author

Are we g2g?

Copy link
Collaborator

@watfordgnf watfordgnf left a comment

Choose a reason for hiding this comment

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

Saw one fix and had some minor comments.

@@ -2003,7 +2009,7 @@ private int setMsgArgsAryOffsets(byte[] buffer, long length)
int i = 0;

// We only support 4 elements in this protocol version
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this still 4?

}

// buffer for parsing strings
public char[] stringBuf = new char[64];
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should likely be internal.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oof - thanks - will fix!

Signed-off-by: Colin Sullivan <[email protected]>
Copy link
Collaborator

@watfordgnf watfordgnf left a comment

Choose a reason for hiding this comment

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

Looks good.

@ColinSullivan1
Copy link
Member Author

Thanks! Good catch on the size of the args, appreciate it. Turns out I didn't resize the array - embarrassing, but would have been much more so after a release. :)

@ColinSullivan1 ColinSullivan1 merged commit 50cb20d into master Aug 13, 2020
@ColinSullivan1 ColinSullivan1 deleted the headers branch August 13, 2020 19:13
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.

4 participants