509 lines
20 KiB
C#
509 lines
20 KiB
C#
// Copyright (c) .NET Foundation. All rights reserved.
|
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
|
|
using System;
|
|
using System.Buffers;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.IO.Pipelines;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.Extensions.Primitives;
|
|
using Xunit;
|
|
|
|
namespace Microsoft.AspNetCore.WebUtilities
|
|
{
|
|
public class FormPipeReaderTests
|
|
{
|
|
[Fact]
|
|
public async Task ReadFormAsync_EmptyKeyAtEndAllowed()
|
|
{
|
|
var bodyPipe = await MakePipeReader("=bar");
|
|
|
|
var formCollection = await ReadFormAsync(new FormPipeReader(bodyPipe));
|
|
|
|
Assert.Equal("bar", formCollection[""].ToString());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReadFormAsync_EmptyKeyWithAdditionalEntryAllowed()
|
|
{
|
|
var bodyPipe = await MakePipeReader("=bar&baz=2");
|
|
|
|
var formCollection = await ReadFormAsync(new FormPipeReader(bodyPipe));
|
|
|
|
Assert.Equal("bar", formCollection[""].ToString());
|
|
Assert.Equal("2", formCollection["baz"].ToString());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReadFormAsync_EmptyValueAtEndAllowed()
|
|
{
|
|
var bodyPipe = await MakePipeReader("foo=");
|
|
|
|
var formCollection = await ReadFormAsync(new FormPipeReader(bodyPipe));
|
|
|
|
Assert.Equal("", formCollection["foo"].ToString());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReadFormAsync_EmptyValueWithoutEqualsAtEndAllowed()
|
|
{
|
|
var bodyPipe = await MakePipeReader("foo");
|
|
|
|
var formCollection = await ReadFormAsync(new FormPipeReader(bodyPipe));
|
|
|
|
Assert.Equal("", formCollection["foo"].ToString());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReadFormAsync_EmptyValueWithAdditionalEntryAllowed()
|
|
{
|
|
var bodyPipe = await MakePipeReader("foo=&baz=2");
|
|
|
|
var formCollection = await ReadFormAsync(new FormPipeReader(bodyPipe));
|
|
|
|
Assert.Equal("", formCollection["foo"].ToString());
|
|
Assert.Equal("2", formCollection["baz"].ToString());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReadFormAsync_EmptyValueWithoutEqualsWithAdditionalEntryAllowed()
|
|
{
|
|
var bodyPipe = await MakePipeReader("foo&baz=2");
|
|
|
|
var formCollection = await ReadFormAsync(new FormPipeReader(bodyPipe));
|
|
|
|
Assert.Equal("", formCollection["foo"].ToString());
|
|
Assert.Equal("2", formCollection["baz"].ToString());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReadFormAsync_ValueCountLimitMet_Success()
|
|
{
|
|
var bodyPipe = await MakePipeReader("foo=1&bar=2&baz=3");
|
|
|
|
var formCollection = await ReadFormAsync(new FormPipeReader(bodyPipe) { ValueCountLimit = 3 });
|
|
|
|
Assert.Equal("1", formCollection["foo"].ToString());
|
|
Assert.Equal("2", formCollection["bar"].ToString());
|
|
Assert.Equal("3", formCollection["baz"].ToString());
|
|
Assert.Equal(3, formCollection.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReadFormAsync_ValueCountLimitExceeded_Throw()
|
|
{
|
|
var bodyPipe = await MakePipeReader("foo=1&baz=2&bar=3&baz=4&baf=5");
|
|
|
|
var exception = await Assert.ThrowsAsync<InvalidDataException>(
|
|
() => ReadFormAsync(new FormPipeReader(bodyPipe) { ValueCountLimit = 3 }));
|
|
Assert.Equal("Form value count limit 3 exceeded.", exception.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReadFormAsync_ValueCountLimitExceededSameKey_Throw()
|
|
{
|
|
var bodyPipe = await MakePipeReader("baz=1&baz=2&baz=3&baz=4");
|
|
|
|
var exception = await Assert.ThrowsAsync<InvalidDataException>(
|
|
() => ReadFormAsync(new FormPipeReader(bodyPipe) { ValueCountLimit = 3 }));
|
|
Assert.Equal("Form value count limit 3 exceeded.", exception.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReadFormAsync_KeyLengthLimitMet_Success()
|
|
{
|
|
var bodyPipe = await MakePipeReader("fooooooooo=1&bar=2&baz=3&baz=4");
|
|
|
|
var formCollection = await ReadFormAsync(new FormPipeReader(bodyPipe) { KeyLengthLimit = 10 });
|
|
|
|
Assert.Equal("1", formCollection["fooooooooo"].ToString());
|
|
Assert.Equal("2", formCollection["bar"].ToString());
|
|
Assert.Equal("3,4", formCollection["baz"].ToString());
|
|
Assert.Equal(3, formCollection.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReadFormAsync_KeyLengthLimitExceeded_Throw()
|
|
{
|
|
var bodyPipe = await MakePipeReader("foo=1&baz12345678=2");
|
|
|
|
var exception = await Assert.ThrowsAsync<InvalidDataException>(
|
|
() => ReadFormAsync(new FormPipeReader(bodyPipe) { KeyLengthLimit = 10 }));
|
|
Assert.Equal("Form key length limit 10 exceeded.", exception.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReadFormAsync_ValueLengthLimitMet_Success()
|
|
{
|
|
var bodyPipe = await MakePipeReader("foo=1&bar=1234567890&baz=3&baz=4");
|
|
|
|
var formCollection = await ReadFormAsync(new FormPipeReader(bodyPipe) { ValueLengthLimit = 10 });
|
|
|
|
Assert.Equal("1", formCollection["foo"].ToString());
|
|
Assert.Equal("1234567890", formCollection["bar"].ToString());
|
|
Assert.Equal("3,4", formCollection["baz"].ToString());
|
|
Assert.Equal(3, formCollection.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReadFormAsync_ValueLengthLimitExceeded_Throw()
|
|
{
|
|
var bodyPipe = await MakePipeReader("foo=1&baz=12345678901");
|
|
|
|
var exception = await Assert.ThrowsAsync<InvalidDataException>(
|
|
() => ReadFormAsync(new FormPipeReader(bodyPipe) { ValueLengthLimit = 10 }));
|
|
Assert.Equal("Form value length limit 10 exceeded.", exception.Message);
|
|
}
|
|
|
|
// https://en.wikipedia.org/wiki/Percent-encoding
|
|
[Theory]
|
|
[InlineData("++=hello", " ", "hello")]
|
|
[InlineData("a=1+1", "a", "1 1")]
|
|
[InlineData("%22%25%2D%2E%3C%3E%5C%5E%5F%60%7B%7C%7D%7E=%22%25%2D%2E%3C%3E%5C%5E%5F%60%7B%7C%7D%7E", "\"%-.<>\\^_`{|}~", "\"%-.<>\\^_`{|}~")]
|
|
[InlineData("a=%41", "a", "A")] // ascii encoded hex
|
|
[InlineData("a=%C3%A1", "a", "\u00e1")] // utf8 code points
|
|
[InlineData("a=%u20AC", "a", "%u20AC")] // utf16 not supported
|
|
public async Task ReadForm_Decoding(string formData, string key, string expectedValue)
|
|
{
|
|
var bodyPipe = await MakePipeReader(text: formData);
|
|
|
|
var form = await ReadFormAsync(new FormPipeReader(bodyPipe));
|
|
|
|
Assert.Equal(expectedValue, form[key]);
|
|
}
|
|
|
|
[Theory]
|
|
[MemberData(nameof(Encodings))]
|
|
public void TryParseFormValues_SingleSegmentWorks(Encoding encoding)
|
|
{
|
|
var readOnlySequence = new ReadOnlySequence<byte>(encoding.GetBytes("foo=bar&baz=boo"));
|
|
|
|
KeyValueAccumulator accumulator = default;
|
|
var formReader = new FormPipeReader(null, encoding);
|
|
|
|
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true);
|
|
Assert.True(readOnlySequence.IsEmpty);
|
|
|
|
Assert.Equal(2, accumulator.KeyCount);
|
|
var dict = accumulator.GetResults();
|
|
Assert.Equal("bar", dict["foo"]);
|
|
Assert.Equal("boo", dict["baz"]);
|
|
}
|
|
|
|
[Theory]
|
|
[MemberData(nameof(Encodings))]
|
|
public void TryParseFormValues_Works(Encoding encoding)
|
|
{
|
|
var readOnlySequence = ReadOnlySequenceFactory.SingleSegmentFactory.CreateWithContent(encoding.GetBytes("foo=bar&baz=boo&t="));
|
|
|
|
KeyValueAccumulator accumulator = default;
|
|
|
|
var formReader = new FormPipeReader(null, encoding);
|
|
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true);
|
|
Assert.True(readOnlySequence.IsEmpty);
|
|
|
|
Assert.Equal(3, accumulator.KeyCount);
|
|
var dict = accumulator.GetResults();
|
|
Assert.Equal("bar", dict["foo"]);
|
|
Assert.Equal("boo", dict["baz"]);
|
|
Assert.Equal("", dict["t"]);
|
|
}
|
|
|
|
[Theory]
|
|
[MemberData(nameof(Encodings))]
|
|
public void TryParseFormValues_SplitAcrossSegmentsWorks(Encoding encoding)
|
|
{
|
|
var readOnlySequence = ReadOnlySequenceFactory.SegmentPerByteFactory.CreateWithContent(encoding.GetBytes("foo=bar&baz=boo&t="));
|
|
|
|
KeyValueAccumulator accumulator = default;
|
|
|
|
var formReader = new FormPipeReader(null, encoding);
|
|
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true);
|
|
Assert.True(readOnlySequence.IsEmpty);
|
|
|
|
Assert.Equal(3, accumulator.KeyCount);
|
|
var dict = accumulator.GetResults();
|
|
Assert.Equal("bar", dict["foo"]);
|
|
Assert.Equal("boo", dict["baz"]);
|
|
Assert.Equal("", dict["t"]);
|
|
}
|
|
|
|
[Theory]
|
|
[MemberData(nameof(Encodings))]
|
|
public void TryParseFormValues_MultiSegmentWithArrayPoolAcrossSegmentsWorks(Encoding encoding)
|
|
{
|
|
var readOnlySequence = ReadOnlySequenceFactory.SegmentPerByteFactory.CreateWithContent(encoding.GetBytes("foo=bar&baz=bo" + new string('a', 128)));
|
|
|
|
KeyValueAccumulator accumulator = default;
|
|
|
|
var formReader = new FormPipeReader(null, encoding);
|
|
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true);
|
|
Assert.True(readOnlySequence.IsEmpty);
|
|
|
|
Assert.Equal(2, accumulator.KeyCount);
|
|
var dict = accumulator.GetResults();
|
|
Assert.Equal("bar", dict["foo"]);
|
|
Assert.Equal("bo" + new string('a', 128), dict["baz"]);
|
|
}
|
|
|
|
[Theory]
|
|
[MemberData(nameof(Encodings))]
|
|
public void TryParseFormValues_MultiSegmentSplitAcrossSegmentsWithPlusesWorks(Encoding encoding)
|
|
{
|
|
var readOnlySequence = ReadOnlySequenceFactory.SegmentPerByteFactory.CreateWithContent(encoding.GetBytes("+++=+++&++++=++++&+="));
|
|
|
|
KeyValueAccumulator accumulator = default;
|
|
|
|
var formReader = new FormPipeReader(null, encoding);
|
|
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true);
|
|
Assert.True(readOnlySequence.IsEmpty);
|
|
|
|
Assert.Equal(3, accumulator.KeyCount);
|
|
var dict = accumulator.GetResults();
|
|
Assert.Equal(" ", dict[" "]);
|
|
Assert.Equal(" ", dict[" "]);
|
|
Assert.Equal("", dict[" "]);
|
|
}
|
|
|
|
[Theory]
|
|
[MemberData(nameof(Encodings))]
|
|
public void TryParseFormValues_DecodedPlusesWorks(Encoding encoding)
|
|
{
|
|
var readOnlySequence = ReadOnlySequenceFactory.SingleSegmentFactory.CreateWithContent(encoding.GetBytes("++%2B=+++%2B&++++=++++&+="));
|
|
|
|
KeyValueAccumulator accumulator = default;
|
|
|
|
var formReader = new FormPipeReader(null, encoding);
|
|
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true);
|
|
Assert.True(readOnlySequence.IsEmpty);
|
|
|
|
Assert.Equal(3, accumulator.KeyCount);
|
|
var dict = accumulator.GetResults();
|
|
Assert.Equal(" ", dict[" "]);
|
|
Assert.Equal(" +", dict[" +"]);
|
|
Assert.Equal("", dict[" "]);
|
|
}
|
|
|
|
[Theory]
|
|
[MemberData(nameof(Encodings))]
|
|
public void TryParseFormValues_SplitAcrossSegmentsThatNeedDecodingWorks(Encoding encoding)
|
|
{
|
|
var readOnlySequence = ReadOnlySequenceFactory.SegmentPerByteFactory.CreateWithContent(encoding.GetBytes("\"%-.<>\\^_`{|}~=\"%-.<>\\^_`{|}~&\"%-.<>\\^_`{|}=wow"));
|
|
|
|
KeyValueAccumulator accumulator = default;
|
|
|
|
var formReader = new FormPipeReader(null, encoding);
|
|
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true);
|
|
Assert.True(readOnlySequence.IsEmpty);
|
|
|
|
Assert.Equal(2, accumulator.KeyCount);
|
|
var dict = accumulator.GetResults();
|
|
Assert.Equal("\"%-.<>\\^_`{|}~", dict["\"%-.<>\\^_`{|}~"]);
|
|
Assert.Equal("wow", dict["\"%-.<>\\^_`{|}"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryParseFormValues_MultiSegmentFastPathWorks()
|
|
{
|
|
var readOnlySequence = ReadOnlySequenceFactory.CreateSegments(Encoding.UTF8.GetBytes("foo=bar&"), Encoding.UTF8.GetBytes("baz=boo"));
|
|
|
|
KeyValueAccumulator accumulator = default;
|
|
|
|
var formReader = new FormPipeReader(null);
|
|
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true);
|
|
Assert.True(readOnlySequence.IsEmpty);
|
|
|
|
Assert.Equal(2, accumulator.KeyCount);
|
|
var dict = accumulator.GetResults();
|
|
Assert.Equal("bar", dict["foo"]);
|
|
Assert.Equal("boo", dict["baz"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryParseFormValues_ExceedKeyLengthThrows()
|
|
{
|
|
var readOnlySequence = ReadOnlySequenceFactory.SingleSegmentFactory.CreateWithContent(Encoding.UTF8.GetBytes("foo=bar&baz=boo&t="));
|
|
|
|
KeyValueAccumulator accumulator = default;
|
|
|
|
var formReader = new FormPipeReader(null);
|
|
formReader.KeyLengthLimit = 2;
|
|
|
|
var exception = Assert.Throws<InvalidDataException>(() => formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true));
|
|
Assert.Equal("Form key length limit 2 exceeded.", exception.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryParseFormValues_ExceedKeyLengthThrowsInSplitSegment()
|
|
{
|
|
var readOnlySequence = ReadOnlySequenceFactory.CreateSegments(Encoding.UTF8.GetBytes("fo=bar&ba"), Encoding.UTF8.GetBytes("z=boo&t="));
|
|
|
|
KeyValueAccumulator accumulator = default;
|
|
|
|
var formReader = new FormPipeReader(null);
|
|
formReader.KeyLengthLimit = 2;
|
|
|
|
var exception = Assert.Throws<InvalidDataException>(() => formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true));
|
|
Assert.Equal("Form key length limit 2 exceeded.", exception.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryParseFormValues_ExceedValueLengthThrows()
|
|
{
|
|
var readOnlySequence = ReadOnlySequenceFactory.CreateSegments(Encoding.UTF8.GetBytes("foo=bar&baz=boo&t="));
|
|
|
|
KeyValueAccumulator accumulator = default;
|
|
|
|
var formReader = new FormPipeReader(null);
|
|
formReader.ValueLengthLimit = 2;
|
|
|
|
var exception = Assert.Throws<InvalidDataException>(() => formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true));
|
|
Assert.Equal("Form value length limit 2 exceeded.", exception.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryParseFormValues_ExceedValueLengthThrowsInSplitSegment()
|
|
{
|
|
var readOnlySequence = ReadOnlySequenceFactory.CreateSegments(Encoding.UTF8.GetBytes("foo=ba&baz=bo"), Encoding.UTF8.GetBytes("o&t="));
|
|
|
|
KeyValueAccumulator accumulator = default;
|
|
|
|
var formReader = new FormPipeReader(null);
|
|
formReader.ValueLengthLimit = 2;
|
|
|
|
var exception = Assert.Throws<InvalidDataException>(() => formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true));
|
|
Assert.Equal("Form value length limit 2 exceeded.", exception.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryParseFormValues_ExceedKeyLengthThrowsInSplitSegmentEnd()
|
|
{
|
|
var readOnlySequence = ReadOnlySequenceFactory.CreateSegments(Encoding.UTF8.GetBytes("foo=ba&baz=bo"), Encoding.UTF8.GetBytes("o&asdfasdfasd="));
|
|
|
|
KeyValueAccumulator accumulator = default;
|
|
|
|
var formReader = new FormPipeReader(null);
|
|
formReader.KeyLengthLimit = 10;
|
|
|
|
var exception = Assert.Throws<InvalidDataException>(() => formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true));
|
|
Assert.Equal("Form key length limit 10 exceeded.", exception.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryParseFormValues_ExceedValueLengthThrowsInSplitSegmentEnd()
|
|
{
|
|
var readOnlySequence = ReadOnlySequenceFactory.CreateSegments(Encoding.UTF8.GetBytes("foo=ba&baz=bo"), Encoding.UTF8.GetBytes("o&t=asdfasdfasd"));
|
|
|
|
KeyValueAccumulator accumulator = default;
|
|
|
|
var formReader = new FormPipeReader(null);
|
|
formReader.ValueLengthLimit = 10;
|
|
|
|
var exception = Assert.Throws<InvalidDataException>(() => formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true));
|
|
Assert.Equal("Form value length limit 10 exceeded.", exception.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ResetPipeWorks()
|
|
{
|
|
// Same test that is in the benchmark
|
|
var pipe = new Pipe();
|
|
var bytes = Encoding.UTF8.GetBytes("foo=bar&baz=boo");
|
|
|
|
for (var i = 0; i < 1000; i++)
|
|
{
|
|
pipe.Writer.Write(bytes);
|
|
pipe.Writer.Complete();
|
|
var formReader = new FormPipeReader(pipe.Reader);
|
|
await formReader.ReadFormAsync();
|
|
pipe.Reader.Complete();
|
|
pipe.Reset();
|
|
}
|
|
}
|
|
|
|
[Theory]
|
|
[MemberData(nameof(IncompleteFormKeys))]
|
|
public void ParseFormWithIncompleteKeyWhenIsFinalBlockSucceeds(ReadOnlySequence<byte> readOnlySequence)
|
|
{
|
|
KeyValueAccumulator accumulator = default;
|
|
|
|
var formReader = new FormPipeReader(null)
|
|
{
|
|
KeyLengthLimit = 3
|
|
};
|
|
|
|
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true);
|
|
Assert.True(readOnlySequence.IsEmpty);
|
|
|
|
IDictionary<string, StringValues> values = accumulator.GetResults();
|
|
Assert.Contains("fo", values);
|
|
Assert.Equal("bar", values["fo"]);
|
|
Assert.Contains("ba", values);
|
|
Assert.Equal("", values["ba"]);
|
|
}
|
|
|
|
[Theory]
|
|
[MemberData(nameof(IncompleteFormValues))]
|
|
public void ParseFormWithIncompleteValueWhenIsFinalBlockSucceeds(ReadOnlySequence<byte> readOnlySequence)
|
|
{
|
|
KeyValueAccumulator accumulator = default;
|
|
|
|
var formReader = new FormPipeReader(null)
|
|
{
|
|
ValueLengthLimit = 3
|
|
};
|
|
|
|
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true);
|
|
Assert.True(readOnlySequence.IsEmpty);
|
|
|
|
IDictionary<string, StringValues> values = accumulator.GetResults();
|
|
Assert.Contains("fo", values);
|
|
Assert.Equal("bar", values["fo"]);
|
|
Assert.Contains("b", values);
|
|
Assert.Equal("", values["b"]);
|
|
}
|
|
|
|
public static TheoryData<ReadOnlySequence<byte>> IncompleteFormKeys =>
|
|
new TheoryData<ReadOnlySequence<byte>>
|
|
{
|
|
{ ReadOnlySequenceFactory.CreateSegments(Encoding.UTF8.GetBytes("fo=bar&b"), Encoding.UTF8.GetBytes("a")) },
|
|
{ new ReadOnlySequence<byte>(Encoding.UTF8.GetBytes("fo=bar&ba")) }
|
|
};
|
|
|
|
public static TheoryData<ReadOnlySequence<byte>> IncompleteFormValues =>
|
|
new TheoryData<ReadOnlySequence<byte>>
|
|
{
|
|
{ ReadOnlySequenceFactory.CreateSegments(Encoding.UTF8.GetBytes("fo=bar&b"), Encoding.UTF8.GetBytes("=")) },
|
|
{ new ReadOnlySequence<byte>(Encoding.UTF8.GetBytes("fo=bar&b=")) }
|
|
};
|
|
|
|
public static TheoryData<Encoding> Encodings =>
|
|
new TheoryData<Encoding>
|
|
{
|
|
{ Encoding.UTF8 },
|
|
{ Encoding.UTF32 },
|
|
{ Encoding.ASCII },
|
|
{ Encoding.Unicode }
|
|
};
|
|
|
|
internal virtual Task<Dictionary<string, StringValues>> ReadFormAsync(FormPipeReader reader)
|
|
{
|
|
return reader.ReadFormAsync();
|
|
}
|
|
|
|
private static async Task<PipeReader> MakePipeReader(string text)
|
|
{
|
|
var formContent = Encoding.UTF8.GetBytes(text);
|
|
Pipe bodyPipe = new Pipe();
|
|
|
|
await bodyPipe.Writer.WriteAsync(formContent);
|
|
|
|
// Complete the writer so the reader will complete after processing all data.
|
|
bodyPipe.Writer.Complete();
|
|
return bodyPipe.Reader;
|
|
}
|
|
}
|
|
}
|