Skip to content

Commit 9a343e3

Browse files
Merge pull request #39 from galvesribeiro/multi-media-types
Allow a MediaTypeHandler to support multiple media types.
2 parents 6708c0e + e4bf15c commit 9a343e3

File tree

8 files changed

+50
-11
lines changed

8 files changed

+50
-11
lines changed

src/Orleans.Http.Abstractions/IMediaTypeHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace Orleans.Http.Abstractions
77
{
88
public interface IMediaTypeHandler
99
{
10-
string MediaType { get; }
10+
string[] MediaTypes { get; }
1111
ValueTask Serialize(object obj, PipeWriter writer);
1212
ValueTask<object> Deserialize(PipeReader reader, Type type, CancellationToken cancellationToken);
1313
}

src/Orleans.Http.MediaTypes.Protobuf/ProtobufMediaTypeHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace Orleans.Http.MediaTypes.Protobuf
99
{
1010
internal sealed class ProtobufMediaTypeHandler : IMediaTypeHandler
1111
{
12-
public string MediaType => "application/protobuf";
12+
public string[] MediaTypes => new[] { "application/protobuf" };
1313

1414
public ValueTask<object> Deserialize(PipeReader reader, Type type, CancellationToken cancellationToken)
1515
{

src/Orleans.Http/FormsMediaTypeHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace Orleans.Http
1212
internal sealed class FormsMediaTypeHandler : IMediaTypeHandler
1313
{
1414
private static readonly Type _dicType = typeof(Dictionary<string, string>);
15-
public string MediaType => "application/x-www-form-urlencoded";
15+
public string[] MediaTypes => new[] { "application/x-www-form-urlencoded" };
1616

1717
public async ValueTask<object> Deserialize(PipeReader reader, Type type, CancellationToken cancellationToken)
1818
{

src/Orleans.Http/JsonMediaTypeHandler.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@ namespace Orleans.Http
99
{
1010
internal sealed class JsonMediaTypeHandler : IMediaTypeHandler
1111
{
12-
private const string MEDIA_TYPE = "application/json";
1312
private readonly JsonSerializerOptions _options;
14-
public string MediaType => MEDIA_TYPE;
13+
public string[] MediaTypes => new[] { "application/json; charset=utf-8", "application/json;charset=utf-8", "application/json" };
1514

1615
public JsonMediaTypeHandler(JsonSerializerOptions options)
1716
{

src/Orleans.Http/MediaTypeManager.cs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,23 @@ internal sealed class MediaTypeManager
1919
public MediaTypeManager(IServiceProvider serviceProvider)
2020
{
2121
this._logger = serviceProvider.GetRequiredService<ILoggerFactory>().CreateLogger<MediaTypeManager>();
22-
this._handlers = serviceProvider.GetServices<IMediaTypeHandler>()?.ToDictionary(h => h.MediaType, h => h, StringComparer.InvariantCultureIgnoreCase);
23-
if (this._handlers == null || this._handlers.Count == 0)
22+
this._handlers = new Dictionary<string, IMediaTypeHandler>(StringComparer.InvariantCultureIgnoreCase);
23+
24+
var handlersRegistered = serviceProvider.GetServices<IMediaTypeHandler>();
25+
if (handlersRegistered != null)
26+
{
27+
foreach (var handler in handlersRegistered)
28+
{
29+
foreach (var mediaType in handler.MediaTypes)
30+
{
31+
this._handlers[mediaType] = handler;
32+
}
33+
}
34+
}
35+
36+
if (this._handlers.Count == 0)
2437
{
2538
this._logger.LogWarning("There are no IMediaTypeHandlers registered! Request body will be ignored.");
26-
this._handlers = new Dictionary<string, IMediaTypeHandler>();
2739
}
2840
}
2941

@@ -40,7 +52,7 @@ public async ValueTask<bool> Serialize(string mediaType, object obj, PipeWriter
4052
}
4153
catch (Exception exc)
4254
{
43-
this._logger.LogWarning(exc, $"Failure to serialize body into '{handler.MediaType}' using {handler.GetType().FullName}: {exc.Message}.");
55+
this._logger.LogWarning(exc, $"Failure to serialize body into '{mediaType}' using {handler.GetType().FullName}: {exc.Message}.");
4456
}
4557

4658
return false;

src/Orleans.Http/XMLMediaTypeHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace Orleans.Http
1111
internal sealed class XMLMediaTypeHandler : IMediaTypeHandler
1212
{
1313
private readonly ConcurrentDictionary<string, XmlSerializer> _serializers = new ConcurrentDictionary<string, XmlSerializer>();
14-
public string MediaType => "application/xml";
14+
public string[] MediaTypes => new[] { "application/xml" };
1515

1616
public ValueTask<object> Deserialize(PipeReader reader, Type type, CancellationToken cancellationToken)
1717
{

test/Orleans.Http.Test/HttpTests.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,24 @@ public async Task RouteTest()
106106
}
107107

108108
[Fact]
109-
public async Task FormsTest()
109+
public async Task JsonTest()
110110
{
111111
var payload = new TestPayload();
112112
payload.Number = 12340000;
113113
payload.Text = "Test text";
114114

115+
var url = "/grains/test/00000000-0000-0000-0000-000000000000/JsonTest";
116+
var response = await this._http.PostAsync(url, new StringContent(JsonSerializer.Serialize(payload, typeof(TestPayload)), Encoding.UTF8, TestExtensions.JSON));
117+
Assert.True(response.IsSuccessStatusCode);
118+
var stream = await response.Content.ReadAsStreamAsync();
119+
var resp = await JsonSerializer.DeserializeAsync<TestPayload>(stream);
120+
Assert.True(payload.Number == resp.Number);
121+
Assert.True(payload.Text == resp.Text);
122+
}
123+
124+
[Fact]
125+
public async Task FormsTest()
126+
{
115127
var url = "/grains/test/00000000-0000-0000-0000-000000000000/FormTest";
116128
var dic = new Dictionary<string, string>();
117129
dic["Test"] = "testing dic";

test/Orleans.Http.Test/TestGrain.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using Orleans.Http.Abstractions;
77
using ProtoBuf;
88
using System.Collections.Generic;
9+
using System.Text.Json.Serialization;
910

1011
namespace Orleans.Http.Test
1112
{
@@ -82,14 +83,19 @@ public interface ITestGrain : IGrainWithGuidKey
8283

8384
[HttpPost("{grainId}/FormTest")]
8485
Task FormTest([FromBody]Dictionary<string, string> payload);
86+
87+
[HttpPost("{grainId}/JsonTest")]
88+
Task<TestPayload> JsonTest([FromBody]TestPayload payload);
8589
}
8690

8791
[ProtoContract]
8892
public class TestPayload
8993
{
9094
[ProtoMember(1)]
95+
[JsonPropertyName("number")]
9196
public int Number { get; set; }
9297
[ProtoMember(2)]
98+
[JsonPropertyName("text")]
9399
public string Text { get; set; }
94100
}
95101

@@ -196,6 +202,16 @@ public Task FormTest(Dictionary<string, string> payload)
196202

197203
throw new ArgumentException(nameof(payload));
198204
}
205+
206+
public Task<TestPayload> JsonTest(TestPayload payload)
207+
{
208+
if (payload != null && payload.Number == 12340000 && payload.Text == "Test text")
209+
{
210+
return Task.FromResult(payload);
211+
}
212+
213+
throw new ArgumentException(nameof(payload));
214+
}
199215
}
200216

201217
public class RandomGuidRouteGrainProvider : IRouteGrainProvider

0 commit comments

Comments
 (0)