diff --git a/src/Dapr.AspNetCore/CloudEventsMiddlewareOptions.cs b/src/Dapr.AspNetCore/CloudEventsMiddlewareOptions.cs
index 0692fed74..84e68adb5 100644
--- a/src/Dapr.AspNetCore/CloudEventsMiddlewareOptions.cs
+++ b/src/Dapr.AspNetCore/CloudEventsMiddlewareOptions.cs
@@ -39,15 +39,39 @@ public class CloudEventsMiddlewareOptions
///
///
///
- /// Setting this property to true will forward the CloudEvent properties as Request Headers in the following format.
+ /// Setting this property to true will forward all the CloudEvent properties as Request Headers.
+ /// For more fine grained control of which properties are forwarded you can use either or .
///
///
- /// Property names will always be prefixed with 'Cloudevent.' and lower case.
+ /// Property names will always be prefixed with 'Cloudevent.' and be lower case in the following format:"Cloudevent.type"
///
///
/// ie. A CloudEvent property "type": "Example.Type" will be added as "Cloudevent.type": "Example.Type" request header.
///
///
public bool ForwardCloudEventPropertiesAsHeaders { get; set; }
+
+ ///
+ /// Gets or sets an array of CloudEvent property names that will be forwarded as Request Headers if is set to true.
+ ///
+ ///
+ ///
+ /// Note: Setting this will only forwarded the listed property names.
+ ///
+ ///
+ /// ie: ["type", "subject"]
+ ///
+ ///
+ public string[] IncludedCloudEventPropertiesAsHeaders { get; set; }
+
+ ///
+ /// Gets or sets an array of CloudEvent property names that will not be forwarded as Request Headers if is set to true.
+ ///
+ ///
+ ///
+ /// ie: ["type", "subject"]
+ ///
+ ///
+ public string[] ExcludedCloudEventPropertiesFromHeaders { get; set; }
}
}
diff --git a/test/Dapr.AspNetCore.Test/CloudEventsMiddlewareTest.cs b/test/Dapr.AspNetCore.Test/CloudEventsMiddlewareTest.cs
index dfb99538b..c8a5ff402 100644
--- a/test/Dapr.AspNetCore.Test/CloudEventsMiddlewareTest.cs
+++ b/test/Dapr.AspNetCore.Test/CloudEventsMiddlewareTest.cs
@@ -138,6 +138,7 @@ public async Task InvokeAsync_ForwardsJsonPropertiesAsHeaders(string dataContent
ReadBody(httpContext.Request.Body).Should().Be("{\"name\":\"jimmy\"}");
httpContext.Request.Headers.Should().ContainKey("Cloudevent.type").WhichValue.Should().BeEquivalentTo("Test.Type");
+ httpContext.Request.Headers.Should().ContainKey("Cloudevent.subject").WhichValue.Should().BeEquivalentTo("Test.Subject");
return Task.CompletedTask;
});
@@ -146,8 +147,84 @@ public async Task InvokeAsync_ForwardsJsonPropertiesAsHeaders(string dataContent
var context = new DefaultHttpContext();
context.Request.ContentType = charSet == null ? "application/cloudevents+json" : $"application/cloudevents+json;charset={charSet}";
context.Request.Body = dataContentType == null ?
- MakeBody("{ \"type\": \"Test.Type\", \"data\": { \"name\":\"jimmy\" } }", encoding) :
- MakeBody($"{{ \"datacontenttype\": \"{dataContentType}\", \"type\":\"Test.Type\", \"data\": {{ \"name\":\"jimmy\" }} }}", encoding);
+ MakeBody("{ \"type\": \"Test.Type\", \"subject\": \"Test.Subject\", \"data\": { \"name\":\"jimmy\" } }", encoding) :
+ MakeBody($"{{ \"datacontenttype\": \"{dataContentType}\", \"type\":\"Test.Type\", \"subject\": \"Test.Subject\", \"data\": {{ \"name\":\"jimmy\" }} }}", encoding);
+
+ await pipeline.Invoke(context);
+ }
+
+ [Theory]
+ [InlineData(null, null)] // assumes application/json + utf8
+ [InlineData("application/json", null)] // assumes utf8
+ [InlineData("application/json", "utf-8")]
+ [InlineData("application/json", "UTF-8")]
+ [InlineData("application/person+json", "UTF-16")] // arbitrary content type and charset
+ public async Task InvokeAsync_ForwardsIncludedJsonPropertiesAsHeaders(string dataContentType, string charSet)
+ {
+ var encoding = charSet == null ? null : Encoding.GetEncoding(charSet);
+ var app = new ApplicationBuilder(null);
+ app.UseCloudEvents(new CloudEventsMiddlewareOptions
+ {
+ ForwardCloudEventPropertiesAsHeaders = true,
+ IncludedCloudEventPropertiesAsHeaders = new []{"type"}
+ });
+
+ // Do verification in the scope of the middleware
+ app.Run(httpContext =>
+ {
+ httpContext.Request.ContentType.Should().Be(dataContentType ?? "application/json");
+ ReadBody(httpContext.Request.Body).Should().Be("{\"name\":\"jimmy\"}");
+
+ httpContext.Request.Headers.Should().ContainKey("Cloudevent.type").WhichValue.Should().BeEquivalentTo("Test.Type");
+ httpContext.Request.Headers.Should().NotContainKey("Cloudevent.subject");
+ return Task.CompletedTask;
+ });
+
+ var pipeline = app.Build();
+
+ var context = new DefaultHttpContext();
+ context.Request.ContentType = charSet == null ? "application/cloudevents+json" : $"application/cloudevents+json;charset={charSet}";
+ context.Request.Body = dataContentType == null ?
+ MakeBody("{ \"type\": \"Test.Type\", \"subject\": \"Test.Subject\", \"data\": { \"name\":\"jimmy\" } }", encoding) :
+ MakeBody($"{{ \"datacontenttype\": \"{dataContentType}\", \"type\":\"Test.Type\", \"subject\": \"Test.Subject\", \"data\": {{ \"name\":\"jimmy\" }} }}", encoding);
+
+ await pipeline.Invoke(context);
+ }
+
+ [Theory]
+ [InlineData(null, null)] // assumes application/json + utf8
+ [InlineData("application/json", null)] // assumes utf8
+ [InlineData("application/json", "utf-8")]
+ [InlineData("application/json", "UTF-8")]
+ [InlineData("application/person+json", "UTF-16")] // arbitrary content type and charset
+ public async Task InvokeAsync_DoesNotForwardExcludedJsonPropertiesAsHeaders(string dataContentType, string charSet)
+ {
+ var encoding = charSet == null ? null : Encoding.GetEncoding(charSet);
+ var app = new ApplicationBuilder(null);
+ app.UseCloudEvents(new CloudEventsMiddlewareOptions
+ {
+ ForwardCloudEventPropertiesAsHeaders = true,
+ ExcludedCloudEventPropertiesFromHeaders = new []{"type"}
+ });
+
+ // Do verification in the scope of the middleware
+ app.Run(httpContext =>
+ {
+ httpContext.Request.ContentType.Should().Be(dataContentType ?? "application/json");
+ ReadBody(httpContext.Request.Body).Should().Be("{\"name\":\"jimmy\"}");
+
+ httpContext.Request.Headers.Should().NotContainKey("Cloudevent.type");
+ httpContext.Request.Headers.Should().ContainKey("Cloudevent.subject").WhichValue.Should().BeEquivalentTo("Test.Subject");
+ return Task.CompletedTask;
+ });
+
+ var pipeline = app.Build();
+
+ var context = new DefaultHttpContext();
+ context.Request.ContentType = charSet == null ? "application/cloudevents+json" : $"application/cloudevents+json;charset={charSet}";
+ context.Request.Body = dataContentType == null ?
+ MakeBody("{ \"type\": \"Test.Type\", \"subject\": \"Test.Subject\", \"data\": { \"name\":\"jimmy\" } }", encoding) :
+ MakeBody($"{{ \"datacontenttype\": \"{dataContentType}\", \"type\":\"Test.Type\", \"subject\": \"Test.Subject\", \"data\": {{ \"name\":\"jimmy\" }} }}", encoding);
await pipeline.Invoke(context);
}