Skip to content

Commit 8cb8457

Browse files
committed
增加IChunkedable接口
1 parent f9a5dbe commit 8cb8457

File tree

8 files changed

+124
-20
lines changed

8 files changed

+124
-20
lines changed

WebApiClientCore.Test/Attributes/ParameterAttributes/JsonContentAttributeTest.cs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace WebApiClientCore.Test.Attributes.ParameterAttributes
1313
public class JsonContentAttributeTest
1414
{
1515
[Fact]
16-
public async Task BeforeRequestAsyncTest()
16+
public async Task Utf16ChunkedTest()
1717
{
1818
var apiAction = new DefaultApiActionDescriptor(typeof(IMyApi).GetMethod("PostAsync")!);
1919
var context = new TestRequestContext(apiAction, new
@@ -25,9 +25,32 @@ public async Task BeforeRequestAsyncTest()
2525
context.HttpContext.RequestMessage.RequestUri = new Uri("http://www.webapi.com/");
2626
context.HttpContext.RequestMessage.Method = HttpMethod.Post;
2727

28-
var attr = new JsonContentAttribute() { CharSet = "utf-16" };
28+
var attr = new JsonContentAttribute() { CharSet = "utf-16", AllowChunked = true };
2929
await attr.OnRequestAsync(new ApiParameterContext(context, 0));
30+
var body = await context.HttpContext.RequestMessage.Content!.ReadAsUtf8ByteArrayAsync();
3031

32+
var options = context.HttpContext.HttpApiOptions.JsonSerializeOptions;
33+
using var buffer = new RecyclableBufferWriter<byte>();
34+
JsonBufferSerializer.Serialize(buffer, context.Arguments[0], options);
35+
var target = buffer.WrittenSpan.ToArray();
36+
Assert.True(body.SequenceEqual(target));
37+
}
38+
39+
[Fact]
40+
public async Task Utf8UnChunkedTest()
41+
{
42+
var apiAction = new DefaultApiActionDescriptor(typeof(IMyApi).GetMethod("PostAsync")!);
43+
var context = new TestRequestContext(apiAction, new
44+
{
45+
name = "laojiu",
46+
birthDay = DateTime.Parse("2010-10-10")
47+
});
48+
49+
context.HttpContext.RequestMessage.RequestUri = new Uri("http://www.webapi.com/");
50+
context.HttpContext.RequestMessage.Method = HttpMethod.Post;
51+
52+
var attr = new JsonContentAttribute() { CharSet = "utf-8", AllowChunked = false };
53+
await attr.OnRequestAsync(new ApiParameterContext(context, 0));
3154
var body = await context.HttpContext.RequestMessage.Content!.ReadAsUtf8ByteArrayAsync();
3255

3356
var options = context.HttpContext.HttpApiOptions.JsonSerializeOptions;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System.Net.Http;
2+
using System.Text;
3+
using System.Threading.Tasks;
4+
using WebApiClientCore.HttpContents;
5+
using Xunit;
6+
7+
namespace WebApiClientCore.Test.HttpContents
8+
{
9+
public class JsonContentTest
10+
{
11+
[Fact]
12+
public async Task Utf8JsonTest()
13+
{
14+
var options = new WebApiClientCore.HttpApiOptions();
15+
var content = new JsonContent("at我", options.JsonSerializeOptions);
16+
Assert.Equal(content.GetEncoding(), Encoding.UTF8);
17+
var text = await content.ReadAsStringAsync();
18+
Assert.Equal("\"at我\"", text);
19+
}
20+
21+
[Fact]
22+
public async Task Utf16JsonTest()
23+
{
24+
var options = new WebApiClientCore.HttpApiOptions();
25+
var content = new JsonContent("at我", options.JsonSerializeOptions, Encoding.Unicode);
26+
Assert.Equal(content.GetEncoding(), Encoding.Unicode);
27+
var text = await content.ReadAsStringAsync();
28+
Assert.Equal("\"at我\"", text);
29+
}
30+
}
31+
}

WebApiClientCore/Attributes/ParameterAttributes/JsonContentAttribute.cs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,20 @@ namespace WebApiClientCore.Attributes
1111
/// 使用JsonSerializer序列化参数值得到的 json 文本作为 application/json 请求
1212
/// 每个Api只能注明于其中的一个参数
1313
/// </summary>
14-
public class JsonContentAttribute : HttpContentAttribute, ICharSetable
14+
public class JsonContentAttribute : HttpContentAttribute, ICharSetable, IChunkedable
1515
{
1616
private const string jsonMediaType = "application/json";
1717
private static readonly MediaTypeHeaderValue defaultMediaType = new(jsonMediaType);
1818

1919
private MediaTypeHeaderValue mediaType = defaultMediaType;
2020
private Encoding encoding = Encoding.UTF8;
2121

22+
/// <summary>
23+
/// 获取或设置是否允许 chunked 传输
24+
/// 默认为 true
25+
/// </summary>
26+
public bool AllowChunked { get; set; } = true;
27+
2228
/// <summary>
2329
/// 获取或设置编码名称
2430
/// </summary>
@@ -43,9 +49,17 @@ public string CharSet
4349
protected override Task SetHttpContentAsync(ApiParameterContext context)
4450
{
4551
var value = context.ParameterValue;
46-
var valueType = value == null ? context.Parameter.ParameterType : value.GetType();
4752
var options = context.HttpContext.HttpApiOptions.JsonSerializeOptions;
48-
context.HttpContext.RequestMessage.Content = JsonContent.Create(value, valueType, this.mediaType, options);
53+
54+
if (this.AllowChunked)
55+
{
56+
var valueType = value == null ? context.Parameter.ParameterType : value.GetType();
57+
context.HttpContext.RequestMessage.Content = JsonContent.Create(value, valueType, this.mediaType, options);
58+
}
59+
else
60+
{
61+
context.HttpContext.RequestMessage.Content = new HttpContents.JsonContent(value, options, this.encoding);
62+
}
4963
return Task.CompletedTask;
5064
}
5165
}

WebApiClientCore/HttpContents/JsonContent.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,17 @@ public JsonContent(object? value, JsonSerializerOptions? jsonSerializerOptions,
5858
else
5959
{
6060
this.Headers.ContentType = new MediaTypeHeaderValue(mediaType) { CharSet = encoding.WebName };
61+
this.ConvertEncoding(encoding);
62+
}
63+
}
6164

62-
var utf8Json = this.WrittenSegment;
63-
var encodingBuffer = Encoding.Convert(Encoding.UTF8, encoding, utf8Json.Array!, utf8Json.Offset, utf8Json.Count);
65+
private void ConvertEncoding(Encoding encoding)
66+
{
67+
var utf8Json = this.WrittenSegment;
68+
var encodingBuffer = Encoding.Convert(Encoding.UTF8, encoding, utf8Json.Array!, utf8Json.Offset, utf8Json.Count);
6469

65-
this.Clear();
66-
this.Write(encodingBuffer);
67-
}
70+
this.Clear();
71+
this.Write(encodingBuffer);
6872
}
6973
}
7074
}

