Commit Graph

154 Commits

Author SHA1 Message Date
Jon Skeet 93c49cad9f Implement JsonEventFormatter for System.Text.Json
This leads to two different formatters both called
JsonEventFormatter, just in different namespaces. That probably
wouldn't cause too much ambiguity, as few applications would depend
on both packages. It avoids longer names such as
"SystemTextJsonEventFormatter" which is pretty unwieldy.

Both the implementation and the tests are very much based on the
Newtonsoft.Json implementation.

Fixes #42.

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-03-24 07:22:41 +00:00
Jon Skeet 1a03dac19e Add guidance for CloudEventFormatter implementers
(And adjust the implementations to match.)

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-03-19 12:44:21 +00:00
Jon Skeet 0fc5aaf478 feat: Implement conventions for ASP.NET Core protocol bindings
Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-03-16 11:23:34 +00:00
Jon Skeet f93f1fe6e6 feat: Make the MQTT protocol bindings follow conventions
Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-03-16 11:23:34 +00:00
Jon Skeet 17d943302a feat: Make the Kafka protocol bindings follow conventions
Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-03-16 11:23:34 +00:00
Jon Skeet 450ba23e96 feat: Make the AMQP protocol bindings follow conventions
Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-03-16 11:23:34 +00:00
Jon Skeet b61e639859 feat!: Implement newly-documented conventions for built-in HTTP bindings
This is a breaking change, using the CopyTo convention instead of CopyFrom.

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-03-16 11:23:34 +00:00
Jon Skeet d3d7a3e9b4 feat: Additional infrastructure code to make protocol bindings simpler to implement
Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-03-16 11:23:34 +00:00
Jon Skeet 83cdc5a1b4 docs: Document expectations for protocol bindings
Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-03-16 11:23:34 +00:00
Jon Skeet 7f6fa9380b fix: Make Kafka binary mode conversion use event formatter
Fixes #103, by always delegating to event formatters. (We'll provide
guidance on how those should handle data.)

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-03-16 11:23:34 +00:00
Jon Skeet 5b914bdf3e fix: Change AMQP data handling
Rather than the AMQP code "knowing" how to handle different data
types, delegate that to an event formatter.

There's *still* a little bit of an ugly
not-quite-single-responsibility in terms of event formatters;
CloudEvent formats tend to be specified in terms of structured mode
messages, not binary mode. It's possible that we should really
separate out "data formatting" from everything else... but it does
get intertwined in structured mode formats.

This change fixes #104, but we certainly want more testing and
documentation for this code in general.

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-03-12 08:08:49 +00:00
Jon Skeet 6656b5c123 Implement validation for CloudEventAttributeType.String
Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-03-04 22:48:19 +00:00
Jon Skeet 8e56fe32b9 Remove unnecessary inheritance for HttpContent
Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-03-01 08:56:48 +00:00
Jon Skeet 72a5dc31f4 Remove unnecessary inheritance for Kafka messages
Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-03-01 08:56:48 +00:00
Jon Skeet b934614324 Remove unnecessary inheritance in MQTT
It feels like you probably always want to specify a topic when creating a message, hence the parameter - but we should probably get feedback for that.
(The one advantage of using inheritance for this was that you could use an object initializer for the whole thing...)

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-03-01 08:56:48 +00:00
Jon Skeet 34ede5b5ba Remove unnecessary AMQP inheritance
The naming of the "ToAmqpMessage" extension method is to allow multiple message types to have unambiguous names.

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-03-01 08:56:48 +00:00
Jon Skeet 07ea4e4448 Add extension points to JsonEventFormatter
This makes it reasonably straightforward to add custom data handling
using derived classes.

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-03-01 06:48:23 +00:00
Jon Skeet 38fdd05f8a Validate JSON token types for non-extension attributes
Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-03-01 06:48:23 +00:00
Jon Skeet 2b658fc752 Comprehensive tests for JsonEventFormatter
This required a bit of rework for the implementation, but the result
is cleaner, in my view.

There's one skipped test, for when an attribute (other than data) is
populated via an integer/Boolean token. We should discuss what we
want to happen in that case.

The extension tests had to change as JsonEventFormatter now
validates that the event it's parsed is valid (for structured mode),
and the ones we were using didn't have a source attribute.

(We will probably want to pepper lots of places with calls to
CloudEvent.Validate, but most of those can come later.)

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-02-25 11:31:48 +00:00
Jon Skeet ccc41b97dd Make unimplemented methods abstract in CloudEventFormatter
Once we've hit 2.0, we won't be able to add new abstract methods to
this class, but for the moment it's okay... and it really does make
sense for these methods to be abstract.

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-02-19 07:29:03 +00:00
Jon Skeet 23a3cd6e69 Rework CloudEventFormatter
This is largely a matter of clarifying responsibilities and adding
documentation to CloudEventFormatter and our current
implementations. Additionally, the content type of the message is
now passed to structured-mode decoding methods to assist with
aspects such as character encodings.

