< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 371
Coverable lines: 371
Total lines: 660
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 112
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Net.Http/src/System/Net/Http/MultipartContent.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Buffers;
 5using System.Collections.Generic;
 6using System.Diagnostics;
 7using System.IO;
 8using System.Net.Http.Headers;
 9using System.Text;
 10using System.Threading;
 11using System.Threading.Tasks;
 12
 13namespace System.Net.Http
 14{
 15    public class MultipartContent : HttpContent, IEnumerable<HttpContent>
 16    {
 17        #region Fields
 18
 19        private const int ColonSpaceLength = 2;
 20        private const int CommaSpaceLength = 2;
 21
 022        private static readonly SearchValues<char> s_allowedBoundaryChars =
 023            SearchValues.Create(" '()+,-./0123456789:=?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz");
 24
 025        private static readonly byte[] CrLfBytes = HttpRuleParser.DefaultHttpEncoding.GetBytes("\r\n");
 026        private static readonly byte[] DashDashBytes = HttpRuleParser.DefaultHttpEncoding.GetBytes("--");
 27
 28        private readonly List<HttpContent> _nestedContent;
 29        private readonly byte[] _startBoundaryBytes;   // "--{boundary}\r\n"
 30        private readonly byte[] _endBoundaryBytes;     // "\r\n--{boundary}--\r\n"
 31
 32        #endregion Fields
 33
 34        #region Construction
 35
 36        public MultipartContent()
 037            : this("mixed", GetDefaultBoundary())
 038        { }
 39
 40        public MultipartContent(string subtype)
 041            : this(subtype, GetDefaultBoundary())
 042        { }
 43
 044        public MultipartContent(string subtype, string boundary)
 045        {
 046            ArgumentException.ThrowIfNullOrWhiteSpace(subtype);
 047            ValidateBoundary(boundary);
 48
 049            byte[] boundaryBytes = HttpRuleParser.DefaultHttpEncoding.GetBytes(boundary);
 050            _startBoundaryBytes = [.. DashDashBytes, .. boundaryBytes, .. CrLfBytes];
 051            _endBoundaryBytes = [.. CrLfBytes, .. DashDashBytes, .. boundaryBytes, .. DashDashBytes, .. CrLfBytes];
 52
 053            string quotedBoundary = boundary;
 054            if (!quotedBoundary.StartsWith('\"'))
 055            {
 056                quotedBoundary = "\"" + quotedBoundary + "\"";
 057            }
 58
 059            MediaTypeHeaderValue contentType = new MediaTypeHeaderValue("multipart/" + subtype);
 060            contentType.Parameters.Add(new NameValueHeaderValue(nameof(boundary), quotedBoundary));
 061            Headers.ContentType = contentType;
 62
 063            _nestedContent = new List<HttpContent>();
 064        }
 65
 66        private static void ValidateBoundary(string boundary)
 067        {
 68            // NameValueHeaderValue is too restrictive for boundary.
 69            // Instead validate it ourselves and then quote it.
 070            ArgumentException.ThrowIfNullOrWhiteSpace(boundary);
 71
 72            // RFC 2046 Section 5.1.1
 73            // boundary := 0*69<bchars> bcharsnospace
 74            // bchars := bcharsnospace / " "
 75            // bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" / "+" / "_" / "," / "-" / "." / "/" / ":" / "=" / "?"
 076            if (boundary.Length > 70)
 077            {
 078                throw new ArgumentOutOfRangeException(nameof(boundary), boundary,
 079                    SR.Format(System.Globalization.CultureInfo.InvariantCulture, SR.net_http_content_field_too_long, 70)
 80            }
 81            // Cannot end with space.
 082            if (boundary.EndsWith(' '))
 083            {
 084                throw new ArgumentException(SR.Format(System.Globalization.CultureInfo.InvariantCulture, SR.net_http_hea
 85            }
 86
 087            if (boundary.AsSpan().ContainsAnyExcept(s_allowedBoundaryChars))
 088            {
 089                throw new ArgumentException(SR.Format(System.Globalization.CultureInfo.InvariantCulture, SR.net_http_hea
 90            }
 091        }
 92
 93        private static string GetDefaultBoundary()
 094        {
 095            return Guid.NewGuid().ToString();
 096        }
 97
 98        public virtual void Add(HttpContent content)
 099        {
 0100            ArgumentNullException.ThrowIfNull(content);
 101
 0102            _nestedContent.Add(content);
 0103        }
 104
 105        #endregion Construction
 106
 107        #region Dispose
 108
 109        protected override void Dispose(bool disposing)
 0110        {
 0111            if (disposing)
 0112            {
 0113                foreach (HttpContent content in _nestedContent)
 0114                {
 0115                    content.Dispose();
 0116                }
 0117                _nestedContent.Clear();
 0118            }
 0119            base.Dispose(disposing);
 0120        }
 121
 122        #endregion Dispose
 123
 124        #region IEnumerable<HttpContent> Members
 125
 126        public IEnumerator<HttpContent> GetEnumerator()
 0127        {
 0128            return _nestedContent.GetEnumerator();
 0129        }
 130
 131        #endregion
 132
 133        #region IEnumerable Members
 134
 135        Collections.IEnumerator Collections.IEnumerable.GetEnumerator()
 0136        {
 0137            return _nestedContent.GetEnumerator();
 0138        }
 139
 140        #endregion
 141
 142        #region Serialization
 143
 144        /// <summary>
 145        /// Gets or sets a callback that returns the <see cref="Encoding"/> to decode the value for the specified respon
 146        /// or <see langword="null"/> to use the default behavior.
 147        /// </summary>
 0148        public HeaderEncodingSelector<HttpContent>? HeaderEncodingSelector { get; set; }
 149
 150        // for-each content
 151        //   write "--" + boundary
 152        //   for-each content header
 153        //     write header: header-value
 154        //   write content.CopyTo[Async]
 155        // write "--" + boundary + "--"
 156        // Can't be canceled directly by the user.  If the overall request is canceled
 157        // then the stream will be closed an exception thrown.
 158        protected override void SerializeToStream(Stream stream, TransportContext? context, CancellationToken cancellati
 0159        {
 0160            Debug.Assert(stream != null);
 161            try
 0162            {
 163                // Write start boundary.
 0164                stream.Write(_startBoundaryBytes);
 165
 166                // Write each nested content.
 0167                for (int contentIndex = 0; contentIndex < _nestedContent.Count; contentIndex++)
 0168                {
 169                    // Write divider, headers, and content.
 0170                    HttpContent content = _nestedContent[contentIndex];
 0171                    SerializeHeadersToStream(stream, content, writeDivider: contentIndex != 0);
 0172                    content.CopyTo(stream, context, cancellationToken);
 0173                }
 174
 175                // Write footer boundary.
 0176                stream.Write(_endBoundaryBytes);
 0177            }
 0178            catch (Exception ex)
 0179            {
 0180                if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(this, ex);
 0181                throw;
 182            }
 0183        }
 184
 185        // for-each content
 186        //   write "--" + boundary
 187        //   for-each content header
 188        //     write header: header-value
 189        //   write content.CopyTo[Async]
 190        // write "--" + boundary + "--"
 191        // Can't be canceled directly by the user.  If the overall request is canceled
 192        // then the stream will be closed an exception thrown.
 193        protected override Task SerializeToStreamAsync(Stream stream, TransportContext? context) =>
 0194            SerializeToStreamAsyncCore(stream, context, default);
 195
 196        protected override Task SerializeToStreamAsync(Stream stream, TransportContext? context, CancellationToken cance
 197            // Only skip the original protected virtual SerializeToStreamAsync if this
 198            // isn't a derived type that may have overridden the behavior.
 0199            GetType() == typeof(MultipartContent) ? SerializeToStreamAsyncCore(stream, context, cancellationToken) :
 0200            base.SerializeToStreamAsync(stream, context, cancellationToken);
 201
 202        private protected async Task SerializeToStreamAsyncCore(Stream stream, TransportContext? context, CancellationTo
 0203        {
 0204            Debug.Assert(stream != null);
 205            try
 0206            {
 207                // Write start boundary.
 0208                await stream.WriteAsync(_startBoundaryBytes, cancellationToken).ConfigureAwait(false);
 209
 210                // Write each nested content.
 0211                var output = new MemoryStream();
 0212                for (int contentIndex = 0; contentIndex < _nestedContent.Count; contentIndex++)
 0213                {
 214                    // Write divider, headers, and content.
 0215                    HttpContent content = _nestedContent[contentIndex];
 216
 0217                    output.SetLength(0);
 0218                    SerializeHeadersToStream(output, content, writeDivider: contentIndex != 0);
 0219                    output.Position = 0;
 0220                    await output.CopyToAsync(stream, cancellationToken).ConfigureAwait(false);
 221
 0222                    await content.CopyToAsync(stream, context, cancellationToken).ConfigureAwait(false);
 0223                }
 224
 225                // Write footer boundary.
 0226                await stream.WriteAsync(_endBoundaryBytes, cancellationToken).ConfigureAwait(false);
 0227            }
 0228            catch (Exception ex)
 0229            {
 0230                if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(this, ex);
 0231                throw;
 232            }
 0233        }
 234
 235        protected override Stream CreateContentReadStream(CancellationToken cancellationToken)
 0236        {
 0237            ValueTask<Stream> task = CreateContentReadStreamAsyncCore(async: false, cancellationToken);
 0238            Debug.Assert(task.IsCompleted);
 0239            return task.GetAwaiter().GetResult();
 0240        }
 241
 242        protected override Task<Stream> CreateContentReadStreamAsync() =>
 0243            CreateContentReadStreamAsyncCore(async: true, CancellationToken.None).AsTask();
 244
 245        protected override Task<Stream> CreateContentReadStreamAsync(CancellationToken cancellationToken) =>
 246            // Only skip the original protected virtual CreateContentReadStreamAsync if this
 247            // isn't a derived type that may have overridden the behavior.
 0248            GetType() == typeof(MultipartContent) ? CreateContentReadStreamAsyncCore(async: true, cancellationToken).AsT
 0249            base.CreateContentReadStreamAsync(cancellationToken);
 250
 251        private async ValueTask<Stream> CreateContentReadStreamAsyncCore(bool async, CancellationToken cancellationToken
 0252        {
 253            try
 0254            {
 0255                var streams = new Stream[2 + (_nestedContent.Count * 2)];
 0256                int streamIndex = 0;
 257
 258                // Start boundary.
 0259                streams[streamIndex++] = new MemoryStream(_startBoundaryBytes, writable: false);
 260
 261                // Each nested content.
 0262                for (int contentIndex = 0; contentIndex < _nestedContent.Count; contentIndex++)
 0263                {
 0264                    cancellationToken.ThrowIfCancellationRequested();
 265
 0266                    HttpContent nestedContent = _nestedContent[contentIndex];
 0267                    streams[streamIndex++] = EncodeHeadersToNewStream(nestedContent, writeDivider: contentIndex != 0);
 268
 269                    Stream readStream;
 0270                    if (async)
 0271                    {
 0272                        readStream = nestedContent.TryReadAsStream() ?? await nestedContent.ReadAsStreamAsync(cancellati
 0273                    }
 274                    else
 0275                    {
 0276                        readStream = nestedContent.ReadAsStream(cancellationToken);
 0277                    }
 278                    // Cannot be null, at least an empty stream is necessary.
 0279                    readStream ??= new MemoryStream();
 280
 0281                    if (!readStream.CanSeek)
 0282                    {
 283                        // Seekability impacts whether HttpClientHandlers are able to rewind. To maintain compat
 284                        // and to allow such use cases when a nested stream isn't seekable (which should be rare),
 285                        // we fall back to the base behavior. We don't dispose of the streams already obtained
 286                        // as we don't necessarily own them yet.
 287
 288#pragma warning disable CA2016
 289                        // Do not pass a cancellationToken to base.CreateContentReadStreamAsync() as it would trigger an
 0290                        return async ? await base.CreateContentReadStreamAsync().ConfigureAwait(false) : base.CreateCont
 291#pragma warning restore CA2016
 292                    }
 0293                    streams[streamIndex++] = readStream;
 0294                }
 295
 296                // Footer boundary.
 0297                streams[streamIndex] = new MemoryStream(_endBoundaryBytes, writable: false);
 298
 0299                return new ContentReadStream(streams);
 300            }
 0301            catch (Exception ex)
 0302            {
 0303                if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(this, ex);
 0304                throw;
 305            }
 0306        }
 307
 308        private void SerializeHeadersToStream(Stream stream, HttpContent content, bool writeDivider)
 0309        {
 310            // Add divider.
 0311            if (writeDivider) // Write divider for all but the first content.
 0312            {
 0313                stream.Write(CrLfBytes);
 0314                stream.Write(_startBoundaryBytes);
 0315            }
 316
 317            // Add headers.
 0318            foreach (KeyValuePair<string, HeaderStringValues> headerPair in content.Headers.NonValidated)
 0319            {
 0320                Encoding headerValueEncoding = HeaderEncodingSelector?.Invoke(headerPair.Key, content) ?? HttpRuleParser
 321
 0322                WriteToStream(stream, headerPair.Key);
 0323                WriteToStream(stream, ": ");
 0324                string delim = string.Empty;
 0325                foreach (string value in headerPair.Value)
 0326                {
 0327                    WriteToStream(stream, delim);
 0328                    WriteToStream(stream, value, headerValueEncoding);
 0329                    delim = ", ";
 0330                }
 0331                stream.Write(CrLfBytes);
 0332            }
 333
 334            // Extra CRLF to end headers (even if there are no headers).
 0335            stream.Write(CrLfBytes);
 0336        }
 337
 338        private MemoryStream EncodeHeadersToNewStream(HttpContent content, bool writeDivider)
 0339        {
 0340            var stream = new MemoryStream();
 0341            SerializeHeadersToStream(stream, content, writeDivider);
 0342            stream.Position = 0;
 0343            return stream;
 0344        }
 345
 0346        internal override bool AllowDuplex => false;
 347
 348        protected internal override bool TryComputeLength(out long length)
 0349        {
 350            // Start Boundary.
 0351            long currentLength = _startBoundaryBytes.Length;
 352
 0353            if (_nestedContent.Count > 1)
 0354            {
 355                // Internal boundaries
 0356                currentLength += (_nestedContent.Count - 1) * (CrLfBytes.Length + _startBoundaryBytes.Length);
 0357            }
 358
 0359            foreach (HttpContent content in _nestedContent)
 0360            {
 361                // Headers.
 0362                foreach (KeyValuePair<string, HeaderStringValues> headerPair in content.Headers.NonValidated)
 0363                {
 0364                    currentLength += headerPair.Key.Length + ColonSpaceLength;
 365
 0366                    Encoding headerValueEncoding = HeaderEncodingSelector?.Invoke(headerPair.Key, content) ?? HttpRulePa
 367
 0368                    int valueCount = 0;
 0369                    foreach (string value in headerPair.Value)
 0370                    {
 0371                        currentLength += headerValueEncoding.GetByteCount(value);
 0372                        valueCount++;
 0373                    }
 374
 0375                    if (valueCount > 1)
 0376                    {
 0377                        currentLength += (valueCount - 1) * CommaSpaceLength;
 0378                    }
 379
 0380                    currentLength += CrLfBytes.Length;
 0381                }
 382
 0383                currentLength += CrLfBytes.Length;
 384
 385                // Content.
 0386                if (!content.TryComputeLength(out long tempContentLength))
 0387                {
 0388                    length = 0;
 0389                    return false;
 390                }
 0391                currentLength += tempContentLength;
 0392            }
 393
 394            // Terminating boundary.
 0395            currentLength += _endBoundaryBytes.Length;
 396
 0397            length = currentLength;
 0398            return true;
 0399        }
 400
 401        private sealed class ContentReadStream : Stream
 402        {
 403            private readonly Stream[] _streams;
 404            private readonly long _length;
 405
 406            private int _next;
 407            private Stream? _current;
 408            private long _position;
 409
 0410            internal ContentReadStream(Stream[] streams)
 0411            {
 0412                Debug.Assert(streams != null);
 0413                _streams = streams;
 0414                foreach (Stream stream in streams)
 0415                {
 0416                    _length += stream.Length;
 0417                }
 0418            }
 419
 420            protected override void Dispose(bool disposing)
 0421            {
 0422                if (disposing)
 0423                {
 0424                    foreach (Stream s in _streams)
 0425                    {
 0426                        s.Dispose();
 0427                    }
 0428                }
 0429            }
 430
 431            public override async ValueTask DisposeAsync()
 0432            {
 0433                foreach (Stream s in _streams)
 0434                {
 0435                    await s.DisposeAsync().ConfigureAwait(false);
 0436                }
 0437            }
 438
 0439            public override bool CanRead => true;
 0440            public override bool CanSeek => true;
 0441            public override bool CanWrite => false;
 442
 443            public override int Read(byte[] buffer, int offset, int count)
 0444            {
 0445                ValidateBufferArguments(buffer, offset, count);
 0446                if (count == 0)
 0447                {
 0448                    return 0;
 449                }
 450
 0451                while (true)
 0452                {
 0453                    if (_current != null)
 0454                    {
 0455                        int bytesRead = _current.Read(buffer, offset, count);
 0456                        if (bytesRead != 0)
 0457                        {
 0458                            _position += bytesRead;
 0459                            return bytesRead;
 460                        }
 461
 0462                        _current = null;
 0463                    }
 464
 0465                    if (_next >= _streams.Length)
 0466                    {
 0467                        return 0;
 468                    }
 469
 0470                    _current = _streams[_next++];
 0471                }
 0472            }
 473
 474            public override int ReadByte()
 0475            {
 0476                byte b = 0;
 0477                return Read(new Span<byte>(ref b)) == 1 ? b : -1;
 0478            }
 479
 480            public override int Read(Span<byte> buffer)
 0481            {
 0482                if (buffer.Length == 0)
 0483                {
 0484                    return 0;
 485                }
 486
 0487                while (true)
 0488                {
 0489                    if (_current != null)
 0490                    {
 0491                        int bytesRead = _current.Read(buffer);
 0492                        if (bytesRead != 0)
 0493                        {
 0494                            _position += bytesRead;
 0495                            return bytesRead;
 496                        }
 497
 0498                        _current = null;
 0499                    }
 500
 0501                    if (_next >= _streams.Length)
 0502                    {
 0503                        return 0;
 504                    }
 505
 0506                    _current = _streams[_next++];
 0507                }
 0508            }
 509
 510            public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToke
 0511            {
 0512                ValidateBufferArguments(buffer, offset, count);
 0513                return ReadAsyncPrivate(new Memory<byte>(buffer, offset, count), cancellationToken).AsTask();
 0514            }
 515
 516            public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
 0517                ReadAsyncPrivate(buffer, cancellationToken);
 518
 519            public override IAsyncResult BeginRead(byte[] array, int offset, int count, AsyncCallback? asyncCallback, ob
 0520                TaskToAsyncResult.Begin(ReadAsync(array, offset, count, CancellationToken.None), asyncCallback, asyncSta
 521
 522            public override int EndRead(IAsyncResult asyncResult) =>
 0523                TaskToAsyncResult.End<int>(asyncResult);
 524
 525            public async ValueTask<int> ReadAsyncPrivate(Memory<byte> buffer, CancellationToken cancellationToken)
 0526            {
 0527                if (buffer.Length == 0)
 0528                {
 0529                    return 0;
 530                }
 531
 0532                while (true)
 0533                {
 0534                    if (_current != null)
 0535                    {
 0536                        int bytesRead = await _current.ReadAsync(buffer, cancellationToken).ConfigureAwait(false);
 0537                        if (bytesRead != 0)
 0538                        {
 0539                            _position += bytesRead;
 0540                            return bytesRead;
 541                        }
 542
 0543                        _current = null;
 0544                    }
 545
 0546                    if (_next >= _streams.Length)
 0547                    {
 0548                        return 0;
 549                    }
 550
 0551                    _current = _streams[_next++];
 0552                }
 0553            }
 554
 555            public override long Position
 556            {
 0557                get { return _position; }
 558                set
 0559                {
 0560                    ArgumentOutOfRangeException.ThrowIfNegative(value);
 561
 0562                    long previousStreamsLength = 0;
 0563                    for (int i = 0; i < _streams.Length; i++)
 0564                    {
 0565                        Stream curStream = _streams[i];
 0566                        long curLength = curStream.Length;
 567
 0568                        if (value < previousStreamsLength + curLength)
 0569                        {
 0570                            _current = curStream;
 0571                            i++;
 0572                            _next = i;
 573
 0574                            curStream.Position = value - previousStreamsLength;
 0575                            for (; i < _streams.Length; i++)
 0576                            {
 0577                                _streams[i].Position = 0;
 0578                            }
 579
 0580                            _position = value;
 0581                            return;
 582                        }
 583
 0584                        previousStreamsLength += curLength;
 0585                    }
 586
 0587                    _current = null;
 0588                    _next = _streams.Length;
 0589                    _position = value;
 0590                }
 591            }
 592
 593            public override long Seek(long offset, SeekOrigin origin)
 0594            {
 0595                switch (origin)
 596                {
 597                    case SeekOrigin.Begin:
 0598                        Position = offset;
 0599                        break;
 600
 601                    case SeekOrigin.Current:
 0602                        Position += offset;
 0603                        break;
 604
 605                    case SeekOrigin.End:
 0606                        Position = _length + offset;
 0607                        break;
 608
 609                    default:
 0610                        throw new ArgumentOutOfRangeException(nameof(origin));
 611                }
 612
 0613                return Position;
 0614            }
 615
 0616            public override long Length => _length;
 617
 0618            public override void Flush() { }
 0619            public override Task FlushAsync(CancellationToken cancellationToken) => Task.CompletedTask;
 620
 0621            public override void SetLength(long value) { throw new NotSupportedException(); }
 0622            public override void Write(byte[] buffer, int offset, int count) { throw new NotSupportedException(); }
 0623            public override void Write(ReadOnlySpan<byte> buffer) { throw new NotSupportedException(); }
 0624            public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) {
 0625            public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = defa
 626        }
 627
 628
 629        private static void WriteToStream(Stream stream, string content) =>
 0630            WriteToStream(stream, content, HttpRuleParser.DefaultHttpEncoding);
 631
 632        private static void WriteToStream(Stream stream, string content, Encoding encoding)
 0633        {
 634            const int StackallocThreshold = 1024;
 635
 0636            int maxLength = encoding.GetMaxByteCount(content.Length);
 637
 0638            byte[]? rentedBuffer = null;
 0639            Span<byte> buffer = maxLength <= StackallocThreshold
 0640                ? stackalloc byte[StackallocThreshold]
 0641                : (rentedBuffer = ArrayPool<byte>.Shared.Rent(maxLength));
 642
 643            try
 0644            {
 0645                int written = encoding.GetBytes(content, buffer);
 0646                stream.Write(buffer.Slice(0, written));
 0647            }
 648            finally
 0649            {
 0650                if (rentedBuffer != null)
 0651                {
 0652                    ArrayPool<byte>.Shared.Return(rentedBuffer);
 0653                }
 0654            }
 0655        }
 656
 657        #endregion Serialization
 658    }
 659}
 660

Methods/Properties

.cctor()
.ctor()
.ctor(System.String)
.ctor(System.String,System.String)
ValidateBoundary(System.String)
GetDefaultBoundary()
Add(System.Net.Http.HttpContent)
Dispose(System.Boolean)
GetEnumerator()
System.Collections.IEnumerable.GetEnumerator()
HeaderEncodingSelector()
SerializeToStream(System.IO.Stream,System.Net.TransportContext,System.Threading.CancellationToken)
SerializeToStreamAsync(System.IO.Stream,System.Net.TransportContext)
SerializeToStreamAsync(System.IO.Stream,System.Net.TransportContext,System.Threading.CancellationToken)
SerializeToStreamAsyncCore(System.IO.Stream,System.Net.TransportContext,System.Threading.CancellationToken)
CreateContentReadStream(System.Threading.CancellationToken)
CreateContentReadStreamAsync()
CreateContentReadStreamAsync(System.Threading.CancellationToken)
CreateContentReadStreamAsyncCore(System.Boolean,System.Threading.CancellationToken)
SerializeHeadersToStream(System.IO.Stream,System.Net.Http.HttpContent,System.Boolean)
EncodeHeadersToNewStream(System.Net.Http.HttpContent,System.Boolean)
AllowDuplex()
TryComputeLength(System.Int64&)
.ctor(System.IO.Stream[])
Dispose(System.Boolean)
DisposeAsync()
CanRead()
CanSeek()
CanWrite()
Read(System.Byte[],System.Int32,System.Int32)
ReadByte()
Read(System.Span`1<System.Byte>)
ReadAsync(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken)
ReadAsync(System.Memory`1<System.Byte>,System.Threading.CancellationToken)
BeginRead(System.Byte[],System.Int32,System.Int32,System.AsyncCallback,System.Object)
EndRead(System.IAsyncResult)
ReadAsyncPrivate(System.Memory`1<System.Byte>,System.Threading.CancellationToken)
Position()
Position(System.Int64)
Seek(System.Int64,System.IO.SeekOrigin)
Length()
Flush()
FlushAsync(System.Threading.CancellationToken)
SetLength(System.Int64)
Write(System.Byte[],System.Int32,System.Int32)
Write(System.ReadOnlySpan`1<System.Byte>)
WriteAsync(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken)
WriteAsync(System.ReadOnlyMemory`1<System.Byte>,System.Threading.CancellationToken)
WriteToStream(System.IO.Stream,System.String)
WriteToStream(System.IO.Stream,System.String,System.Text.Encoding)