Beispiel #1
0
        /// <summary>
        /// Converts this Kafka message into a CloudEvent object.
        /// </summary>
        /// <param name="message">The Kafka message to convert. Must not be null.</param>
        /// <param name="formatter">The event formatter to use to parse the CloudEvent. Must not be null.</param>
        /// <param name="extensionAttributes">The extension attributes to use when parsing the CloudEvent. May be null.</param>
        /// <returns>A reference to a validated CloudEvent instance.</returns>
        public static CloudEvent ToCloudEvent(this Message <string, byte[]> message,
                                              CloudEventFormatter formatter, IEnumerable <CloudEventAttribute> extensionAttributes)
        {
            Validation.CheckNotNull(message, nameof(message));
            Validation.CheckNotNull(formatter, nameof(formatter));

            if (!IsCloudEvent(message))
            {
                throw new InvalidOperationException();
            }

            var contentType = ExtractContentType(message);

            CloudEvent cloudEvent;

            // Structured mode
            if (MimeUtilities.IsCloudEventsContentType(contentType))
            {
                cloudEvent = formatter.DecodeStructuredModeMessage(message.Value, new ContentType(contentType), extensionAttributes);
            }
            else
            {
                // Binary mode
                if (!(GetHeaderValue(message, SpecVersionKafkaHeader) is byte[] versionIdBytes))
                {
                    throw new ArgumentException("Request is not a CloudEvent");
                }
                string versionId = Encoding.UTF8.GetString(versionIdBytes);
                CloudEventsSpecVersion version = CloudEventsSpecVersion.FromVersionId(versionId)
                                                 ?? throw new ArgumentException($"Unknown CloudEvents spec version '{versionId}'", nameof(message));

                cloudEvent = new CloudEvent(version, extensionAttributes)
                {
                    DataContentType = contentType
                };

                foreach (var header in message.Headers.Where(h => h.Key.StartsWith(KafkaHeaderPrefix)))
                {
                    var attributeName = header.Key.Substring(KafkaHeaderPrefix.Length).ToLowerInvariant();
                    if (attributeName == CloudEventsSpecVersion.SpecVersionAttribute.Name)
                    {
                        continue;
                    }
                    // TODO: Is this feasible?
                    var headerValue = header.GetValueBytes();
                    if (headerValue is null)
                    {
                        continue;
                    }
                    string attributeValue = Encoding.UTF8.GetString(headerValue);

                    cloudEvent.SetAttributeFromString(attributeName, attributeValue);
                }
                formatter.DecodeBinaryModeEventData(message.Value, cloudEvent);
            }

            InitPartitioningKey(message, cloudEvent);
            return(Validation.CheckCloudEventArgument(cloudEvent, nameof(message)));
        }
Beispiel #2
0
 public void IsCloudEventsContentType(string contentType, bool expectedResult) =>
 Assert.Equal(expectedResult, MimeUtilities.IsCloudEventsContentType(contentType));
 private static bool HasCloudEventsContentType(HttpRequest request) =>
 MimeUtilities.IsCloudEventsContentType(request?.ContentType);
Beispiel #4
0
 // TODO: This would include "application/cloudeventsarerubbish" for example...
 private static bool HasCloudEventsContentType(HttpContent content) =>
 MimeUtilities.IsCloudEventsContentType(content?.Headers?.ContentType?.MediaType);
Beispiel #5
0
        // TODO: Avoid all the byte[] -> string conversions? If we didn't care about case-sensitivity, we could prepare byte arrays to perform comparisons with.

        /// <summary>
        /// Indicates whether this message holds a single CloudEvent.
        /// </summary>
        /// <remarks>
        /// This method returns false for batch requests, as they need to be parsed differently.
        /// </remarks>
        /// <param name="message">The message to check for the presence of a CloudEvent. Must not be null.</param>
        /// <returns>true, if the request is a CloudEvent</returns>
        public static bool IsCloudEvent(this Message <string, byte[]> message) =>
        GetHeaderValue(message, SpecVersionKafkaHeader) is object ||
        MimeUtilities.IsCloudEventsContentType(ExtractContentType(message));
Beispiel #6
0
 private static bool HasCloudEventsContentType(Message message, out string contentType)
 {
     contentType = message.Properties.ContentType?.ToString();
     return(MimeUtilities.IsCloudEventsContentType(contentType));
 }