The methods have been renamed to make it clearer that it's the
message that uses structured or binary mode, not the event itself.
(There's no such thing as a "structured mode CloudEvent" or a
"binary mode CloudEvent".)

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-02-18 07:38:50 +00:00
Jon Skeet 951a8c5c42 Add utilities methods for working with MIME
Suggestions for alternative naming would be welcome, but we do want these to be public.

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-02-18 07:38:50 +00:00
Jon Skeet 89044ec905 Don't default the spec version when decoding structured events (all transports)
The spec version is a required attribute - if it's not present, the message isn't a CloudEvent.
The repetitive code here is somewhat annoying, but that's not the only aspect of structured event decoding that has this issue. We may want to revisit this in the future.

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-02-18 07:38:50 +00:00
Jon Skeet 3f689f63f2 Reduce the public operations in our existing event formatters
In particular, that gives more flexibility over implementations (e.g. not needing to worry about URI or Date tokens in JObject)

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-02-18 07:38:50 +00:00
Jon Skeet d6d6479e83 Allow event formatters to only deal with byte arrays, and do so synchronously
Everything else builds on this, but can be overridden for more efficient parsing where appropriate.

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-02-18 07:38:50 +00:00
Jon Skeet bdcfa830f0 Remove params-oriented methods in specific formatters
We don't expect users to use CloudEventFormatter directly anyway, so
convenience methods aren't really important. If we later decide we
want them, we can put them in the base class instead.

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-02-18 07:38:50 +00:00
Jon Skeet 52437b3d50 Rename ICloudEventFormatter to CloudEventFormatter
While this could be CloudEventFormatterBase, it's probably clearer
as it is.

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-02-18 07:38:50 +00:00
Jon Skeet c3495d0a55 Change ICloudEventFormatter into an abstract class
Obviously the name is then inappropriate, but that will be changed in a subsequent commit.

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-02-18 07:38:50 +00:00
Jon Skeet 8b63348296 feat: Extract the existing JSON event formatter from the main SDK
This allows us to remove the Newtonsoft.Json dependency from the
SDK, and implement another event formatter based on System.Text.Json
later on. That should probably wait until we've iterated on the
design of event formatters though.

