168 lines
12 KiB
C#
168 lines
12 KiB
C#
// Copyright (c) Cloud Native Foundation.
|
|
// Licensed under the Apache 2.0 license.
|
|
// See LICENSE file in the project root for full license information.
|
|
|
|
using CloudNative.CloudEvents.Core;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Net.Mime;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace CloudNative.CloudEvents
|
|
{
|
|
/// <summary>
|
|
/// Performs CloudEvent conversions as part of encoding and decoding messages for protocol bindings.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// Event formatters are responsible for complete CloudEvent encoding and decoding for structured-mode messages (where
|
|
/// all the CloudEvent information is represented within the message body), and data-only encoding and decoding
|
|
/// for binary-mode messages (where CloudEvent attributes are represented in message metadata, and the CloudEvent data
|
|
/// is represented in the message body).
|
|
/// </para>
|
|
/// <para>
|
|
/// Each event formatter type is responsible for documenting what types of value are acceptable for the <see cref="CloudEvent.Data"/>
|
|
/// property in CloudEvents it is asked to encode, and likewise what types of value will be present in the same property
|
|
/// when it is asked to decode a message. Event formatters should aim to be as consistent as possible with respect to data handling
|
|
/// between structured and binary modes, although this is not always possible as the structured mode representation may contain
|
|
/// more hints around how to interpret the data than the binary mode representation. Inconsistencies should be carefully
|
|
/// noted so that consumers can write robust code.
|
|
/// </para>
|
|
/// <para>
|
|
/// An event format is often naturally associated with a particular kind of data, but it is not limited to working with
|
|
/// that kind. For example, the JSON event format allows JSON data to be stored particularly naturally within the structured-mode
|
|
/// message body (which is itself JSON), but it is still able to handle arbitrary binary or text data.
|
|
/// </para>
|
|
/// </remarks>
|
|
public abstract class CloudEventFormatter
|
|
{
|
|
/// <summary>
|
|
/// Decodes a CloudEvent from a structured-mode message body, represented as a byte array.
|
|
/// </summary>
|
|
/// <param name="body">The message body (content). Must not be null.</param>
|
|
/// <param name="contentType">The content type of the message, or null if no content type is known.
|
|
/// Typically this is a content type with a media type of "application/cloudevents"; the additional
|
|
/// information such as the charset parameter may be needed in order to decode the message body.</param>
|
|
/// <param name="extensionAttributes">The extension attributes to use when populating the CloudEvent. May be null.</param>
|
|
/// <returns>The CloudEvent derived from the structured message body.</returns>
|
|
public abstract CloudEvent DecodeStructuredModeMessage(byte[] body, ContentType contentType, IEnumerable<CloudEventAttribute> extensionAttributes);
|
|
|
|
/// <summary>
|
|
/// Decodes a CloudEvent from a structured-mode message body, represented as a stream. The default implementation copies the
|
|
/// content of the stream into a byte array before passing it to <see cref="DecodeStructuredModeMessage(byte[], ContentType, IEnumerable{CloudEventAttribute})"/>
|
|
/// but this can be overridden by event formatters that can decode a stream more efficiently.
|
|
/// </summary>
|
|
/// <param name="messageBody">The message body (content). Must not be null.</param>
|
|
/// <param name="contentType">The content type of the message, or null if no content type is known.
|
|
/// Typically this is a content type with a media type of "application/cloudevents"; the additional
|
|
/// information such as the charset parameter may be needed in order to decode the message body.</param>
|
|
/// <param name="extensionAttributes">The extension attributes to use when populating the CloudEvent. May be null.</param>
|
|
/// <returns>The decoded CloudEvent.</returns>
|
|
public virtual CloudEvent DecodeStructuredModeMessage(Stream messageBody, ContentType contentType, IEnumerable<CloudEventAttribute> extensionAttributes)
|
|
{
|
|
var bytes = BinaryDataUtilities.ToByteArray(messageBody);
|
|
return DecodeStructuredModeMessage(bytes, contentType, extensionAttributes);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Asynchronously decodes a CloudEvent from a structured-mode message body, represented as a stream. The default implementation asynchronously copies the
|
|
/// content of the stream into a byte array before passing it to <see cref="DecodeStructuredModeMessage(byte[], ContentType, IEnumerable{CloudEventAttribute})"/>
|
|
/// but this can be overridden by event formatters that can decode a stream more efficiently.
|
|
/// </summary>
|
|
/// <param name="body">The message body (content). Must not be null.</param>
|
|
/// <param name="contentType">The content type of the message, or null if no content type is known.
|
|
/// Typically this is a content type with a media type of "application/cloudevents"; the additional
|
|
/// information such as the charset parameter may be needed in order to decode the message body.</param>
|
|
/// <param name="extensionAttributes">The extension attributes to use when populating the CloudEvent. May be null.</param>
|
|
/// <returns>The CloudEvent derived from the structured message body.</returns>
|
|
public virtual async Task<CloudEvent> DecodeStructuredModeMessageAsync(Stream body, ContentType contentType, IEnumerable<CloudEventAttribute> extensionAttributes)
|
|
{
|
|
var bytes = await BinaryDataUtilities.ToByteArrayAsync(body).ConfigureAwait(false);
|
|
return DecodeStructuredModeMessage(bytes, contentType, extensionAttributes);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Encodes a CloudEvent as the body of a structured-mode message.
|
|
/// </summary>
|
|
/// <param name="cloudEvent">The CloudEvent to encode. Must not be null.</param>
|
|
/// <param name="contentType">On successful return, the content type of the structured-mode message body.
|
|
/// Must not be null (on return).</param>
|
|
/// <returns>The structured-mode representation of the CloudEvent.</returns>
|
|
public abstract byte[] EncodeStructuredModeMessage(CloudEvent cloudEvent, out ContentType contentType);
|
|
|
|
/// <summary>
|
|
/// Decodes the given data obtained from a binary-mode message, populating the <see cref="CloudEvent.Data"/>
|
|
/// property of <paramref name="cloudEvent"/>. Other attributes within the CloudEvent may be used to inform
|
|
/// the interpretation of the message body. This method is expected to be called after all other aspects of the CloudEvent
|
|
/// have been populated.
|
|
/// </summary>
|
|
/// <param name="body">The message body (content). Must not be null, but may be empty.</param>
|
|
/// <param name="cloudEvent">The CloudEvent whose Data property should be populated. Must not be null.</param>
|
|
/// <exception cref="ArgumentException">The data in the given CloudEvent cannot be decoded by this
|
|
/// event formatter.</exception>
|
|
public abstract void DecodeBinaryModeEventData(byte[] body, CloudEvent cloudEvent);
|
|
|
|
/// <summary>
|
|
/// Encodes the data from <paramref name="cloudEvent"/> in a manner suitable for a binary mode message.
|
|
/// </summary>
|
|
/// <exception cref="ArgumentException">The data in the given CloudEvent cannot be encoded by this
|
|
/// event formatter.</exception>
|
|
/// <returns>The binary-mode representation of the CloudEvent.</returns>
|
|
public abstract byte[] EncodeBinaryModeEventData(CloudEvent cloudEvent);
|
|
|
|
/// <summary>
|
|
/// Decodes a collection CloudEvents from a batch-mode message body, represented as a byte array.
|
|
/// </summary>
|
|
/// <param name="body">The message body (content). Must not be null.</param>
|
|
/// <param name="contentType">The content type of the message, or null if no content type is known.
|
|
/// Typically this is a content type with a media type with a prefix of "application/cloudevents-batch"; the additional
|
|
/// information such as the charset parameter may be needed in order to decode the message body.</param>
|
|
/// <param name="extensionAttributes">The extension attributes to use when populating the CloudEvent. May be null.</param>
|
|
/// <returns>The collection of CloudEvents derived from the batch message body.</returns>
|
|
public abstract IReadOnlyList<CloudEvent> DecodeBatchModeMessage(byte[] body, ContentType contentType, IEnumerable<CloudEventAttribute> extensionAttributes);
|
|
|
|
/// <summary>
|
|
/// Decodes a collection CloudEvents from a batch-mode message body, represented as a stream. The default implementation copies the
|
|
/// content of the stream into a byte array before passing it to <see cref="DecodeBatchModeMessage(byte[], ContentType, IEnumerable{CloudEventAttribute})"/>
|
|
/// but this can be overridden by event formatters that can decode a stream more efficiently.
|
|
/// </summary>
|
|
/// <param name="body">The message body (content). Must not be null.</param>
|
|
/// <param name="contentType">The content type of the message, or null if no content type is known.
|
|
/// Typically this is a content type with a media type with a prefix of "application/cloudevents"; the additional
|
|
/// information such as the charset parameter may be needed in order to decode the message body.</param>
|
|
/// <param name="extensionAttributes">The extension attributes to use when populating the CloudEvent. May be null.</param>
|
|
/// <returns>The collection of CloudEvents derived from the batch message body.</returns>
|
|
public virtual IReadOnlyList<CloudEvent> DecodeBatchModeMessage(Stream body, ContentType contentType, IEnumerable<CloudEventAttribute> extensionAttributes)
|
|
{
|
|
var bytes = BinaryDataUtilities.ToByteArray(body);
|
|
return DecodeBatchModeMessage(bytes, contentType, extensionAttributes);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Asynchronously decodes a collection CloudEvents from a batch-mode message body, represented as a stream. The default implementation asynchronously copies the
|
|
/// content of the stream into a byte array before passing it to <see cref="DecodeBatchModeMessage(byte[], ContentType, IEnumerable{CloudEventAttribute})"/>
|
|
/// but this can be overridden by event formatters that can decode a stream more efficiently.
|
|
/// </summary>
|
|
/// <param name="body">The message body (content). Must not be null.</param>
|
|
/// <param name="contentType">The content type of the message, or null if no content type is known.
|
|
/// Typically this is a content type with a media type with a prefix of "application/cloudevents"; the additional
|
|
/// information such as the charset parameter may be needed in order to decode the message body.</param>
|
|
/// <param name="extensionAttributes">The extension attributes to use when populating the CloudEvent. May be null.</param>
|
|
/// <returns>The collection of CloudEvents derived from the batch message body.</returns>
|
|
public virtual async Task<IReadOnlyList<CloudEvent>> DecodeBatchModeMessageAsync(Stream body, ContentType contentType, IEnumerable<CloudEventAttribute> extensionAttributes)
|
|
{
|
|
var bytes = await BinaryDataUtilities.ToByteArrayAsync(body).ConfigureAwait(false);
|
|
return DecodeBatchModeMessage(bytes, contentType, extensionAttributes);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Encodes a sequence of CloudEvents as the body of a message.
|
|
/// </summary>
|
|
/// <param name="cloudEvents">The CloudEvents to encode. Must not be null.</param>
|
|
/// <param name="contentType">On successful return, the content type of the batch message body.
|
|
/// Must not be null (on return).</param>
|
|
/// <returns>The batch representation of the CloudEvent.</returns>
|
|
public abstract byte[] EncodeBatchModeMessage(IEnumerable<CloudEvent> cloudEvents, out ContentType contentType);
|
|
}
|
|
} |