WebApiClientCore/HttpContents/XmlContent.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ public class XmlContent : BufferContent
2626
public XmlContent(string? xml, Encoding encoding)
2727
{
2828
encoding.GetBytes(xml, this);
29-
this.Headers.ContentType = encoding == Encoding.UTF8 ? defaultMediaType : new MediaTypeHeaderValue(MediaType) { CharSet = encoding.WebName };
29+
this.Headers.ContentType = encoding == Encoding.UTF8
30+
? defaultMediaType :
31+
new MediaTypeHeaderValue(MediaType) { CharSet = encoding.WebName };
3032
}
3133

3234
/// <summary>
@@ -38,8 +40,9 @@ public XmlContent(string? xml, Encoding encoding)
3840
public XmlContent(object? obj, XmlWriterSettings xmlWriterSettings)
3941
{
4042
XmlSerializer.Serialize(this, obj, xmlWriterSettings);
41-
var encoding = xmlWriterSettings.Encoding;
42-
this.Headers.ContentType = encoding == Encoding.UTF8 ? defaultMediaType : new MediaTypeHeaderValue(MediaType) { CharSet = encoding.WebName };
43+
this.Headers.ContentType = xmlWriterSettings.Encoding == Encoding.UTF8
44+
? defaultMediaType
45+
: new MediaTypeHeaderValue(MediaType) { CharSet = xmlWriterSettings.Encoding.WebName };
4346
}
4447
}
4548
}