This commit moves us closer towards (but doesn't fix) #42.

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-02-13 06:42:43 +00:00
Jon Skeet ab2a9b6448 Comment-only review changes
Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-02-11 07:57:38 +00:00
Jon Skeet 33552a13f6 Address review comments
Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-02-11 07:57:38 +00:00
Jon Skeet 7d01a4a181 Fix URI parsing on Linux
This still leaves a hole where the user created a Uri instance
manually on Linux and it claims to be absolute, but it would
potentially be confusing to spot this in Validate as well...

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-02-11 07:57:38 +00:00
Jon Skeet 78dd8416b0 Add tests, primarily for CloudEvent, CloudEventAttribute and CloudEventAttributeType
Each of these classes has 100% coverage just by running their own tests.
There are still some areas of concern:

- .NET's URI parsing and formatting seems hard to predict, so we're not validating as much as I'd like
- There are some interesting questions about CloudEvent behavior which are tested in a "QuestionableBehavior" nested class in CloudEventTest

There's a fair amount of production code changing in here as well, primarily around validation.

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-02-11 07:57:38 +00:00
Jon Skeet 70b5ae99fd Overhaul of codebase with new approach to attributes
This touches almost file in the repository, because it's hard not to
with such a fundamental change.

There are *lots* of TODOs now, all of which we should chase down
before release. In most cases this isn't a new problem - it's just
one that wasn't noted before,

The two main changes are:

- Spec versions, attributes, and attributes types are now first-class
  types. Rather than being able to set attributes to any value you
  want, values have to be of the right type and have a valid value
  (e.g. for datacontenttype). This centralizes value conversion
  for the most part (although transport/format-specific conversions
  may still be required) and makes everything more predictable.
- Extensions are now *not* first-class types; instead, the extension
  attributes can be registered with the CloudEvent in order to perform
  appropriate validation etc, and a pattern around extensions
  providing extension methods on CloudEvent allows them to be used
  easily.

This work has revealed a lot of smaller problems, such as the HTTP
transports propagating a content of "null" (rather than no content)
when no data was set in the CloudEvent. More testing is certainly
required.

It's worth noting that this is a really big breaking change. The 2.0
release was already going to be breaking, but this is much larger
than the previous changes. I assert that the benefits outweight the
costs though, and even though the package already has many users,
we hope there will be many times more users in the future.

Proposed process for this PR:

- This initial commit does not include nearly as many unit tests for
  CloudEvent, CloudEventAttribute or CloudEventAttributeType as I'd
  like. Those will come in a follow-up commit (which should be
  reviewed before merging) but don't affect the review of the overall
  ideas.
- If the general thrust of this PR is acceptable, then I propose we
  merge it, only making changes to the most egregious problems, and
  leaving further clean-up work (of which there's likely to be a lot)
  to later PRs. It's easier to create a clean-up PR in Visual Studio
  than to suggest fixes via GitHub.

Style changes:

- Use explicit access modifiers
- Move using directives before the namespace declaration
- Unit tests are generally more separated out to correspond to
  production classes, and are in separate directories/namespaces
  by project instead of all at the top level.

Currently StyleCop is not installed, but we should probably either
do that or use regular Roslyn analyzers in the long term - along
with turning on XML documentation generation.

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-02-11 07:57:38 +00:00
Jon Skeet 87e15241de Make the spec version of an event immutable
This commit includes two WithSpecVersion methods, one in CloudEvent
and the other in CloudEventAttributes, which convert from one
version to another. These are currently internal, but we can expose
them later if we wish.

Fixes #65
Fixes #66

Creating this commit has raised more issues to discuss:

- CloudEventSpecVersion.Default is a public enum value; changing that
  later would be a breaking change in difficult-to-document ways.
- In general, CloudEventSpecVersion feels like it deserves to be a
  class with well-known specific instances, rather than an enum. That
  would make various things much simpler.
- Given that attributes other than data have a limited set of types,
  I suspect it's worth having a CloudEventAttribute type encapsulating
  that.

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-01-28 18:25:22 +00:00
Jon Skeet d234dfc4de Use DateTimeOffset for timestamp attributes
Also, format those timestamps using the Timestamps class introduced previously.

Fixes #61
Fixes #57
Fixes #48

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-01-27 07:17:58 +00:00
Jon Skeet d5310c94d0 Isolated helper code for timestamp parsing/formatting
(This is a separate commit for easier review)

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-01-27 07:17:58 +00:00
JoshLove-msft 9c52e6c85e Fix typo in resource string
Signed-off-by: JoshLove-msft <54595583+JoshLove-msft@users.noreply.github.com>
2021-01-22 06:46:02 +00:00
Jon Skeet 7debdc1513 Update netcoreapp3.0 targets to netcoreapp3.1
(3.1 is the LTS release; 3.0 is out of support now.)

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-01-15 17:34:42 +00:00
Jon Skeet aac7267a51 Don't push to NuGet from AppVeyor
We can potentially turn the AppVeyor integration down entirely later
on, but at least for now let's make sure packages are pushed manually.

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-01-15 17:34:06 +00:00
Jon Skeet 5471d972f2 Revert to requiring a content type for binary mode
We now provide a more explicit check.

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-01-12 10:00:29 +00:00
Jon Skeet 25a719e48a Address review comments for HTTP header mapping
CloudEventContent now *does* map attributes to HTTP headers in
structured mode, including datacontenttype.

This commit also fixes the format of date/time values to be RFC-3339
compliant.

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-01-12 10:00:29 +00:00
Jon Skeet 3301cbf879 Fix CloudEventContent's handling of headers
- For structured mode, we shouldn't map attributes to HTTP headers
- For binary mode, we should default the media content type to application/json
- UrlEncode and UrlDecode headers in binary mode
- Adds more testing of headers

Fixes #67 and #69.

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-01-12 10:00:29 +00:00
Jon Skeet 4aa5a481e3 Prevent the spec version attribute from being removed via Remove calls
Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-01-12 08:55:20 +00:00
Jon Skeet c95871b782 Preserve the spec version attribute when clearing CloudEventAttributes
Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-01-12 08:55:20 +00:00
Jon Skeet 0441d93593 Prevent null values being added to CloudEventAttributes via the Add methods
Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-01-12 08:55:20 +00:00
Jon Skeet acafac096d Allow every attribute other than the spec version to be cleared
Fixes #58

Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-01-12 08:55:20 +00:00
Jon Skeet e836d6ce90 Sign test/sample assemblies, and make internals visible to unit tests
Signed-off-by: Jon Skeet <jonskeet@google.com>
2021-01-12 08:55:20 +00:00
Jon Skeet b494765587 Update the release trigger to install .NET Core 2.1
(This is so we can run the tests against netcoreapp2.1.)

Signed-off-by: Jon Skeet <jonskeet@google.com>
2020-11-11 18:49:32 +00:00
Jon Skeet 3f2308edf6 Use a centralized version number during beta
See PROCESSES.md for the reasoning

Signed-off-by: Jon Skeet <jonskeet@google.com>
2020-11-11 07:38:08 +00:00