public void Dictionary_Add_NullValue() { IDictionary <string, object> attributes = new CloudEventAttributes(CloudEventsSpecVersion.Default, emptyExtensions); string attributeName = CloudEventAttributes.TypeAttributeName(); Assert.Throws <ArgumentNullException>(() => attributes.Add(attributeName, null)); }
public void Dictionary_Remove_SpecVersion() { IDictionary <string, object> attributes = new CloudEventAttributes(CloudEventsSpecVersion.Default, emptyExtensions); string specVersionAttributeName = CloudEventAttributes.SpecVersionAttributeName(); Assert.Throws <InvalidOperationException>(() => attributes.Remove(specVersionAttributeName)); }
private void MapHeaders(CloudEvent cloudEvent) { var ignoreKeys = new List <string>(3) { CloudEventAttributes.DataAttributeName(cloudEvent.SpecVersion), CloudEventAttributes.IdAttributeName(cloudEvent.SpecVersion), CloudEventAttributes.DataContentTypeAttributeName(cloudEvent.SpecVersion), }; foreach (var attribute in cloudEvent.GetAttributes()) { if (!ignoreKeys.Contains(attribute.Key)) { var key = Constants.PropertyKeyPrefix + attribute.Key; switch (attribute.Value) { case Uri uri: UserProperties.Add(key, uri.ToString()); break; default: UserProperties.Add(key, attribute.Value); break; } } } }
public void Indexer_SetToNullValue_SpecVersion() { var attributes = new CloudEventAttributes(CloudEventsSpecVersion.Default, emptyExtensions); string attributeName = CloudEventAttributes.SpecVersionAttributeName(); Assert.Throws <InvalidOperationException>(() => attributes[attributeName] = null); }
/// <summary> /// Determines if a given JSON <paramref name="jObject"/> is considered a <see cref="CloudEvent"/>. /// </summary> /// <param name="jObject">The raw JSON object.</param> /// <returns> /// [true] if the specified <paramref name="jObject"/> is considered a valid <see cref="CloudEvent"/>; [false] otherwise. /// </returns> public static bool IsCloudEvent(this JObject jObject) { Guard.NotNull(jObject, nameof(jObject)); return(jObject.ContainsKey(CloudEventAttributes.SpecVersionAttributeName()) || jObject.ContainsKey(CloudEventAttributes.SpecVersionAttributeName(CloudEventsSpecVersion.V0_1))); }
public static void Update <T>(this IBasicProperties self, MotorCloudEvent <byte[]> cloudEvent, RabbitMQPublisherConfig <T> config, ICloudEventFormatter cloudEventFormatter) { var messagePriority = cloudEvent.Extension <RabbitMQPriorityExtension>()?.Priority ?? config.DefaultPriority; if (messagePriority.HasValue) { self.Priority = messagePriority.Value; } var dictionary = new Dictionary <string, object>(); foreach (var attr in cloudEvent.GetAttributes()) { if (string.Equals(attr.Key, CloudEventAttributes.DataAttributeName(cloudEvent.SpecVersion)) || string.Equals(attr.Key, CloudEventAttributes.DataContentTypeAttributeName(cloudEvent.SpecVersion)) || string.Equals(attr.Key, RabbitMQPriorityExtension.PriorityAttributeName) || string.Equals(attr.Key, RabbitMQBindingConfigExtension.ExchangeAttributeName) || string.Equals(attr.Key, RabbitMQBindingConfigExtension.RoutingKeyAttributeName)) { continue; } dictionary.Add($"{CloudEventPrefix}{attr.Key}", cloudEventFormatter.EncodeAttribute(cloudEvent.SpecVersion, attr.Key, attr.Value, cloudEvent.GetExtensions().Values)); } self.Headers = dictionary; }
public void Collection_Add_NullValue() { ICollection <KeyValuePair <string, object> > attributes = new CloudEventAttributes(CloudEventsSpecVersion.Default, emptyExtensions); string attributeName = CloudEventAttributes.TypeAttributeName(); var pair = KeyValuePair.Create(attributeName, default(object)); Assert.Throws <InvalidOperationException>(() => attributes.Add(pair)); }
public void Collection_Remove_SpecVersion() { ICollection <KeyValuePair <string, object> > attributes = new CloudEventAttributes(CloudEventsSpecVersion.Default, emptyExtensions); string specVersionAttributeName = CloudEventAttributes.SpecVersionAttributeName(); // The value part is irrelevant; we throw on any attempt to remove a pair with a key that's the spec attribute version. var pair = KeyValuePair.Create(specVersionAttributeName, new object()); Assert.Throws <InvalidOperationException>(() => attributes.Remove(pair)); }
public void Indexer_SetToNullValue_RegularAttribute() { var attributes = new CloudEventAttributes(CloudEventsSpecVersion.Default, emptyExtensions); string attributeName = CloudEventAttributes.TypeAttributeName(); attributes[attributeName] = "some event type"; attributes[attributeName] = null; Assert.Null(attributes[attributeName]); }
private void MapHeaders(CloudEvent cloudEvent, ICloudEventFormatter formatter) { foreach (var attr in cloudEvent.GetAttributes()) { if (string.Equals(attr.Key, CloudEventAttributes.DataAttributeName(cloudEvent.SpecVersion)) || string.Equals(attr.Key, CloudEventAttributes.DataContentTypeAttributeName(cloudEvent.SpecVersion)) || string.Equals(attr.Key, PartitioningExtension.PartitioningKeyAttributeName)) { continue; } Headers.Add(KafkaHeaderPerfix + attr.Key, formatter.EncodeAttribute(cloudEvent.SpecVersion, attr.Key, attr.Value, cloudEvent.Extensions.Values)); } }
public static MotorCloudEvent <byte[]> ExtractCloudEvent <T>(this IBasicProperties self, IApplicationNameService applicationNameService, ICloudEventFormatter cloudEventFormatter, ReadOnlyMemory <byte> body, IReadOnlyCollection <ICloudEventExtension> extensions) { var specVersion = CloudEventsSpecVersion.V1_0; var attributes = new Dictionary <string, object>(); IDictionary <string, object> headers = new Dictionary <string, object>(); if (self.IsHeadersPresent() && self.Headers != null) { headers = self.Headers; } foreach (var header in headers .Where(t => t.Key.StartsWith(CloudEventPrefix)) .Select(t => new KeyValuePair <string, object>( t.Key.Substring(CloudEventPrefix.Length), t.Value))) { if (string.Equals(header.Key, CloudEventAttributes.DataContentTypeAttributeName(specVersion), StringComparison.InvariantCultureIgnoreCase) || string.Equals(header.Key, CloudEventAttributes.SpecVersionAttributeName(specVersion), StringComparison.InvariantCultureIgnoreCase)) { continue; } attributes.Add(header.Key, header.Value); } if (attributes.Count == 0) { return(new MotorCloudEvent <byte[]>(applicationNameService, body.ToArray(), typeof(T).Name, new Uri("rabbitmq://notset"), extensions: extensions.ToArray())); } var cloudEvent = new MotorCloudEvent <byte[]>(applicationNameService, body.ToArray(), extensions); foreach (var attribute in attributes) { cloudEvent.GetAttributes().Add(attribute.Key, cloudEventFormatter.DecodeAttribute( cloudEvent.SpecVersion, attribute.Key, (byte[])attribute.Value, extensions)); } return(cloudEvent); }
public void Clear_PreservesSpecVersion() { IDictionary <string, object> attributes = new CloudEventAttributes(CloudEventsSpecVersion.Default, emptyExtensions); string specVersionAttributeName = CloudEventAttributes.SpecVersionAttributeName(); string specVersionValue = (string)attributes[specVersionAttributeName]; attributes[CloudEventAttributes.TypeAttributeName()] = "some event type"; Assert.Equal(2, attributes.Count); attributes.Clear(); // We'd normally expect an empty dictionary now, but CloudEventAttributes always preserves the spec version. var entry = Assert.Single(attributes); Assert.Equal(CloudEventAttributes.SpecVersionAttributeName(), entry.Key); Assert.Equal(specVersionValue, entry.Value); }
private static CloudEvent BinaryToCloudEvent(Message message, ICloudEventExtension[] extensions) { var specVersion = GetCloudEventsSpecVersion(message); var cloudEventType = GetAttribute(message, CloudEventAttributes.TypeAttributeName(specVersion)); var cloudEventSource = new Uri(GetAttribute(message, CloudEventAttributes.SourceAttributeName(specVersion))); var cloudEvent = new CloudEvent(specVersion, cloudEventType, cloudEventSource, id: message.MessageId, extensions: extensions); var attributes = cloudEvent.GetAttributes(); foreach (var property in message.UserProperties) { if (property.Key.StartsWith(Constants.PropertyKeyPrefix, StringComparison.InvariantCultureIgnoreCase)) { #pragma warning disable CA1308 // Normalize strings to uppercase var key = property.Key.Substring(Constants.PropertyKeyPrefix.Length).ToLowerInvariant(); #pragma warning restore CA1308 // Normalize strings to uppercase attributes[key] = property.Value; } } cloudEvent.DataContentType = message.ContentType == null ? null : new ContentType(message.ContentType); cloudEvent.Data = message.Body; return(cloudEvent); }
public AmqpCloudEventMessage(CloudEvent cloudEvent, ContentMode contentMode, ICloudEventFormatter formatter) { if (contentMode == ContentMode.Structured) { this.BodySection = new Data { Binary = formatter.EncodeStructuredEvent(cloudEvent, out var contentType) }; this.Properties = new Properties() { ContentType = contentType.MediaType }; this.ApplicationProperties = new ApplicationProperties(); MapHeaders(cloudEvent); return; } if (cloudEvent.Data is byte[]) { this.BodySection = new Data { Binary = (byte[])cloudEvent.Data }; } else if (cloudEvent.Data is Stream) { if (cloudEvent.Data is MemoryStream) { this.BodySection = new Data { Binary = ((MemoryStream)cloudEvent.Data).ToArray() }; } else { var buffer = new MemoryStream(); ((Stream)cloudEvent.Data).CopyTo(buffer); this.BodySection = new Data { Binary = buffer.ToArray() }; } } else if (cloudEvent.Data is string) { this.BodySection = new AmqpValue() { Value = cloudEvent.Data }; } this.Properties = new Properties() { ContentType = cloudEvent.DataContentType?.MediaType }; this.ApplicationProperties = new ApplicationProperties(); MapHeaders(cloudEvent); } void MapHeaders(CloudEvent cloudEvent) { foreach (var attribute in cloudEvent.GetAttributes()) { if (!attribute.Key.Equals(CloudEventAttributes.DataAttributeName(cloudEvent.SpecVersion)) && !attribute.Key.Equals(CloudEventAttributes.DataContentTypeAttributeName(cloudEvent.SpecVersion))) { if (attribute.Value is Uri) { this.ApplicationProperties.Map.Add("cloudEvents:" + attribute.Key, attribute.Value.ToString()); } else if (attribute.Value is DateTime || attribute.Value is DateTime || attribute.Value is string) { this.ApplicationProperties.Map.Add("cloudEvents:" + attribute.Key, attribute.Value); } else { Map dict = new Map(); foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(attribute.Value)) { dict.Add(descriptor.Name, descriptor.GetValue(attribute.Value)); } this.ApplicationProperties.Map.Add("cloudEvents:" + attribute.Key, dict); } } } } }
public AmqpCloudEventMessage(CloudEvent cloudEvent, ContentMode contentMode, ICloudEventFormatter formatter) { if (contentMode == ContentMode.Structured) { this.BodySection = new Data { Binary = formatter.EncodeStructuredEvent(cloudEvent, out var contentType) }; this.Properties = new Properties() { ContentType = contentType.MediaType }; this.ApplicationProperties = new ApplicationProperties(); MapHeaders(cloudEvent); return; } if (cloudEvent.Data is byte[]) { this.BodySection = new Data { Binary = (byte[])cloudEvent.Data }; } else if (cloudEvent.Data is Stream) { if (cloudEvent.Data is MemoryStream) { this.BodySection = new Data { Binary = ((MemoryStream)cloudEvent.Data).ToArray() }; } else { var buffer = new MemoryStream(); ((Stream)cloudEvent.Data).CopyTo(buffer); this.BodySection = new Data { Binary = buffer.ToArray() }; } } else if (cloudEvent.Data is string) { this.BodySection = new AmqpValue() { Value = cloudEvent.Data }; } this.Properties = new Properties() { ContentType = cloudEvent.DataContentType?.MediaType }; this.ApplicationProperties = new ApplicationProperties(); MapHeaders(cloudEvent); } void MapHeaders(CloudEvent cloudEvent) { foreach (var attribute in cloudEvent.GetAttributes()) { if (!attribute.Key.Equals(CloudEventAttributes.DataAttributeName(cloudEvent.SpecVersion)) && !attribute.Key.Equals(CloudEventAttributes.DataContentTypeAttributeName(cloudEvent.SpecVersion))) { string key = "cloudEvents:" + attribute.Key; if (attribute.Value is Uri) { this.ApplicationProperties.Map.Add(key, attribute.Value.ToString()); } else if (attribute.Value is DateTimeOffset dto) { // AMQPNetLite doesn't support DateTimeOffset values, so convert to UTC. // That means we can't roundtrip events with non-UTC timestamps, but that's not awful. this.ApplicationProperties.Map.Add(key, dto.UtcDateTime); } else if (attribute.Value is string) { this.ApplicationProperties.Map.Add(key, attribute.Value); } else { Map dict = new Map(); foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(attribute.Value)) { dict.Add(descriptor.Name, descriptor.GetValue(attribute.Value)); } this.ApplicationProperties.Map.Add("cloudEvents:" + attribute.Key, dict); } } } } }
public CloudEvent DecodeJObject(JObject jObject, IEnumerable <ICloudEventExtension> extensions) { if (jObject == null) { throw new ArgumentNullException(nameof(jObject)); } var specVersion = GetSpecVersion(jObject); var cloudEvent = new CloudEvent(specVersion, extensions); var attributes = cloudEvent.GetAttributes(); foreach (var keyValuePair in jObject) { // skip the version since we set that above if (keyValuePair.Key.Equals(CloudEventAttributes.SpecVersionAttributeName(CloudEventsSpecVersion.V0_1), StringComparison.OrdinalIgnoreCase) || keyValuePair.Key.Equals(CloudEventAttributes.SpecVersionAttributeName(CloudEventsSpecVersion.V0_2), StringComparison.OrdinalIgnoreCase) || keyValuePair.Key.Equals(CloudEventAttributes.SpecVersionAttributeName(CloudEventsSpecVersion.V1_0), StringComparison.OrdinalIgnoreCase)) { continue; } if ( specVersion == CloudEventsSpecVersion.V1_0 && keyValuePair.Key.Equals("data_base64", StringComparison.OrdinalIgnoreCase) ) { attributes["data"] = Convert.FromBase64String(keyValuePair.Value.ToString()); continue; } if (keyValuePair.Key.Equals(CloudEventAttributes.DataAttributeName(specVersion), StringComparison.OrdinalIgnoreCase)) { try { attributes[keyValuePair.Key] = keyValuePair.Value.ToObject <T>(_serializer); continue; } catch (Exception ex) { throw new InvalidOperationException($"Failed to deserialize data of type {typeof(T).FullName}", ex); } } switch (keyValuePair.Value.Type) { case JTokenType.String: attributes[keyValuePair.Key] = keyValuePair.Value.ToObject <string>(_serializer); break; case JTokenType.Date: var timeValue = ((JValue)keyValuePair.Value).Value; // The value type may be DateTime or DateTimeOffset if (keyValuePair.Key.Equals(CloudEventAttributes.TimeAttributeName(specVersion), StringComparison.OrdinalIgnoreCase) && timeValue is DateTimeOffset dateTimeOffset) { attributes[keyValuePair.Key] = dateTimeOffset.UtcDateTime; } else { attributes[keyValuePair.Key] = timeValue; } break; case JTokenType.Uri: attributes[keyValuePair.Key] = keyValuePair.Value.ToObject <Uri>(_serializer); break; case JTokenType.Null: attributes[keyValuePair.Key] = null; break; case JTokenType.Integer: attributes[keyValuePair.Key] = keyValuePair.Value.ToObject <int>(_serializer); break; default: attributes[keyValuePair.Key] = (dynamic)keyValuePair.Value; break; } } return(cloudEvent); }