WebApiClientCore/IChunkedable.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
namespace WebApiClientCore
2+
{
3+
/// <summary>
4+
/// 是否允许chunked传输
5+
/// </summary>
6+
interface IChunkedable
7+
{
8+
/// <summary>
9+
/// 获取或设置是否允许 chunked 传输
10+
/// </summary>
11+
bool AllowChunked { get; set; }
12+
}
13+
}

WebApiClientCore/Parameters/JsonPatchDocument.cs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,17 @@ namespace WebApiClientCore.Parameters
1515
/// </summary>
1616
[DebuggerTypeProxy(typeof(DebugView))]
1717
[RequiresDynamicCode("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext.")]
18-
public class JsonPatchDocument : IApiParameter
18+
public class JsonPatchDocument : IApiParameter, IChunkedable
1919
{
2020
private static readonly MediaTypeHeaderValue mediaTypeHeaderValue = new("application/json-patch+json");
2121
private readonly List<object> operations = [];
2222

23+
/// <summary>
24+
/// 获取或设置是否允许 chunked 传输
25+
/// 默认为 true
26+
/// </summary>
27+
public bool AllowChunked { get; set; } = true;
28+
2329
/// <summary>
2430
/// Add操作
2531
/// </summary>
@@ -79,8 +85,14 @@ public Task OnRequestAsync(ApiParameterContext context)
7985
}
8086

8187
var options = context.HttpContext.HttpApiOptions.JsonSerializeOptions;
82-
context.HttpContext.RequestMessage.Content = JsonContent.Create(this.operations, this.operations.GetType(), mediaTypeHeaderValue, options);
83-
88+
if (this.AllowChunked)
89+
{
90+
context.HttpContext.RequestMessage.Content = JsonContent.Create(this.operations, this.operations.GetType(), mediaTypeHeaderValue, options);
91+
}
92+
else
93+
{
94+
context.HttpContext.RequestMessage.Content = new HttpContents.JsonPatchContent(this.operations, options);
95+
}
8496
return Task.CompletedTask;
8597
}
8698

WebApiClientCore/Serialization/XmlSerializer.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,7 @@ public static class XmlSerializer
3333

3434
var settings = options ?? writerSettings;
3535
using var writer = new EncodingStringWriter(settings.Encoding);
36-
using var xmlWriter = XmlWriter.Create(writer, settings);
37-
var xmlSerializer = new System.Xml.Serialization.XmlSerializer(obj.GetType());
38-
xmlSerializer.Serialize(xmlWriter, obj);
36+
SerializeCore(writer, obj, settings);
3937
return writer.ToString();
4038
}
4139

@@ -55,7 +53,13 @@ public static void Serialize(IBufferWriter<byte> bufferWriter, object? obj, XmlW
5553

5654
var settings = options ?? writerSettings;
5755
using var writer = new BufferTextWriter(bufferWriter, settings.Encoding);
58-
using var xmlWriter = XmlWriter.Create(writer, settings);
56+
SerializeCore(writer, obj, settings);
57+
}
58+
59+
[RequiresUnreferencedCode("Members from serialized types may be trimmed if not referenced directly")]
60+
private static void SerializeCore(TextWriter textWriter, object obj, XmlWriterSettings settings)
61+
{
62+
using var xmlWriter = XmlWriter.Create(textWriter, settings);
5963
var xmlSerializer = new System.Xml.Serialization.XmlSerializer(obj.GetType());
6064
xmlSerializer.Serialize(xmlWriter, obj);
6165
}

0 commit comments

Comments
 (0)