├── .DS_Store ├── LICENSE ├── README.md ├── assembly ├── unix-arm64 │ └── System.Net.Http.dll ├── unix-x64 │ └── System.Net.Http.dll └── windows-x64 │ └── System.Net.Http.dll ├── docker ├── .DS_Store ├── unix-arm64 │ ├── Dockerfile │ └── System.Net.Http.dll ├── unix-x64 │ ├── Dockerfile │ └── System.Net.Http.dll └── windows-x64 │ ├── Dockerfile │ └── System.Net.Http.dll └── src └── System.Net.Http ├── .vs └── System.Net.Http │ ├── DesignTimeBuild │ └── .dtbcache │ └── v16 │ ├── .suo │ └── Server │ └── sqlite3 │ ├── db.lock │ └── storage.ide ├── ConsoleApp1 ├── ConsoleApp1.csproj └── Program.cs ├── Directory.Build.props ├── System.Net.Http.sln ├── TestBypassSSL ├── Program.cs └── TestBypassSSL.csproj ├── ref ├── Configurations.props ├── System.Net.Http.cs └── System.Net.Http.csproj ├── src ├── Configurations.props ├── HttpDiagnosticsGuide.md ├── ILLinkTrim.xml ├── MatchingRefApiCompatBaseline.uap.txt ├── Resources │ └── Strings.resx ├── System.Net.Http.csproj ├── System │ └── Net │ │ └── Http │ │ ├── ByteArrayContent.cs │ │ ├── ByteArrayHelpers.cs │ │ ├── ClientCertificateOption.cs │ │ ├── CurlHandler │ │ ├── CurlException.cs │ │ ├── CurlHandler.ClientCertificateProvider.cs │ │ ├── CurlHandler.CurlResponseMessage.cs │ │ ├── CurlHandler.EasyRequest.cs │ │ ├── CurlHandler.MultiAgent.cs │ │ ├── CurlHandler.SslProvider.Linux.cs │ │ ├── CurlHandler.SslProvider.OSX.cs │ │ ├── CurlHandler.cs │ │ └── CurlResponseHeaderReader.cs │ │ ├── DelegatingHandler.cs │ │ ├── DiagnosticsHandler.cs │ │ ├── DiagnosticsHandlerLoggingStrings.cs │ │ ├── FormUrlEncodedContent.cs │ │ ├── Headers │ │ ├── AuthenticationHeaderValue.cs │ │ ├── BaseHeaderParser.cs │ │ ├── ByteArrayHeaderParser.cs │ │ ├── CacheControlHeaderParser.cs │ │ ├── CacheControlHeaderValue.cs │ │ ├── ContentDispositionHeaderValue.cs │ │ ├── ContentRangeHeaderValue.cs │ │ ├── DateHeaderParser.cs │ │ ├── EntityTagHeaderValue.cs │ │ ├── GenericHeaderParser.cs │ │ ├── HeaderDescriptor.cs │ │ ├── HeaderUtilities.cs │ │ ├── HttpContentHeaders.cs │ │ ├── HttpGeneralHeaders.cs │ │ ├── HttpHeaderParser.cs │ │ ├── HttpHeaderType.cs │ │ ├── HttpHeaderValueCollection.cs │ │ ├── HttpHeaders.cs │ │ ├── HttpRequestHeaders.cs │ │ ├── HttpResponseHeaders.cs │ │ ├── Int32NumberHeaderParser.cs │ │ ├── Int64NumberHeaderParser.cs │ │ ├── KnownHeader.cs │ │ ├── KnownHeaders.cs │ │ ├── MediaTypeHeaderParser.cs │ │ ├── MediaTypeHeaderValue.cs │ │ ├── MediaTypeWithQualityHeaderValue.cs │ │ ├── NameValueHeaderValue.cs │ │ ├── NameValueWithParametersHeaderValue.cs │ │ ├── ObjectCollection.cs │ │ ├── ProductHeaderValue.cs │ │ ├── ProductInfoHeaderParser.cs │ │ ├── ProductInfoHeaderValue.cs │ │ ├── RangeConditionHeaderValue.cs │ │ ├── RangeHeaderValue.cs │ │ ├── RangeItemHeaderValue.cs │ │ ├── RetryConditionHeaderValue.cs │ │ ├── StringWithQualityHeaderValue.cs │ │ ├── TimeSpanHeaderParser.cs │ │ ├── TransferCodingHeaderParser.cs │ │ ├── TransferCodingHeaderValue.cs │ │ ├── TransferCodingWithQualityHeaderValue.cs │ │ ├── UriHeaderParser.cs │ │ ├── ViaHeaderValue.cs │ │ └── WarningHeaderValue.cs │ │ ├── HttpClient.cs │ │ ├── HttpClientHandler.Core.cs │ │ ├── HttpClientHandler.Unix.cs │ │ ├── HttpClientHandler.Windows.cs │ │ ├── HttpClientHandler.cs │ │ ├── HttpClientHandler.netcoreapp.cs │ │ ├── HttpCompletionOption.cs │ │ ├── HttpContent.cs │ │ ├── HttpMessageHandler.cs │ │ ├── HttpMessageInvoker.cs │ │ ├── HttpMethod.cs │ │ ├── HttpParseResult.cs │ │ ├── HttpRequestException.cs │ │ ├── HttpRequestMessage.cs │ │ ├── HttpResponseMessage.cs │ │ ├── HttpRuleParser.cs │ │ ├── HttpUtilities.cs │ │ ├── MessageProcessingHandler.cs │ │ ├── MultipartContent.cs │ │ ├── MultipartFormDataContent.cs │ │ ├── NetEventSource.Http.cs │ │ ├── ReadOnlyMemoryContent.cs │ │ ├── SocketsHttpHandler │ │ ├── ArrayBuffer.cs │ │ ├── AuthenticationHelper.Digest.cs │ │ ├── AuthenticationHelper.NtAuth.cs │ │ ├── AuthenticationHelper.cs │ │ ├── CancellationHelper.cs │ │ ├── ChunkedEncodingReadStream.cs │ │ ├── ChunkedEncodingWriteStream.cs │ │ ├── ConnectHelper.cs │ │ ├── ConnectionCloseReadStream.cs │ │ ├── ContentLengthReadStream.cs │ │ ├── ContentLengthWriteStream.cs │ │ ├── CookieHelper.cs │ │ ├── CreditManager.cs │ │ ├── DecompressionHandler.cs │ │ ├── EmptyReadStream.cs │ │ ├── ExposedSocketNetworkStream.cs │ │ ├── HPack │ │ │ ├── DynamicTable.cs │ │ │ ├── HPackDecoder.cs │ │ │ ├── HPackDecodingException.cs │ │ │ ├── HPackEncoder.cs │ │ │ ├── HeaderField.cs │ │ │ ├── Huffman.cs │ │ │ ├── HuffmanDecodingException.cs │ │ │ ├── IntegerDecoder.cs │ │ │ ├── IntegerEncoder.cs │ │ │ └── StaticTable.cs │ │ ├── Http2Connection.cs │ │ ├── Http2ConnectionException.cs │ │ ├── Http2ProtocolErrorCode.cs │ │ ├── Http2ProtocolException.cs │ │ ├── Http2Stream.cs │ │ ├── Http2StreamException.cs │ │ ├── HttpAuthenticatedConnectionHandler.cs │ │ ├── HttpBaseStream.cs │ │ ├── HttpConnection.cs │ │ ├── HttpConnectionBase.cs │ │ ├── HttpConnectionHandler.cs │ │ ├── HttpConnectionKind.cs │ │ ├── HttpConnectionPool.cs │ │ ├── HttpConnectionPoolManager.cs │ │ ├── HttpConnectionResponseContent.cs │ │ ├── HttpConnectionSettings.cs │ │ ├── HttpContentReadStream.cs │ │ ├── HttpContentStream.cs │ │ ├── HttpContentWriteStream.cs │ │ ├── HttpEnvironmentProxy.Unix.cs │ │ ├── HttpEnvironmentProxy.Windows.cs │ │ ├── HttpEnvironmentProxy.cs │ │ ├── HttpNoProxy.cs │ │ ├── HttpWindowsProxy.cs │ │ ├── IHttpTrace.cs │ │ ├── MacProxy.cs │ │ ├── RawConnectionStream.cs │ │ ├── RedirectHandler.cs │ │ ├── SocketsHttpHandler.cs │ │ ├── SystemProxyInfo.OSX.cs │ │ ├── SystemProxyInfo.Unix.cs │ │ ├── SystemProxyInfo.Windows.cs │ │ ├── SystemProxyInfo.cs │ │ ├── SystemProxyInfo.uap.cs │ │ └── TaskCompletionSourceWithCancellation.cs │ │ ├── StreamContent.cs │ │ ├── StreamToStreamCopy.cs │ │ └── StringContent.cs └── uap │ └── System │ └── Net │ ├── CookieHelper.cs │ ├── HttpClientHandler.cs │ ├── HttpHandlerToFilter.cs │ ├── cookie.cs │ └── cookieexception.cs └── tests ├── FunctionalTests ├── ByteArrayContentTest.cs ├── ByteAtATimeContent.cs ├── ChannelBindingAwareContent.cs ├── Configurations.props ├── CustomContent.cs ├── CustomContent.netcore.cs ├── DefaultCredentialsTest.cs ├── DelegatingHandlerTest.cs ├── DiagnosticsTests.cs ├── DribbleStream.cs ├── FakeDiagnosticSourceListenerObserver.cs ├── FormUrlEncodedContentTest.cs ├── HPackTest.cs ├── HttpClient.SelectedSitesTest.cs ├── HttpClientEKUTest.cs ├── HttpClientHandlerTest.AcceptAllCerts.cs ├── HttpClientHandlerTest.Asynchrony.cs ├── HttpClientHandlerTest.Authentication.cs ├── HttpClientHandlerTest.AutoRedirect.cs ├── HttpClientHandlerTest.Cancellation.cs ├── HttpClientHandlerTest.ClientCertificates.cs ├── HttpClientHandlerTest.Cookies.cs ├── HttpClientHandlerTest.Decompression.cs ├── HttpClientHandlerTest.DefaultProxyCredentials.cs ├── HttpClientHandlerTest.Finalization.cs ├── HttpClientHandlerTest.Headers.cs ├── HttpClientHandlerTest.Http1.cs ├── HttpClientHandlerTest.Http2.cs ├── HttpClientHandlerTest.MaxConnectionsPerServer.cs ├── HttpClientHandlerTest.MaxResponseHeadersLength.cs ├── HttpClientHandlerTest.Proxy.cs ├── HttpClientHandlerTest.ResponseDrain.cs ├── HttpClientHandlerTest.ServerCertificates.Unix.cs ├── HttpClientHandlerTest.ServerCertificates.Windows.cs ├── HttpClientHandlerTest.ServerCertificates.cs ├── HttpClientHandlerTest.SslProtocols.Unix.cs ├── HttpClientHandlerTest.SslProtocols.Windows.cs ├── HttpClientHandlerTest.SslProtocols.cs ├── HttpClientHandlerTest.cs ├── HttpClientHandlerTestBase.cs ├── HttpClientMiniStressTest.cs ├── HttpClientTest.cs ├── HttpClientTest.netcoreapp.cs ├── HttpContentTest.cs ├── HttpMessageInvokerTest.cs ├── HttpMethodTest.cs ├── HttpMethodTest.netcoreapp.cs ├── HttpProtocolTests.cs ├── HttpRequestMessageTest.cs ├── HttpResponseMessageTest.cs ├── HttpRetryProtocolTests.cs ├── IdnaProtocolTests.cs ├── MessageProcessingHandlerTest.cs ├── MultiInterfaceNonRewindableReadOnlyStream.cs ├── MultiInterfaceReadOnlyStream.cs ├── MultiInterfaceStreamContent.cs ├── MultipartContentTest.cs ├── MultipartFormDataContentTest.cs ├── NtAuthTests.cs ├── PlatformHandlerTest.cs ├── PostScenarioTest.cs ├── PostScenarioUWPTest.cs ├── Properties │ └── launchSettings.json ├── ReadOnlyMemoryContentTest.cs ├── RepeatedFlushContent.cs ├── ResponseStreamTest.cs ├── SchSendAuxRecordHttpTest.cs ├── SelectedSitesTest.txt ├── SocketsHttpHandlerTest.cs ├── StreamContentTest.cs ├── StringContentTest.cs ├── SyncBlockingContent.cs ├── System.Net.Http.Functional.Tests.csproj ├── TestHelper.cs ├── ThrowingContent.cs ├── Watchdog.cs ├── XUnitAssemblyAttributes.cs └── prerequisites │ ├── ShowIdentity.ashx │ ├── Web.config │ └── readme.txt ├── StressTests └── HttpStress │ ├── Directory.Build.props │ ├── Directory.Build.targets │ ├── HttpStress.csproj │ ├── HttpStress.sln │ └── Program.cs └── UnitTests ├── Configurations.props ├── DigestAuthenticationTests.cs ├── Fakes ├── HttpClientHandler.cs └── MacProxy.cs ├── HPack ├── HPackDecoderTest.cs ├── HPackIntegerTest.cs ├── HPackRoundtripTests.cs └── HuffmanDecodingTests.cs ├── Headers ├── AuthenticationHeaderValueTest.cs ├── ByteArrayHeaderParserTest.cs ├── CacheControlHeaderParserTest.cs ├── CacheControlHeaderValueTest.cs ├── ContentDispositionHeaderValueTest.cs ├── ContentRangeHeaderValueTest.cs ├── CurlResponseHeaderReaderTest.cs ├── DateHeaderParserTest.cs ├── EntityTagHeaderValueTest.cs ├── GenericHeaderParserTest │ ├── AuthenticationParserTest.cs │ ├── ContentRangeParserTest.cs │ ├── EntityTagParserTest.cs │ ├── HostParserTest.cs │ ├── MailAddressParserTest.cs │ ├── NameValueParserTest.cs │ ├── NameValueWithParametersParserTest.cs │ ├── ProductParserTest.cs │ ├── RangeConditionParserTest.cs │ ├── RangeParserTest.cs │ ├── RetryConditionParserTest.cs │ ├── StringWithQualityParserTest.cs │ ├── TokenListParserTest.cs │ ├── ViaParserTest.cs │ └── WarningParserTest.cs ├── HeaderUtilitiesTest.cs ├── HttpContentHeadersTest.cs ├── HttpHeaderValueCollectionTest.cs ├── HttpHeadersTest.cs ├── HttpRequestHeadersTest.cs ├── HttpResponseHeadersTest.cs ├── Int32NumberHeaderParserTest.cs ├── Int64NumberHeaderParserTest.cs ├── MediaTypeHeaderParserTest.cs ├── MediaTypeHeaderValueTest.cs ├── MediaTypeWithQualityHeaderValueTest.cs ├── NameValueHeaderValueTest.cs ├── NameValueWithParametersHeaderValueTest.cs ├── ObjectCollectionTest.cs ├── ProductHeaderValueTest.cs ├── ProductInfoHeaderParserTest.cs ├── ProductInfoHeaderValueTest.cs ├── RangeConditionHeaderValueTest.cs ├── RangeHeaderValueTest.cs ├── RangeItemHeaderValueTest.cs ├── RetryConditionHeaderValueTest.cs ├── StringWithQualityHeaderValueTest.cs ├── TimeSpanHeaderParserTest.cs ├── TransferCodingHeaderParserTest.cs ├── TransferCodingHeaderValueTest.cs ├── TransferCodingWithQualityHeaderValueTest.cs ├── UriHeaderParserTest.cs ├── ViaHeaderValueTest.cs └── WarningHeaderValueTest.cs ├── HttpContentTest.cs ├── HttpEnvironmentProxyTest.cs ├── HttpRuleParserTest.cs ├── HttpWindowsProxyTest.cs ├── MockContent.cs ├── Properties └── launchSettings.json ├── StreamToStreamCopyTest.cs ├── System.Net.Http.Unit.Tests.csproj └── SystemProxyInfoTest.cs /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultranijia/EmbyCrack/edb5e2b0319e750b75fd028e30e904d21135b002/.DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Yukino 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EmbyCracked 2 | 3 | ## Feature 4 | + 破解 Emby 高级版验证 5 | + 修改了默认插件源,加速中国用户下载插件 6 | + docker 一键安装 7 | 8 | ## Usage 9 | 10 | ### 手动替换 11 | + **注意**:如果以前使用其他破解方案,必须将系统的 hosts 的 mb3admin.com www.mb3admin.com 条目删除,否则破解不会生效 12 | + 将 [破解程序集](https://github.com/YukiCoco/EmbyCrack/tree/master/assembly) 替换原有文件即完成破解,原有文件路径为 `system/System.Net.Http.dll` 13 | + 客户端使用: 14 | + 浏览器:安装 [URLRedirector]() 插件,将 `https://mb3admin.com` 替换为 `http://crackemby.neko.re` 15 | + Android & Android TV:直接使用破解版,自己找找就有了 16 | + 详细使用方法移步[这里](https://neko.re/archives/128.html) 17 | 18 | ### 使用 Docker 19 | + `yukinococo/emby_crack:unix-x64`(Unix) 20 | + `yukinococo/emby_crack:windows-x64` (Windows) 21 | -------------------------------------------------------------------------------- /assembly/unix-arm64/System.Net.Http.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultranijia/EmbyCrack/edb5e2b0319e750b75fd028e30e904d21135b002/assembly/unix-arm64/System.Net.Http.dll -------------------------------------------------------------------------------- /assembly/unix-x64/System.Net.Http.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultranijia/EmbyCrack/edb5e2b0319e750b75fd028e30e904d21135b002/assembly/unix-x64/System.Net.Http.dll -------------------------------------------------------------------------------- /assembly/windows-x64/System.Net.Http.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultranijia/EmbyCrack/edb5e2b0319e750b75fd028e30e904d21135b002/assembly/windows-x64/System.Net.Http.dll -------------------------------------------------------------------------------- /docker/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultranijia/EmbyCrack/edb5e2b0319e750b75fd028e30e904d21135b002/docker/.DS_Store -------------------------------------------------------------------------------- /docker/unix-arm64/Dockerfile: -------------------------------------------------------------------------------- 1 | # Emby Server 2 | FROM emby/embyserver 3 | COPY ./System.Net.Http.dll /system/ -------------------------------------------------------------------------------- /docker/unix-arm64/System.Net.Http.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultranijia/EmbyCrack/edb5e2b0319e750b75fd028e30e904d21135b002/docker/unix-arm64/System.Net.Http.dll -------------------------------------------------------------------------------- /docker/unix-x64/Dockerfile: -------------------------------------------------------------------------------- 1 | # Emby Server 2 | FROM emby/embyserver 3 | COPY ./System.Net.Http.dll /system/ -------------------------------------------------------------------------------- /docker/unix-x64/System.Net.Http.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultranijia/EmbyCrack/edb5e2b0319e750b75fd028e30e904d21135b002/docker/unix-x64/System.Net.Http.dll -------------------------------------------------------------------------------- /docker/windows-x64/Dockerfile: -------------------------------------------------------------------------------- 1 | # Emby Server 2 | FROM emby/embyserver 3 | COPY ./System.Net.Http.dll /system/ -------------------------------------------------------------------------------- /docker/windows-x64/System.Net.Http.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultranijia/EmbyCrack/edb5e2b0319e750b75fd028e30e904d21135b002/docker/windows-x64/System.Net.Http.dll -------------------------------------------------------------------------------- /src/System.Net.Http/.vs/System.Net.Http/DesignTimeBuild/.dtbcache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultranijia/EmbyCrack/edb5e2b0319e750b75fd028e30e904d21135b002/src/System.Net.Http/.vs/System.Net.Http/DesignTimeBuild/.dtbcache -------------------------------------------------------------------------------- /src/System.Net.Http/.vs/System.Net.Http/v16/.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultranijia/EmbyCrack/edb5e2b0319e750b75fd028e30e904d21135b002/src/System.Net.Http/.vs/System.Net.Http/v16/.suo -------------------------------------------------------------------------------- /src/System.Net.Http/.vs/System.Net.Http/v16/Server/sqlite3/db.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultranijia/EmbyCrack/edb5e2b0319e750b75fd028e30e904d21135b002/src/System.Net.Http/.vs/System.Net.Http/v16/Server/sqlite3/db.lock -------------------------------------------------------------------------------- /src/System.Net.Http/.vs/System.Net.Http/v16/Server/sqlite3/storage.ide: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultranijia/EmbyCrack/edb5e2b0319e750b75fd028e30e904d21135b002/src/System.Net.Http/.vs/System.Net.Http/v16/Server/sqlite3/storage.ide -------------------------------------------------------------------------------- /src/System.Net.Http/ConsoleApp1/ConsoleApp1.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/System.Net.Http/ConsoleApp1/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ConsoleApp1 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | Console.WriteLine("Hello World!"); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/System.Net.Http/Directory.Build.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 4.2.2.0 5 | Microsoft 6 | true 7 | true 8 | 9 | -------------------------------------------------------------------------------- /src/System.Net.Http/TestBypassSSL/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net.Http; 3 | 4 | namespace TestBypassSSL 5 | { 6 | class Program 7 | { 8 | static void Main(string[] args) 9 | { 10 | //Console.WriteLine("Hello World!"); 11 | HttpClient httpClient = new HttpClient(); 12 | var result = httpClient.GetAsync("https://mb3admin.com/").Result; 13 | Console.WriteLine(result.Content.ReadAsStringAsync().Result); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/System.Net.Http/TestBypassSSL/TestBypassSSL.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/System.Net.Http/ref/Configurations.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp; 5 | uap; 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/System.Net.Http/ref/System.Net.Http.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | {132BF813-FC40-4D39-8B6F-E55D7633F0ED} 4 | netcoreapp-Debug;netcoreapp-Release;uap-Debug;uap-Release 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/Configurations.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | uap-Windows_NT; 5 | netcoreapp-OSX; 6 | netcoreapp-Unix; 7 | netcoreapp-Windows_NT; 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/ILLinkTrim.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/MatchingRefApiCompatBaseline.uap.txt: -------------------------------------------------------------------------------- 1 | Compat issues with assembly System.Net.Http: 2 | TypesMustExist : Type 'System.Net.Internal.Cookie' does not exist in the reference but it does exist in the implementation. 3 | TypesMustExist : Type 'System.Net.Internal.CookieException' does not exist in the reference but it does exist in the implementation. 4 | Total Issues: 2 5 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/ByteArrayContent.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | using System.IO; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | 10 | namespace System.Net.Http 11 | { 12 | public class ByteArrayContent : HttpContent 13 | { 14 | private readonly byte[] _content; 15 | private readonly int _offset; 16 | private readonly int _count; 17 | 18 | public ByteArrayContent(byte[] content) 19 | { 20 | if (content == null) 21 | { 22 | throw new ArgumentNullException(nameof(content)); 23 | } 24 | 25 | _content = content; 26 | _offset = 0; 27 | _count = content.Length; 28 | 29 | SetBuffer(_content, _offset, _count); 30 | } 31 | 32 | public ByteArrayContent(byte[] content, int offset, int count) 33 | { 34 | if (content == null) 35 | { 36 | throw new ArgumentNullException(nameof(content)); 37 | } 38 | if ((offset < 0) || (offset > content.Length)) 39 | { 40 | throw new ArgumentOutOfRangeException(nameof(offset)); 41 | } 42 | if ((count < 0) || (count > (content.Length - offset))) 43 | { 44 | throw new ArgumentOutOfRangeException(nameof(count)); 45 | } 46 | 47 | _content = content; 48 | _offset = offset; 49 | _count = count; 50 | 51 | SetBuffer(_content, _offset, _count); 52 | } 53 | 54 | protected override Task SerializeToStreamAsync(Stream stream, TransportContext context) => 55 | SerializeToStreamAsyncCore(stream, default); 56 | 57 | internal override Task SerializeToStreamAsync(Stream stream, TransportContext context, CancellationToken cancellationToken) => 58 | // Only skip the original protected virtual SerializeToStreamAsync if this 59 | // isn't a derived type that may have overridden the behavior. 60 | GetType() == typeof(ByteArrayContent) ? SerializeToStreamAsyncCore(stream, cancellationToken) : 61 | base.SerializeToStreamAsync(stream, context, cancellationToken); 62 | 63 | private protected Task SerializeToStreamAsyncCore(Stream stream, CancellationToken cancellationToken) => 64 | stream.WriteAsync(_content, _offset, _count, cancellationToken); 65 | 66 | protected internal override bool TryComputeLength(out long length) 67 | { 68 | length = _count; 69 | return true; 70 | } 71 | 72 | protected override Task CreateContentReadStreamAsync() => 73 | Task.FromResult(CreateMemoryStreamForByteArray()); 74 | 75 | internal override Stream TryCreateContentReadStream() => 76 | GetType() == typeof(ByteArrayContent) ? CreateMemoryStreamForByteArray() : // type check ensures we use possible derived type's CreateContentReadStreamAsync override 77 | null; 78 | 79 | internal MemoryStream CreateMemoryStreamForByteArray() => new MemoryStream(_content, _offset, _count, writable: false); 80 | 81 | internal override bool AllowDuplex => false; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/ByteArrayHelpers.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | 7 | namespace System 8 | { 9 | internal static class ByteArrayHelpers 10 | { 11 | internal static bool EqualsOrdinalAsciiIgnoreCase(string left, ReadOnlySpan right) 12 | { 13 | Debug.Assert(left != null, "Expected non-null string"); 14 | 15 | if (left.Length != right.Length) 16 | { 17 | return false; 18 | } 19 | 20 | for (int i = 0; i < left.Length; i++) 21 | { 22 | uint charA = left[i]; 23 | uint charB = right[i]; 24 | 25 | unchecked 26 | { 27 | // We're only interested in ASCII characters here. 28 | if ((charA - 'a') <= ('z' - 'a')) 29 | charA -= ('a' - 'A'); 30 | if ((charB - 'a') <= ('z' - 'a')) 31 | charB -= ('a' - 'A'); 32 | } 33 | 34 | if (charA != charB) 35 | { 36 | return false; 37 | } 38 | } 39 | 40 | return true; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/ClientCertificateOption.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace System.Net.Http 6 | { 7 | public enum ClientCertificateOption 8 | { 9 | Manual = 0, 10 | Automatic, 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/CurlHandler/CurlException.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Runtime.InteropServices; 6 | 7 | namespace System.Net.Http 8 | { 9 | internal sealed class CurlException : Exception 10 | { 11 | internal CurlException(int error, string message) : base(message) 12 | { 13 | HResult = error; 14 | } 15 | 16 | internal CurlException(int error, Exception innerException) : base(GetCurlErrorString(error, isMulti:false), innerException) 17 | { 18 | HResult = error; 19 | } 20 | 21 | internal CurlException(int error, bool isMulti) : this(error, GetCurlErrorString(error, isMulti)) 22 | { 23 | } 24 | 25 | internal static string GetCurlErrorString(int code, bool isMulti) 26 | { 27 | IntPtr ptr = isMulti ? Interop.Http.MultiGetErrorString(code) : Interop.Http.EasyGetErrorString(code); 28 | return Marshal.PtrToStringAnsi(ptr); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/DelegatingHandler.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | using System.Threading; 9 | using System.Threading.Tasks; 10 | 11 | namespace System.Net.Http 12 | { 13 | public abstract class DelegatingHandler : HttpMessageHandler 14 | { 15 | private HttpMessageHandler _innerHandler; 16 | private volatile bool _operationStarted = false; 17 | private volatile bool _disposed = false; 18 | 19 | public HttpMessageHandler InnerHandler 20 | { 21 | get 22 | { 23 | return _innerHandler; 24 | } 25 | set 26 | { 27 | if (value == null) 28 | { 29 | throw new ArgumentNullException(nameof(value)); 30 | } 31 | CheckDisposedOrStarted(); 32 | 33 | if (NetEventSource.IsEnabled) NetEventSource.Associate(this, value); 34 | _innerHandler = value; 35 | } 36 | } 37 | 38 | protected DelegatingHandler() 39 | { 40 | } 41 | 42 | protected DelegatingHandler(HttpMessageHandler innerHandler) 43 | { 44 | InnerHandler = innerHandler; 45 | } 46 | 47 | protected internal override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 48 | { 49 | if (request == null) 50 | { 51 | throw new ArgumentNullException(nameof(request), SR.net_http_handler_norequest); 52 | } 53 | SetOperationStarted(); 54 | return _innerHandler.SendAsync(request, cancellationToken); 55 | } 56 | 57 | protected override void Dispose(bool disposing) 58 | { 59 | if (disposing && !_disposed) 60 | { 61 | _disposed = true; 62 | if (_innerHandler != null) 63 | { 64 | _innerHandler.Dispose(); 65 | } 66 | } 67 | 68 | base.Dispose(disposing); 69 | } 70 | 71 | private void CheckDisposed() 72 | { 73 | if (_disposed) 74 | { 75 | throw new ObjectDisposedException(GetType().ToString()); 76 | } 77 | } 78 | 79 | private void CheckDisposedOrStarted() 80 | { 81 | CheckDisposed(); 82 | if (_operationStarted) 83 | { 84 | throw new InvalidOperationException(SR.net_http_operation_started); 85 | } 86 | } 87 | 88 | private void SetOperationStarted() 89 | { 90 | CheckDisposed(); 91 | if (_innerHandler == null) 92 | { 93 | throw new InvalidOperationException(SR.net_http_handler_not_assigned); 94 | } 95 | // This method flags the handler instances as "active". I.e. we executed at least one request (or are 96 | // in the process of doing so). This information is used to lock-down all property setters. Once a 97 | // Send/SendAsync operation started, no property can be changed. 98 | if (!_operationStarted) 99 | { 100 | _operationStarted = true; 101 | } 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/DiagnosticsHandlerLoggingStrings.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace System.Net.Http 6 | { 7 | /// 8 | /// Defines names of DiagnosticListener and Write events for WinHttpHandler, CurlHandler, and HttpHandlerToFilter. 9 | /// 10 | internal static class DiagnosticsHandlerLoggingStrings 11 | { 12 | public const string DiagnosticListenerName = "HttpHandlerDiagnosticListener"; 13 | public const string RequestWriteNameDeprecated = "System.Net.Http.Request"; 14 | public const string ResponseWriteNameDeprecated = "System.Net.Http.Response"; 15 | 16 | public const string ExceptionEventName = "System.Net.Http.Exception"; 17 | public const string ActivityName = "System.Net.Http.HttpRequestOut"; 18 | public const string ActivityStartName = "System.Net.Http.HttpRequestOut.Start"; 19 | 20 | public const string RequestIdHeaderName = "Request-Id"; 21 | public const string CorrelationContextHeaderName = "Correlation-Context"; 22 | 23 | public const string TraceParentHeaderName = "traceparent"; 24 | public const string TraceStateHeaderName = "tracestate"; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/FormUrlEncodedContent.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using System.Net.Http.Headers; 8 | using System.Text; 9 | using System.Threading; 10 | using System.Threading.Tasks; 11 | 12 | namespace System.Net.Http 13 | { 14 | public class FormUrlEncodedContent : ByteArrayContent 15 | { 16 | public FormUrlEncodedContent(IEnumerable> nameValueCollection) 17 | : base(GetContentByteArray(nameValueCollection)) 18 | { 19 | Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded"); 20 | } 21 | 22 | private static byte[] GetContentByteArray(IEnumerable> nameValueCollection) 23 | { 24 | if (nameValueCollection == null) 25 | { 26 | throw new ArgumentNullException(nameof(nameValueCollection)); 27 | } 28 | 29 | // Encode and concatenate data 30 | StringBuilder builder = new StringBuilder(); 31 | foreach (KeyValuePair pair in nameValueCollection) 32 | { 33 | if (builder.Length > 0) 34 | { 35 | builder.Append('&'); 36 | } 37 | 38 | builder.Append(Encode(pair.Key)); 39 | builder.Append('='); 40 | builder.Append(Encode(pair.Value)); 41 | } 42 | 43 | return HttpRuleParser.DefaultHttpEncoding.GetBytes(builder.ToString()); 44 | } 45 | 46 | private static string Encode(string data) 47 | { 48 | if (string.IsNullOrEmpty(data)) 49 | { 50 | return string.Empty; 51 | } 52 | // Escape spaces as '+'. 53 | return Uri.EscapeDataString(data).Replace("%20", "+"); 54 | } 55 | 56 | internal override Task SerializeToStreamAsync(Stream stream, TransportContext context, CancellationToken cancellationToken) => 57 | // Only skip the original protected virtual SerializeToStreamAsync if this 58 | // isn't a derived type that may have overridden the behavior. 59 | GetType() == typeof(FormUrlEncodedContent) ? SerializeToStreamAsyncCore(stream, cancellationToken) : 60 | base.SerializeToStreamAsync(stream, context, cancellationToken); 61 | 62 | internal override Stream TryCreateContentReadStream() => 63 | GetType() == typeof(FormUrlEncodedContent) ? CreateMemoryStreamForByteArray() : // type check ensures we use possible derived type's CreateContentReadStreamAsync override 64 | null; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/Headers/BaseHeaderParser.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace System.Net.Http.Headers 8 | { 9 | internal abstract class BaseHeaderParser : HttpHeaderParser 10 | { 11 | protected BaseHeaderParser(bool supportsMultipleValues) 12 | : base(supportsMultipleValues) 13 | { 14 | } 15 | 16 | protected abstract int GetParsedValueLength(string value, int startIndex, object storeValue, 17 | out object parsedValue); 18 | 19 | public sealed override bool TryParseValue(string value, object storeValue, ref int index, 20 | out object parsedValue) 21 | { 22 | parsedValue = null; 23 | 24 | // If multiple values are supported (i.e. list of values), then accept an empty string: The header may 25 | // be added multiple times to the request/response message. E.g. 26 | // Accept: text/xml; q=1 27 | // Accept: 28 | // Accept: text/plain; q=0.2 29 | if (string.IsNullOrEmpty(value) || (index == value.Length)) 30 | { 31 | return SupportsMultipleValues; 32 | } 33 | 34 | bool separatorFound = false; 35 | int current = HeaderUtilities.GetNextNonEmptyOrWhitespaceIndex(value, index, SupportsMultipleValues, 36 | out separatorFound); 37 | 38 | if (separatorFound && !SupportsMultipleValues) 39 | { 40 | return false; // leading separators not allowed if we don't support multiple values. 41 | } 42 | 43 | if (current == value.Length) 44 | { 45 | if (SupportsMultipleValues) 46 | { 47 | index = current; 48 | } 49 | return SupportsMultipleValues; 50 | } 51 | 52 | object result = null; 53 | int length = GetParsedValueLength(value, current, storeValue, out result); 54 | 55 | if (length == 0) 56 | { 57 | return false; 58 | } 59 | 60 | current = current + length; 61 | current = HeaderUtilities.GetNextNonEmptyOrWhitespaceIndex(value, current, SupportsMultipleValues, 62 | out separatorFound); 63 | 64 | // If we support multiple values and we've not reached the end of the string, then we must have a separator. 65 | if ((separatorFound && !SupportsMultipleValues) || (!separatorFound && (current < value.Length))) 66 | { 67 | return false; 68 | } 69 | 70 | index = current; 71 | parsedValue = result; 72 | return true; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/Headers/ByteArrayHeaderParser.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | 7 | namespace System.Net.Http.Headers 8 | { 9 | // Don't derive from BaseHeaderParser since parsing the Base64 string is delegated to Convert.FromBase64String() 10 | // which will remove leading, trailing, and whitespace in the middle of the string. 11 | internal class ByteArrayHeaderParser : HttpHeaderParser 12 | { 13 | internal static readonly ByteArrayHeaderParser Parser = new ByteArrayHeaderParser(); 14 | 15 | private ByteArrayHeaderParser() 16 | : base(false) 17 | { 18 | } 19 | 20 | public override string ToString(object value) 21 | { 22 | Debug.Assert(value is byte[]); 23 | 24 | return Convert.ToBase64String((byte[])value); 25 | } 26 | 27 | public override bool TryParseValue(string value, object storeValue, ref int index, out object parsedValue) 28 | { 29 | parsedValue = null; 30 | 31 | // Some headers support empty/null values. This one doesn't. 32 | if (string.IsNullOrEmpty(value) || (index == value.Length)) 33 | { 34 | return false; 35 | } 36 | 37 | string base64String = value; 38 | if (index > 0) 39 | { 40 | base64String = value.Substring(index); 41 | } 42 | 43 | // Try convert the string (we assume it's a valid Base64 string) to byte[]. 44 | try 45 | { 46 | parsedValue = Convert.FromBase64String(base64String); 47 | index = value.Length; 48 | return true; 49 | } 50 | catch (FormatException e) 51 | { 52 | if (NetEventSource.IsEnabled) NetEventSource.Error(this, SR.Format(SR.net_http_parser_invalid_base64_string, base64String, e.Message)); 53 | } 54 | 55 | return false; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/Headers/CacheControlHeaderParser.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | 7 | namespace System.Net.Http.Headers 8 | { 9 | internal class CacheControlHeaderParser : BaseHeaderParser 10 | { 11 | internal static readonly CacheControlHeaderParser Parser = new CacheControlHeaderParser(); 12 | 13 | // The Cache-Control header is special: It is a header supporting a list of values, but we represent the list 14 | // as _one_ instance of CacheControlHeaderValue. I.e we set 'SupportsMultipleValues' to 'true' since it is 15 | // OK to have multiple Cache-Control headers in a request/response message. However, after parsing all 16 | // Cache-Control headers, only one instance of CacheControlHeaderValue is created (if all headers contain valid 17 | // values, otherwise we may have multiple strings containing the invalid values). 18 | private CacheControlHeaderParser() 19 | : base(true) 20 | { 21 | } 22 | 23 | protected override int GetParsedValueLength(string value, int startIndex, object storeValue, 24 | out object parsedValue) 25 | { 26 | CacheControlHeaderValue temp = storeValue as CacheControlHeaderValue; 27 | Debug.Assert(storeValue == null || temp != null, "'storeValue' is not of type CacheControlHeaderValue"); 28 | 29 | int resultLength = CacheControlHeaderValue.GetCacheControlLength(value, startIndex, temp, out temp); 30 | 31 | parsedValue = temp; 32 | return resultLength; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/Headers/DateHeaderParser.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | 7 | namespace System.Net.Http.Headers 8 | { 9 | // Don't derive from BaseHeaderParser since parsing is delegated to DateTimeOffset.TryParseExact() 10 | // which will remove leading, trailing, and whitespace in the middle of the string. 11 | internal class DateHeaderParser : HttpHeaderParser 12 | { 13 | internal static readonly DateHeaderParser Parser = new DateHeaderParser(); 14 | 15 | private DateHeaderParser() 16 | : base(false) 17 | { 18 | } 19 | 20 | public override string ToString(object value) 21 | { 22 | Debug.Assert(value is DateTimeOffset); 23 | 24 | return HttpDateParser.DateToString((DateTimeOffset)value); 25 | } 26 | 27 | public override bool TryParseValue(string value, object storeValue, ref int index, out object parsedValue) 28 | { 29 | parsedValue = null; 30 | 31 | // Some headers support empty/null values. This one doesn't. 32 | if (string.IsNullOrEmpty(value) || (index == value.Length)) 33 | { 34 | return false; 35 | } 36 | 37 | ReadOnlySpan dateString = value; 38 | if (index > 0) 39 | { 40 | dateString = value.AsSpan(index); 41 | } 42 | 43 | DateTimeOffset date; 44 | if (!HttpDateParser.TryStringToDate(dateString, out date)) 45 | { 46 | return false; 47 | } 48 | 49 | index = value.Length; 50 | parsedValue = date; 51 | return true; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/Headers/HttpHeaderType.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace System.Net.Http.Headers 6 | { 7 | [Flags] 8 | internal enum HttpHeaderType : byte 9 | { 10 | General = 0b1, 11 | Request = 0b10, 12 | Response = 0b100, 13 | Content = 0b1000, 14 | Custom = 0b10000, 15 | 16 | All = 0b11111, 17 | None = 0 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/Headers/Int32NumberHeaderParser.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | using System.Globalization; 7 | 8 | namespace System.Net.Http.Headers 9 | { 10 | internal class Int32NumberHeaderParser : BaseHeaderParser 11 | { 12 | // Note that we don't need a custom comparer even though we have a value type that gets boxed (comparing two 13 | // equal boxed value types returns 'false' since the object instances used for boxing the two values are 14 | // different). The reason is that the comparer is only used by HttpHeaders when comparing values in a collection. 15 | // Value types are never used in collections (in fact HttpHeaderValueCollection expects T to be a reference 16 | // type). 17 | 18 | internal static readonly Int32NumberHeaderParser Parser = new Int32NumberHeaderParser(); 19 | 20 | private Int32NumberHeaderParser() 21 | : base(false) 22 | { 23 | } 24 | 25 | public override string ToString(object value) 26 | { 27 | Debug.Assert(value is int); 28 | 29 | return ((int)value).ToString(NumberFormatInfo.InvariantInfo); 30 | } 31 | 32 | protected override int GetParsedValueLength(string value, int startIndex, object storeValue, 33 | out object parsedValue) 34 | { 35 | parsedValue = null; 36 | 37 | int numberLength = HttpRuleParser.GetNumberLength(value, startIndex, false); 38 | 39 | if ((numberLength == 0) || (numberLength > HttpRuleParser.MaxInt32Digits)) 40 | { 41 | return 0; 42 | } 43 | 44 | int result = 0; 45 | if (!HeaderUtilities.TryParseInt32(value, startIndex, numberLength, out result)) 46 | { 47 | return 0; 48 | } 49 | 50 | parsedValue = result; 51 | return numberLength; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/Headers/Int64NumberHeaderParser.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | using System.Globalization; 7 | 8 | namespace System.Net.Http.Headers 9 | { 10 | internal class Int64NumberHeaderParser : BaseHeaderParser 11 | { 12 | // Note that we don't need a custom comparer even though we have a value type that gets boxed (comparing two 13 | // equal boxed value types returns 'false' since the object instances used for boxing the two values are 14 | // different). The reason is that the comparer is only used by HttpHeaders when comparing values in a collection. 15 | // Value types are never used in collections (in fact HttpHeaderValueCollection expects T to be a reference 16 | // type). 17 | 18 | internal static readonly Int64NumberHeaderParser Parser = new Int64NumberHeaderParser(); 19 | 20 | private Int64NumberHeaderParser() 21 | : base(false) 22 | { 23 | } 24 | 25 | public override string ToString(object value) 26 | { 27 | Debug.Assert(value is long); 28 | 29 | return ((long)value).ToString(NumberFormatInfo.InvariantInfo); 30 | } 31 | 32 | protected override int GetParsedValueLength(string value, int startIndex, object storeValue, 33 | out object parsedValue) 34 | { 35 | parsedValue = null; 36 | 37 | int numberLength = HttpRuleParser.GetNumberLength(value, startIndex, false); 38 | 39 | if ((numberLength == 0) || (numberLength > HttpRuleParser.MaxInt64Digits)) 40 | { 41 | return 0; 42 | } 43 | 44 | long result = 0; 45 | if (!HeaderUtilities.TryParseInt64(value, startIndex, numberLength, out result)) 46 | { 47 | return 0; 48 | } 49 | 50 | parsedValue = result; 51 | return numberLength; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/Headers/KnownHeader.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | using System.Net.Http.HPack; 7 | using System.Text; 8 | 9 | namespace System.Net.Http.Headers 10 | { 11 | internal sealed class KnownHeader 12 | { 13 | public KnownHeader(string name, int? http2StaticTableIndex = null) : 14 | this(name, HttpHeaderType.Custom, parser: null, knownValues: null, http2StaticTableIndex) 15 | { 16 | Debug.Assert(!string.IsNullOrEmpty(name)); 17 | Debug.Assert(HttpRuleParser.GetTokenLength(name, 0) == name.Length); 18 | } 19 | 20 | public KnownHeader(string name, HttpHeaderType headerType, HttpHeaderParser parser, string[] knownValues = null, int? http2StaticTableIndex = null) 21 | { 22 | Debug.Assert(!string.IsNullOrEmpty(name)); 23 | Debug.Assert(HttpRuleParser.GetTokenLength(name, 0) == name.Length); 24 | Debug.Assert((headerType == HttpHeaderType.Custom) == (parser == null)); 25 | Debug.Assert(knownValues == null || headerType != HttpHeaderType.Custom); 26 | 27 | Name = name; 28 | HeaderType = headerType; 29 | Parser = parser; 30 | KnownValues = knownValues; 31 | 32 | Http2EncodedName = http2StaticTableIndex.HasValue ? 33 | HPackEncoder.EncodeLiteralHeaderFieldWithoutIndexingToAllocatedArray(http2StaticTableIndex.GetValueOrDefault()) : 34 | HPackEncoder.EncodeLiteralHeaderFieldWithoutIndexingNewNameToAllocatedArray(name); 35 | 36 | var asciiBytesWithColonSpace = new byte[name.Length + 2]; // + 2 for ':' and ' ' 37 | int asciiBytes = Encoding.ASCII.GetBytes(name, asciiBytesWithColonSpace); 38 | Debug.Assert(asciiBytes == name.Length); 39 | asciiBytesWithColonSpace[asciiBytesWithColonSpace.Length - 2] = (byte)':'; 40 | asciiBytesWithColonSpace[asciiBytesWithColonSpace.Length - 1] = (byte)' '; 41 | AsciiBytesWithColonSpace = asciiBytesWithColonSpace; 42 | } 43 | 44 | public string Name { get; } 45 | public HttpHeaderParser Parser { get; } 46 | public HttpHeaderType HeaderType { get; } 47 | public string[] KnownValues { get; } 48 | public byte[] AsciiBytesWithColonSpace { get; } 49 | public HeaderDescriptor Descriptor => new HeaderDescriptor(this); 50 | public byte[] Http2EncodedName { get; } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/Headers/MediaTypeHeaderParser.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | 7 | namespace System.Net.Http.Headers 8 | { 9 | internal class MediaTypeHeaderParser : BaseHeaderParser 10 | { 11 | private bool _supportsMultipleValues; 12 | private Func _mediaTypeCreator; 13 | 14 | internal static readonly MediaTypeHeaderParser SingleValueParser = new MediaTypeHeaderParser(false, 15 | CreateMediaType); 16 | internal static readonly MediaTypeHeaderParser SingleValueWithQualityParser = new MediaTypeHeaderParser(false, 17 | CreateMediaTypeWithQuality); 18 | internal static readonly MediaTypeHeaderParser MultipleValuesParser = new MediaTypeHeaderParser(true, 19 | CreateMediaTypeWithQuality); 20 | 21 | private MediaTypeHeaderParser(bool supportsMultipleValues, Func mediaTypeCreator) 22 | : base(supportsMultipleValues) 23 | { 24 | Debug.Assert(mediaTypeCreator != null); 25 | 26 | _supportsMultipleValues = supportsMultipleValues; 27 | _mediaTypeCreator = mediaTypeCreator; 28 | } 29 | 30 | protected override int GetParsedValueLength(string value, int startIndex, object storeValue, 31 | out object parsedValue) 32 | { 33 | MediaTypeHeaderValue temp = null; 34 | int resultLength = MediaTypeHeaderValue.GetMediaTypeLength(value, startIndex, _mediaTypeCreator, out temp); 35 | 36 | parsedValue = temp; 37 | return resultLength; 38 | } 39 | 40 | private static MediaTypeHeaderValue CreateMediaType() 41 | { 42 | return new MediaTypeHeaderValue(); 43 | } 44 | 45 | private static MediaTypeHeaderValue CreateMediaTypeWithQuality() 46 | { 47 | return new MediaTypeWithQualityHeaderValue(); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/Headers/MediaTypeWithQualityHeaderValue.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace System.Net.Http.Headers 8 | { 9 | public sealed class MediaTypeWithQualityHeaderValue : MediaTypeHeaderValue, ICloneable 10 | { 11 | public double? Quality 12 | { 13 | get { return HeaderUtilities.GetQuality((ObjectCollection)Parameters); } 14 | set { HeaderUtilities.SetQuality((ObjectCollection)Parameters, value); } 15 | } 16 | 17 | internal MediaTypeWithQualityHeaderValue() 18 | : base() 19 | { 20 | // Used by the parser to create a new instance of this type. 21 | } 22 | 23 | public MediaTypeWithQualityHeaderValue(string mediaType) 24 | : base(mediaType) 25 | { 26 | } 27 | 28 | public MediaTypeWithQualityHeaderValue(string mediaType, double quality) 29 | : base(mediaType) 30 | { 31 | Quality = quality; 32 | } 33 | 34 | private MediaTypeWithQualityHeaderValue(MediaTypeWithQualityHeaderValue source) 35 | : base(source) 36 | { 37 | // No additional members to initialize here. This constructor is used by Clone(). 38 | } 39 | 40 | object ICloneable.Clone() 41 | { 42 | return new MediaTypeWithQualityHeaderValue(this); 43 | } 44 | 45 | public static new MediaTypeWithQualityHeaderValue Parse(string input) 46 | { 47 | int index = 0; 48 | return (MediaTypeWithQualityHeaderValue)MediaTypeHeaderParser.SingleValueWithQualityParser.ParseValue( 49 | input, null, ref index); 50 | } 51 | 52 | public static bool TryParse(string input, out MediaTypeWithQualityHeaderValue parsedValue) 53 | { 54 | int index = 0; 55 | object output; 56 | parsedValue = null; 57 | 58 | if (MediaTypeHeaderParser.SingleValueWithQualityParser.TryParseValue(input, null, ref index, out output)) 59 | { 60 | parsedValue = (MediaTypeWithQualityHeaderValue)output; 61 | return true; 62 | } 63 | return false; 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/Headers/ObjectCollection.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using System.Collections.ObjectModel; 7 | using System.Diagnostics; 8 | 9 | namespace System.Net.Http.Headers 10 | { 11 | // We need to prevent 'null' values in the collection. Since List allows them, we will create 12 | // a custom collection class. It is less efficient than List but only used for small collections. 13 | internal sealed class ObjectCollection : Collection where T : class 14 | { 15 | private static readonly Action s_defaultValidator = CheckNotNull; 16 | 17 | private readonly Action _validator; 18 | 19 | public ObjectCollection() 20 | : this(s_defaultValidator) 21 | { 22 | } 23 | 24 | public ObjectCollection(Action validator) 25 | : base(new List()) 26 | { 27 | Debug.Assert(validator != null, $"{nameof(validator)} must not be null."); 28 | _validator = validator; 29 | } 30 | 31 | // This is only used internally to enumerate the collection 32 | // without the enumerator allocation. 33 | new public List.Enumerator GetEnumerator() 34 | { 35 | return ((List)Items).GetEnumerator(); 36 | } 37 | 38 | protected override void InsertItem(int index, T item) 39 | { 40 | _validator(item); 41 | base.InsertItem(index, item); 42 | } 43 | 44 | protected override void SetItem(int index, T item) 45 | { 46 | _validator(item); 47 | base.SetItem(index, item); 48 | } 49 | 50 | private static void CheckNotNull(T item) 51 | { 52 | // Null values cannot be added to the collection. 53 | if (item == null) 54 | { 55 | throw new ArgumentNullException(nameof(item)); 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/Headers/ProductInfoHeaderParser.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace System.Net.Http.Headers 8 | { 9 | // Don't derive from BaseHeaderParser since empty values are not supported. After a ' ' separator a valid value 10 | // must follow. Also leading separators are not allowed. 11 | internal class ProductInfoHeaderParser : HttpHeaderParser 12 | { 13 | // Unlike most other headers, User-Agent and Server use whitespace as separators 14 | private const string separator = " "; 15 | 16 | internal static readonly ProductInfoHeaderParser SingleValueParser = new ProductInfoHeaderParser(false); 17 | internal static readonly ProductInfoHeaderParser MultipleValueParser = new ProductInfoHeaderParser(true); 18 | 19 | private ProductInfoHeaderParser(bool supportsMultipleValues) 20 | : base(supportsMultipleValues, separator) 21 | { 22 | } 23 | 24 | public override bool TryParseValue(string value, object storeValue, ref int index, out object parsedValue) 25 | { 26 | parsedValue = null; 27 | 28 | if (string.IsNullOrEmpty(value) || (index == value.Length)) 29 | { 30 | return false; 31 | } 32 | 33 | // Skip leading whitespace 34 | int current = index + HttpRuleParser.GetWhitespaceLength(value, index); 35 | 36 | if (current == value.Length) 37 | { 38 | return false; // whitespace-only values are not valid 39 | } 40 | 41 | ProductInfoHeaderValue result = null; 42 | int length = ProductInfoHeaderValue.GetProductInfoLength(value, current, out result); 43 | 44 | if (length == 0) 45 | { 46 | return false; 47 | } 48 | 49 | // GetProductInfoLength() already skipped trailing whitespace. No need to do it here again. 50 | current = current + length; 51 | 52 | // If we have more values, make sure we saw a whitespace before. Values like "product/1.0(comment)" are 53 | // invalid since there must be a whitespace between the product and the comment value. 54 | if (current < value.Length) 55 | { 56 | // Note that for \r\n to be a valid whitespace, it must be followed by a space/tab. I.e. it's enough if 57 | // we check whether the char before the next value is space/tab. 58 | char lastSeparatorChar = value[current - 1]; 59 | if ((lastSeparatorChar != ' ') && (lastSeparatorChar != '\t')) 60 | { 61 | return false; 62 | } 63 | } 64 | 65 | // Separators for "User-Agent" and "Server" headers are whitespace. This is different from most other headers 66 | // where comma/semicolon is used as separator. 67 | index = current; 68 | parsedValue = result; 69 | return true; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/Headers/TimeSpanHeaderParser.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | using System.Globalization; 7 | 8 | namespace System.Net.Http.Headers 9 | { 10 | internal class TimeSpanHeaderParser : BaseHeaderParser 11 | { 12 | internal static readonly TimeSpanHeaderParser Parser = new TimeSpanHeaderParser(); 13 | 14 | private TimeSpanHeaderParser() 15 | : base(false) 16 | { 17 | } 18 | 19 | public override string ToString(object value) 20 | { 21 | Debug.Assert(value is TimeSpan); 22 | 23 | return ((int)((TimeSpan)value).TotalSeconds).ToString(NumberFormatInfo.InvariantInfo); 24 | } 25 | 26 | protected override int GetParsedValueLength(string value, int startIndex, object storeValue, 27 | out object parsedValue) 28 | { 29 | parsedValue = null; 30 | 31 | int numberLength = HttpRuleParser.GetNumberLength(value, startIndex, false); 32 | 33 | if ((numberLength == 0) || (numberLength > HttpRuleParser.MaxInt32Digits)) 34 | { 35 | return 0; 36 | } 37 | 38 | int result = 0; 39 | if (!HeaderUtilities.TryParseInt32(value, startIndex, numberLength, out result)) 40 | { 41 | return 0; 42 | } 43 | 44 | parsedValue = new TimeSpan(0, 0, result); 45 | return numberLength; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/Headers/TransferCodingHeaderParser.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | 7 | namespace System.Net.Http.Headers 8 | { 9 | internal class TransferCodingHeaderParser : BaseHeaderParser 10 | { 11 | private Func _transferCodingCreator; 12 | 13 | internal static readonly TransferCodingHeaderParser SingleValueParser = 14 | new TransferCodingHeaderParser(false, CreateTransferCoding); 15 | internal static readonly TransferCodingHeaderParser MultipleValueParser = 16 | new TransferCodingHeaderParser(true, CreateTransferCoding); 17 | internal static readonly TransferCodingHeaderParser SingleValueWithQualityParser = 18 | new TransferCodingHeaderParser(false, CreateTransferCodingWithQuality); 19 | internal static readonly TransferCodingHeaderParser MultipleValueWithQualityParser = 20 | new TransferCodingHeaderParser(true, CreateTransferCodingWithQuality); 21 | 22 | private TransferCodingHeaderParser(bool supportsMultipleValues, 23 | Func transferCodingCreator) 24 | : base(supportsMultipleValues) 25 | { 26 | Debug.Assert(transferCodingCreator != null); 27 | 28 | _transferCodingCreator = transferCodingCreator; 29 | } 30 | 31 | protected override int GetParsedValueLength(string value, int startIndex, object storeValue, 32 | out object parsedValue) 33 | { 34 | TransferCodingHeaderValue temp = null; 35 | int resultLength = TransferCodingHeaderValue.GetTransferCodingLength(value, startIndex, 36 | _transferCodingCreator, out temp); 37 | 38 | parsedValue = temp; 39 | return resultLength; 40 | } 41 | 42 | private static TransferCodingHeaderValue CreateTransferCoding() 43 | { 44 | return new TransferCodingHeaderValue(); 45 | } 46 | 47 | private static TransferCodingHeaderValue CreateTransferCodingWithQuality() 48 | { 49 | return new TransferCodingWithQualityHeaderValue(); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/Headers/TransferCodingWithQualityHeaderValue.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace System.Net.Http.Headers 8 | { 9 | public sealed class TransferCodingWithQualityHeaderValue : TransferCodingHeaderValue, ICloneable 10 | { 11 | public double? Quality 12 | { 13 | get { return HeaderUtilities.GetQuality((ObjectCollection)Parameters); } 14 | set { HeaderUtilities.SetQuality((ObjectCollection)Parameters, value); } 15 | } 16 | 17 | internal TransferCodingWithQualityHeaderValue() 18 | { 19 | // Used by the parser to create a new instance of this type. 20 | } 21 | 22 | public TransferCodingWithQualityHeaderValue(string value) 23 | : base(value) 24 | { 25 | } 26 | 27 | public TransferCodingWithQualityHeaderValue(string value, double quality) 28 | : base(value) 29 | { 30 | Quality = quality; 31 | } 32 | 33 | private TransferCodingWithQualityHeaderValue(TransferCodingWithQualityHeaderValue source) 34 | : base(source) 35 | { 36 | // No additional members to initialize here. This constructor is used by Clone(). 37 | } 38 | 39 | object ICloneable.Clone() 40 | { 41 | return new TransferCodingWithQualityHeaderValue(this); 42 | } 43 | 44 | public static new TransferCodingWithQualityHeaderValue Parse(string input) 45 | { 46 | int index = 0; 47 | return (TransferCodingWithQualityHeaderValue)TransferCodingHeaderParser.SingleValueWithQualityParser 48 | .ParseValue(input, null, ref index); 49 | } 50 | 51 | public static bool TryParse(string input, out TransferCodingWithQualityHeaderValue parsedValue) 52 | { 53 | int index = 0; 54 | object output; 55 | parsedValue = null; 56 | 57 | if (TransferCodingHeaderParser.SingleValueWithQualityParser.TryParseValue( 58 | input, null, ref index, out output)) 59 | { 60 | parsedValue = (TransferCodingWithQualityHeaderValue)output; 61 | return true; 62 | } 63 | return false; 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/HttpClientHandler.Core.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Globalization; 6 | 7 | namespace System.Net.Http 8 | { 9 | public partial class HttpClientHandler : HttpMessageHandler 10 | { 11 | // This partial implementation contains members common to Windows and Unix running on .NET Core. 12 | 13 | private volatile bool _operationStarted = false; 14 | private volatile bool _disposed = false; 15 | 16 | public long MaxRequestContentBufferSize 17 | { 18 | // This property is not supported. In the .NET Framework it was only used when the handler needed to 19 | // automatically buffer the request content. That only happened if neither 'Content-Length' nor 20 | // 'Transfer-Encoding: chunked' request headers were specified. So, the handler thus needed to buffer 21 | // in the request content to determine its length and then would choose 'Content-Length' semantics when 22 | // POST'ing. In .NET Core and UAP platforms, the handler will resolve the ambiguity by always choosing 23 | // 'Transfer-Encoding: chunked'. The handler will never automatically buffer in the request content. 24 | get 25 | { 26 | return 0; // Returning zero is appropriate since in .NET Framework it means no limit. 27 | } 28 | 29 | set 30 | { 31 | if (value < 0) 32 | { 33 | throw new ArgumentOutOfRangeException(nameof(value)); 34 | } 35 | 36 | if (value > HttpContent.MaxBufferSize) 37 | { 38 | throw new ArgumentOutOfRangeException(nameof(value), value, 39 | SR.Format(CultureInfo.InvariantCulture, SR.net_http_content_buffersize_limit, 40 | HttpContent.MaxBufferSize)); 41 | } 42 | 43 | CheckDisposedOrStarted(); 44 | 45 | // No-op on property setter. 46 | } 47 | } 48 | 49 | private void CheckDisposed() 50 | { 51 | if (_disposed) 52 | { 53 | throw new ObjectDisposedException(GetType().ToString()); 54 | } 55 | } 56 | 57 | private void CheckDisposedOrStarted() 58 | { 59 | CheckDisposed(); 60 | if (_operationStarted) 61 | { 62 | throw new InvalidOperationException(SR.net_http_operation_started); 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/HttpClientHandler.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | using System.Net.Security; 7 | using System.Security.Cryptography.X509Certificates; 8 | 9 | namespace System.Net.Http 10 | { 11 | public partial class HttpClientHandler : HttpMessageHandler 12 | { 13 | // This partial implementation contains members common to all HttpClientHandler implementations. 14 | private const string SocketsHttpHandlerEnvironmentVariableSettingName = "DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER"; 15 | private const string SocketsHttpHandlerAppCtxSettingName = "System.Net.Http.UseSocketsHttpHandler"; 16 | 17 | private static bool UseSocketsHttpHandler 18 | { 19 | get 20 | { 21 | // First check for the AppContext switch, giving it priority over the environment variable. 22 | if (AppContext.TryGetSwitch(SocketsHttpHandlerAppCtxSettingName, out bool useSocketsHttpHandler)) 23 | { 24 | return useSocketsHttpHandler; 25 | } 26 | 27 | // AppContext switch wasn't used. Check the environment variable to determine which handler should be used. 28 | string envVar = Environment.GetEnvironmentVariable(SocketsHttpHandlerEnvironmentVariableSettingName); 29 | if (envVar != null && (envVar.Equals("false", StringComparison.OrdinalIgnoreCase) || envVar.Equals("0"))) 30 | { 31 | // Use WinHttpHandler on Windows and CurlHandler on Unix. 32 | return false; 33 | } 34 | 35 | // Default to using SocketsHttpHandler. 36 | return true; 37 | } 38 | } 39 | 40 | public static Func DangerousAcceptAnyServerCertificateValidator { get; } = delegate { return true; }; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/HttpClientHandler.netcoreapp.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using System.Net.Security; 7 | using System.Security.Authentication; 8 | using System.Security.Cryptography.X509Certificates; 9 | using System.Threading; 10 | using System.Threading.Tasks; 11 | 12 | namespace System.Net.Http 13 | { 14 | // This partial implementation contains members common to NetCoreApp 15 | public partial class HttpClientHandler : HttpMessageHandler 16 | { 17 | private void ThrowForModifiedManagedSslOptionsIfStarted() 18 | { 19 | // Hack to trigger an InvalidOperationException if a property that's stored on 20 | // SslOptions is changed, since SslOptions itself does not do any such checks. 21 | _socketsHttpHandler.SslOptions = _socketsHttpHandler.SslOptions; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/HttpCompletionOption.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | 9 | namespace System.Net.Http 10 | { 11 | public enum HttpCompletionOption 12 | { 13 | ResponseContentRead = 0, 14 | ResponseHeadersRead, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/HttpMessageHandler.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | using System.Threading; 9 | using System.Threading.Tasks; 10 | 11 | namespace System.Net.Http 12 | { 13 | public abstract class HttpMessageHandler : IDisposable 14 | { 15 | protected HttpMessageHandler() 16 | { 17 | if (NetEventSource.IsEnabled) NetEventSource.Info(this); 18 | } 19 | 20 | protected internal abstract Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken); 21 | 22 | #region IDisposable Members 23 | 24 | protected virtual void Dispose(bool disposing) 25 | { 26 | // Nothing to do in base class. 27 | } 28 | 29 | public void Dispose() 30 | { 31 | Dispose(true); 32 | GC.SuppressFinalize(this); 33 | } 34 | #endregion 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/HttpMessageInvoker.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.IO; 6 | using System.Net.Http.Headers; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | 10 | namespace System.Net.Http 11 | { 12 | public class HttpMessageInvoker : IDisposable 13 | { 14 | private volatile bool _disposed; 15 | private bool _disposeHandler; 16 | private HttpMessageHandler _handler; 17 | 18 | public HttpMessageInvoker(HttpMessageHandler handler) 19 | : this(handler, true) 20 | { 21 | } 22 | 23 | public HttpMessageInvoker(HttpMessageHandler handler, bool disposeHandler) 24 | { 25 | if (NetEventSource.IsEnabled) NetEventSource.Enter(this, handler); 26 | 27 | if (handler == null) 28 | { 29 | throw new ArgumentNullException(nameof(handler)); 30 | } 31 | 32 | if (NetEventSource.IsEnabled) NetEventSource.Associate(this, handler); 33 | 34 | _handler = handler; 35 | _disposeHandler = disposeHandler; 36 | 37 | if (NetEventSource.IsEnabled) NetEventSource.Exit(this); 38 | } 39 | 40 | public virtual Task SendAsync(HttpRequestMessage request, 41 | CancellationToken cancellationToken) 42 | { 43 | if (request == null) 44 | { 45 | throw new ArgumentNullException(nameof(request)); 46 | } 47 | CheckDisposed(); 48 | 49 | if (NetEventSource.IsEnabled) NetEventSource.Enter(this, request); 50 | 51 | Task task = _handler.SendAsync(request, cancellationToken); 52 | 53 | if (NetEventSource.IsEnabled) NetEventSource.Exit(this, task); 54 | 55 | return task; 56 | } 57 | 58 | public void Dispose() 59 | { 60 | Dispose(true); 61 | GC.SuppressFinalize(this); 62 | } 63 | 64 | protected virtual void Dispose(bool disposing) 65 | { 66 | if (disposing && !_disposed) 67 | { 68 | _disposed = true; 69 | 70 | if (_disposeHandler) 71 | { 72 | _handler.Dispose(); 73 | } 74 | } 75 | } 76 | 77 | private void CheckDisposed() 78 | { 79 | if (_disposed) 80 | { 81 | throw new ObjectDisposedException(GetType().ToString()); 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/HttpParseResult.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Text; 7 | 8 | namespace System.Net.Http 9 | { 10 | internal enum HttpParseResult 11 | { 12 | Parsed, 13 | NotParsed, 14 | InvalidFormat, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/HttpRequestException.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics.CodeAnalysis; 6 | using System.IO; 7 | 8 | namespace System.Net.Http 9 | { 10 | [SuppressMessage("Microsoft.Serialization", "CA2229")] 11 | public class HttpRequestException : Exception 12 | { 13 | internal bool AllowRetry { get; } 14 | 15 | public HttpRequestException() 16 | : this(null, null) 17 | { } 18 | 19 | public HttpRequestException(string message) 20 | : this(message, null) 21 | { } 22 | 23 | public HttpRequestException(string message, Exception inner) 24 | : base(message, inner) 25 | { 26 | if (inner != null) 27 | { 28 | HResult = inner.HResult; 29 | } 30 | } 31 | 32 | // This constructor is used internally to indicate that a request was not successfully sent due to an IOException, 33 | // and the exception occurred early enough so that the request may be retried on another connection. 34 | internal HttpRequestException(string message, Exception inner, bool allowRetry) 35 | : this(message, inner) 36 | { 37 | AllowRetry = allowRetry; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/HttpUtilities.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | using System.Threading.Tasks; 7 | using System.Threading; 8 | 9 | namespace System.Net.Http 10 | { 11 | internal static class HttpUtilities 12 | { 13 | internal static Version DefaultRequestVersion => 14 | #if uap 15 | HttpVersion.Version20; 16 | #else 17 | HttpVersion.Version11; 18 | #endif 19 | 20 | internal static Version DefaultResponseVersion => HttpVersion.Version11; 21 | 22 | internal static bool IsHttpUri(Uri uri) 23 | { 24 | Debug.Assert(uri != null); 25 | return IsSupportedScheme(uri.Scheme); 26 | } 27 | 28 | internal static bool IsSupportedScheme(string scheme) => 29 | IsSupportedNonSecureScheme(scheme) || 30 | IsSupportedSecureScheme(scheme); 31 | 32 | internal static bool IsSupportedNonSecureScheme(string scheme) => 33 | string.Equals(scheme, "http", StringComparison.OrdinalIgnoreCase) || IsNonSecureWebSocketScheme(scheme); 34 | 35 | internal static bool IsSupportedSecureScheme(string scheme) => 36 | string.Equals(scheme, "https", StringComparison.OrdinalIgnoreCase) || IsSecureWebSocketScheme(scheme); 37 | 38 | internal static bool IsNonSecureWebSocketScheme(string scheme) => 39 | string.Equals(scheme, "ws", StringComparison.OrdinalIgnoreCase); 40 | 41 | internal static bool IsSecureWebSocketScheme(string scheme) => 42 | string.Equals(scheme, "wss", StringComparison.OrdinalIgnoreCase); 43 | 44 | // Always specify TaskScheduler.Default to prevent us from using a user defined TaskScheduler.Current. 45 | // 46 | // Since we're not doing any CPU and/or I/O intensive operations, continue on the same thread. 47 | // This results in better performance since the continuation task doesn't get scheduled by the 48 | // scheduler and there are no context switches required. 49 | internal static Task ContinueWithStandard(this Task task, object state, Action, object> continuation) 50 | { 51 | return task.ContinueWith(continuation, state, CancellationToken.None, 52 | TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/ReadOnlyMemoryContent.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.IO; 6 | using System.Runtime.InteropServices; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | 10 | namespace System.Net.Http 11 | { 12 | public sealed class ReadOnlyMemoryContent : HttpContent 13 | { 14 | private readonly ReadOnlyMemory _content; 15 | 16 | public ReadOnlyMemoryContent(ReadOnlyMemory content) 17 | { 18 | _content = content; 19 | if (MemoryMarshal.TryGetArray(content, out ArraySegment array)) 20 | { 21 | // If we have an array, allow HttpClient to take optimized paths by just 22 | // giving it the array content to use as its already buffered data. 23 | SetBuffer(array.Array, array.Offset, array.Count); 24 | } 25 | } 26 | 27 | protected override Task SerializeToStreamAsync(Stream stream, TransportContext context) => 28 | stream.WriteAsync(_content).AsTask(); 29 | 30 | internal override Task SerializeToStreamAsync(Stream stream, TransportContext context, CancellationToken cancellationToken) => 31 | stream.WriteAsync(_content, cancellationToken).AsTask(); 32 | 33 | protected internal override bool TryComputeLength(out long length) 34 | { 35 | length = _content.Length; 36 | return true; 37 | } 38 | 39 | protected override Task CreateContentReadStreamAsync() => 40 | Task.FromResult(new ReadOnlyMemoryStream(_content)); 41 | 42 | internal override Stream TryCreateContentReadStream() => 43 | new ReadOnlyMemoryStream(_content); 44 | 45 | internal override bool AllowDuplex => false; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/CancellationHelper.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace System.Net.Http 9 | { 10 | /// Provides utilities related to cancellation. 11 | internal static class CancellationHelper 12 | { 13 | /// The default message used by . 14 | private static readonly string s_cancellationMessage = new OperationCanceledException().Message; // use same message as the default ctor 15 | 16 | /// Determines whether to wrap an in a cancellation exception. 17 | /// The exception. 18 | /// The that may have triggered the exception. 19 | /// true if the exception should be wrapped; otherwise, false. 20 | internal static bool ShouldWrapInOperationCanceledException(Exception exception, CancellationToken cancellationToken) => 21 | !(exception is OperationCanceledException) && cancellationToken.IsCancellationRequested; 22 | 23 | /// Creates a cancellation exception. 24 | /// The inner exception to wrap. May be null. 25 | /// The that triggered the cancellation. 26 | /// The cancellation exception. 27 | internal static Exception CreateOperationCanceledException(Exception innerException, CancellationToken cancellationToken) => 28 | new TaskCanceledException(s_cancellationMessage, innerException, cancellationToken); // TCE for compatibility with other handlers that use TaskCompletionSource.TrySetCanceled() 29 | 30 | /// Throws a cancellation exception. 31 | /// The inner exception to wrap. May be null. 32 | /// The that triggered the cancellation. 33 | private static void ThrowOperationCanceledException(Exception innerException, CancellationToken cancellationToken) => 34 | throw CreateOperationCanceledException(innerException, cancellationToken); 35 | 36 | /// Throws a cancellation exception if cancellation has been requested via . 37 | /// The token to check for a cancellation request. 38 | internal static void ThrowIfCancellationRequested(CancellationToken cancellationToken) 39 | { 40 | if (cancellationToken.IsCancellationRequested) 41 | { 42 | ThrowOperationCanceledException(innerException:null, cancellationToken); 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ChunkedEncodingWriteStream.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace System.Net.Http 10 | { 11 | internal partial class HttpConnection : IDisposable 12 | { 13 | private sealed class ChunkedEncodingWriteStream : HttpContentWriteStream 14 | { 15 | private static readonly byte[] s_finalChunkBytes = { (byte)'0', (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' }; 16 | 17 | public ChunkedEncodingWriteStream(HttpConnection connection) : base(connection) 18 | { 19 | } 20 | 21 | public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken ignored) 22 | { 23 | HttpConnection connection = GetConnectionOrThrow(); 24 | Debug.Assert(connection._currentRequest != null); 25 | 26 | // The token is ignored because it's coming from SendAsync and the only operations 27 | // here are those that are already covered by the token having been registered with 28 | // to close the connection. 29 | 30 | ValueTask task = buffer.Length == 0 ? 31 | // Don't write if nothing was given, especially since we don't want to accidentally send a 0 chunk, 32 | // which would indicate end of body. Instead, just ensure no content is stuck in the buffer. 33 | connection.FlushAsync() : 34 | new ValueTask(WriteChunkAsync(connection, buffer)); 35 | 36 | return task; 37 | 38 | static async Task WriteChunkAsync(HttpConnection connection, ReadOnlyMemory buffer) 39 | { 40 | // Write chunk length in hex followed by \r\n 41 | await connection.WriteHexInt32Async(buffer.Length).ConfigureAwait(false); 42 | await connection.WriteTwoBytesAsync((byte)'\r', (byte)'\n').ConfigureAwait(false); 43 | 44 | // Write chunk contents followed by \r\n 45 | await connection.WriteAsync(buffer).ConfigureAwait(false); 46 | await connection.WriteTwoBytesAsync((byte)'\r', (byte)'\n').ConfigureAwait(false); 47 | } 48 | } 49 | 50 | public override async Task FinishAsync() 51 | { 52 | // Send 0 byte chunk to indicate end, then final CrLf 53 | HttpConnection connection = GetConnectionOrThrow(); 54 | _connection = null; 55 | await connection.WriteBytesAsync(s_finalChunkBytes).ConfigureAwait(false); 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ContentLengthWriteStream.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace System.Net.Http 10 | { 11 | internal partial class HttpConnection : IDisposable 12 | { 13 | private sealed class ContentLengthWriteStream : HttpContentWriteStream 14 | { 15 | public ContentLengthWriteStream(HttpConnection connection) : base(connection) 16 | { 17 | } 18 | 19 | public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken ignored) // token ignored as it comes from SendAsync 20 | { 21 | // Have the connection write the data, skipping the buffer. Importantly, this will 22 | // force a flush of anything already in the buffer, i.e. any remaining request headers 23 | // that are still buffered. 24 | HttpConnection connection = GetConnectionOrThrow(); 25 | Debug.Assert(connection._currentRequest != null); 26 | return new ValueTask(connection.WriteAsync(buffer)); 27 | } 28 | 29 | public override Task FinishAsync() 30 | { 31 | _connection = null; 32 | return Task.CompletedTask; 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/CookieHelper.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Net.Http.Headers; 6 | using System.Diagnostics; 7 | using System.Collections.Generic; 8 | 9 | namespace System.Net.Http 10 | { 11 | internal static class CookieHelper 12 | { 13 | public static void ProcessReceivedCookies(HttpResponseMessage response, CookieContainer cookieContainer) 14 | { 15 | IEnumerable values; 16 | if (response.Headers.TryGetValues(KnownHeaders.SetCookie.Descriptor, out values)) 17 | { 18 | // The header values are always a string[] 19 | var valuesArray = (string[])values; 20 | Debug.Assert(valuesArray.Length > 0, "No values for header??"); 21 | 22 | Uri requestUri = response.RequestMessage.RequestUri; 23 | for (int i = 0; i < valuesArray.Length; i++) 24 | { 25 | try 26 | { 27 | cookieContainer.SetCookies(requestUri, valuesArray[i]); 28 | } 29 | catch (CookieException) 30 | { 31 | // Ignore invalid Set-Cookie header and continue processing. 32 | if (NetEventSource.IsEnabled) 33 | { 34 | NetEventSource.Error(response, $"Invalid Set-Cookie '{valuesArray[i]}' ignored."); 35 | } 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/EmptyReadStream.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.IO; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace System.Net.Http 10 | { 11 | internal sealed class EmptyReadStream : HttpBaseStream 12 | { 13 | internal static EmptyReadStream Instance { get; } = new EmptyReadStream(); 14 | 15 | private EmptyReadStream() { } 16 | 17 | public override bool CanRead => true; 18 | public override bool CanWrite => false; 19 | 20 | protected override void Dispose(bool disposing) { /* nop */ } 21 | public override void Close() { /* nop */ } 22 | 23 | public override int Read(Span buffer) => 0; 24 | 25 | public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken) => 26 | cancellationToken.IsCancellationRequested ? new ValueTask(Task.FromCanceled(cancellationToken)) : 27 | new ValueTask(0); 28 | 29 | public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) 30 | { 31 | ValidateCopyToArgs(this, destination, bufferSize); 32 | return NopAsync(cancellationToken); 33 | } 34 | 35 | public override void Write(ReadOnlySpan buffer) => throw new NotSupportedException(SR.net_http_content_readonly_stream); 36 | 37 | public override ValueTask WriteAsync(ReadOnlyMemory destination, CancellationToken cancellationToken) => throw new NotSupportedException(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ExposedSocketNetworkStream.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace System.Net.Sockets 6 | { 7 | // TODO: Delete once https://github.com/dotnet/corefx/issues/35410 is available. 8 | internal sealed class ExposedSocketNetworkStream : NetworkStream 9 | { 10 | public ExposedSocketNetworkStream(Socket socket, bool ownsSocket) : base(socket, ownsSocket) { } 11 | 12 | public new Socket Socket => base.Socket; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HPack/DynamicTable.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. 3 | // See THIRD-PARTY-NOTICES.TXT in the project root for license information. 4 | 5 | namespace System.Net.Http.HPack 6 | { 7 | internal class DynamicTable 8 | { 9 | private HeaderField[] _buffer; 10 | private int _maxSize; 11 | private int _size; 12 | private int _count; 13 | private int _insertIndex; 14 | private int _removeIndex; 15 | 16 | public DynamicTable(int maxSize) 17 | { 18 | _buffer = new HeaderField[maxSize / HeaderField.RfcOverhead]; 19 | _maxSize = maxSize; 20 | } 21 | 22 | public int Count => _count; 23 | 24 | public int Size => _size; 25 | 26 | public int MaxSize => _maxSize; 27 | 28 | public HeaderField this[int index] 29 | { 30 | get 31 | { 32 | if (index >= _count) 33 | { 34 | throw new IndexOutOfRangeException(); 35 | } 36 | 37 | return _buffer[_insertIndex == 0 ? _buffer.Length - 1 : _insertIndex - index - 1]; 38 | } 39 | } 40 | 41 | public void Insert(ReadOnlySpan name, ReadOnlySpan value) 42 | { 43 | int entryLength = HeaderField.GetLength(name.Length, value.Length); 44 | EnsureAvailable(entryLength); 45 | 46 | if (entryLength > _maxSize) 47 | { 48 | // http://httpwg.org/specs/rfc7541.html#rfc.section.4.4 49 | // It is not an error to attempt to add an entry that is larger than the maximum size; 50 | // an attempt to add an entry larger than the maximum size causes the table to be emptied 51 | // of all existing entries and results in an empty table. 52 | return; 53 | } 54 | 55 | var entry = new HeaderField(name, value); 56 | _buffer[_insertIndex] = entry; 57 | _insertIndex = (_insertIndex + 1) % _buffer.Length; 58 | _size += entry.Length; 59 | _count++; 60 | } 61 | 62 | public void Resize(int maxSize) 63 | { 64 | // TODO: What would cause us to need to grow the table size? The connection-level limit should prevent this, right? 65 | // Understand this better. If we do need to resize, we may want a better resize strategy. 66 | if (maxSize > _maxSize) 67 | { 68 | var newBuffer = new HeaderField[maxSize / HeaderField.RfcOverhead]; 69 | 70 | for (var i = 0; i < Count; i++) 71 | { 72 | newBuffer[i] = _buffer[i]; 73 | } 74 | 75 | _buffer = newBuffer; 76 | _maxSize = maxSize; 77 | } 78 | else 79 | { 80 | _maxSize = maxSize; 81 | EnsureAvailable(0); 82 | } 83 | } 84 | 85 | private void EnsureAvailable(int available) 86 | { 87 | while (_count > 0 && _maxSize - _size < available) 88 | { 89 | _size -= _buffer[_removeIndex].Length; 90 | _count--; 91 | _removeIndex = (_removeIndex + 1) % _buffer.Length; 92 | } 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HPack/HPackDecodingException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. 3 | // See THIRD-PARTY-NOTICES.TXT in the project root for license information. 4 | 5 | using System.Runtime.Serialization; 6 | 7 | namespace System.Net.Http.HPack 8 | { 9 | // TODO: Should this be public? 10 | [Serializable] 11 | internal class HPackDecodingException : Exception 12 | { 13 | public HPackDecodingException() 14 | { 15 | } 16 | 17 | public HPackDecodingException(string message) : base(message) 18 | { 19 | } 20 | 21 | public HPackDecodingException(string message, Exception innerException) : base(message, innerException) 22 | { 23 | } 24 | 25 | public HPackDecodingException(SerializationInfo info, StreamingContext context) : base(info, context) 26 | { 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HPack/HeaderField.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. 3 | // See THIRD-PARTY-NOTICES.TXT in the project root for license information. 4 | 5 | namespace System.Net.Http.HPack 6 | { 7 | internal struct HeaderField 8 | { 9 | // http://httpwg.org/specs/rfc7541.html#rfc.section.4.1 10 | public const int RfcOverhead = 32; 11 | 12 | public HeaderField(ReadOnlySpan name, ReadOnlySpan value) 13 | { 14 | // TODO: We're allocating here on every new table entry. 15 | // That means a poorly-behaved server could cause us to allocate repeatedly. 16 | // We should revisit our allocation strategy here so we don't need to allocate per entry 17 | // and we have a cap to how much allocation can happen per dynamic table 18 | // (without limiting the number of table entries a server can provide within the table size limit). 19 | Name = new byte[name.Length]; 20 | name.CopyTo(Name); 21 | 22 | Value = new byte[value.Length]; 23 | value.CopyTo(Value); 24 | } 25 | 26 | public byte[] Name { get; } 27 | 28 | public byte[] Value { get; } 29 | 30 | public int Length => GetLength(Name.Length, Value.Length); 31 | 32 | public static int GetLength(int nameLength, int valueLenth) => nameLength + valueLenth + 32; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HPack/HuffmanDecodingException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. 3 | // See THIRD-PARTY-NOTICES.TXT in the project root for license information. 4 | 5 | using System.Runtime.Serialization; 6 | 7 | namespace System.Net.Http.HPack 8 | { 9 | // TODO: Should this be public? 10 | [Serializable] 11 | internal class HuffmanDecodingException : Exception 12 | { 13 | public HuffmanDecodingException() 14 | { 15 | } 16 | 17 | public HuffmanDecodingException(SerializationInfo info, StreamingContext context) 18 | : base(info, context) 19 | { 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HPack/IntegerEncoder.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. 3 | // See THIRD-PARTY-NOTICES.TXT in the project root for license information. 4 | 5 | using System.Diagnostics; 6 | 7 | namespace System.Net.Http.HPack 8 | { 9 | internal static class IntegerEncoder 10 | { 11 | /// 12 | /// Encodes an integer into one or more bytes. 13 | /// 14 | /// The value to encode. Must not be negative. 15 | /// The length of the prefix, in bits, to encode within. Must be between 1 and 8. 16 | /// The destination span to encode to. 17 | /// The number of bytes used to encode . 18 | /// If had enough storage to encode , true. Otherwise, false. 19 | public static bool Encode(int value, int numBits, Span destination, out int bytesWritten) 20 | { 21 | Debug.Assert(value >= 0); 22 | Debug.Assert(numBits >= 1 && numBits <= 8); 23 | 24 | if (destination.Length == 0) 25 | { 26 | bytesWritten = 0; 27 | return false; 28 | } 29 | 30 | destination[0] &= MaskHigh(8 - numBits); 31 | 32 | if (value < (1 << numBits) - 1) 33 | { 34 | destination[0] |= (byte)value; 35 | 36 | bytesWritten = 1; 37 | return true; 38 | } 39 | else 40 | { 41 | destination[0] |= (byte)((1 << numBits) - 1); 42 | 43 | if (1 == destination.Length) 44 | { 45 | bytesWritten = 0; 46 | return false; 47 | } 48 | 49 | value = value - ((1 << numBits) - 1); 50 | int i = 1; 51 | 52 | while (value >= 128) 53 | { 54 | destination[i++] = (byte)(value % 128 + 128); 55 | 56 | if (i >= destination.Length) 57 | { 58 | bytesWritten = 0; 59 | return false; 60 | } 61 | 62 | value = value / 128; 63 | } 64 | destination[i++] = (byte)value; 65 | 66 | bytesWritten = i; 67 | return true; 68 | } 69 | } 70 | 71 | private static byte MaskHigh(int n) => (byte)(sbyte.MinValue >> (n - 1)); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2ConnectionException.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Runtime.Serialization; 6 | 7 | namespace System.Net.Http 8 | { 9 | [Serializable] 10 | internal sealed class Http2ConnectionException : Http2ProtocolException 11 | { 12 | public Http2ConnectionException(Http2ProtocolErrorCode protocolError) 13 | : base(SR.Format(SR.net_http_http2_connection_error, GetName(protocolError), ((int)protocolError).ToString("x")), protocolError) 14 | { 15 | } 16 | 17 | private Http2ConnectionException(SerializationInfo info, StreamingContext context) : base(info, context) { } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2ProtocolErrorCode.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace System.Net.Http 6 | { 7 | // NOTE: If any additional error codes are added here, they should also be added to Http2ProtocolException's mapping. 8 | 9 | /// 10 | /// Error codes defined by the HTTP/2 protocol, used in RST_STREAM and GOAWAY frames to convey the reasons for the stream or connection error. 11 | /// https://http2.github.io/http2-spec/#PROTOCOL_ERROR 12 | /// 13 | internal enum Http2ProtocolErrorCode 14 | { 15 | /// The associated condition is not a result of an error. 16 | NoError = 0x0, 17 | /// The endpoint detected an unspecific protocol error. This error is for use when a more specific error code is not available. 18 | ProtocolError = 0x1, 19 | /// The endpoint encountered an unexpected internal error. 20 | InternalError = 0x2, 21 | /// The endpoint detected that its peer violated the flow-control protocol. 22 | FlowControlError = 0x3, 23 | /// The endpoint sent a SETTINGS frame but did not receive a response in a timely manner. 24 | SettingsTimeout = 0x4, 25 | /// The endpoint received a frame after a stream was half-closed. 26 | StreamClosed = 0x5, 27 | /// The endpoint received a frame with an invalid size. 28 | FrameSizeError = 0x6, 29 | /// The endpoint refused the stream prior to performing any application processing. 30 | RefusedStream = 0x7, 31 | /// Used by the endpoint to indicate that the stream is no longer needed. 32 | Cancel = 0x8, 33 | /// The endpoint is unable to maintain the header compression context for the connection. 34 | CompressionError = 0x9, 35 | /// The connection established in response to a CONNECT request was reset or abnormally closed. 36 | ConnectError = 0xa, 37 | /// The endpoint detected that its peer is exhibiting a behavior that might be generating excessive load. 38 | EnhanceYourCalm = 0xb, 39 | /// The underlying transport has properties that do not meet minimum security requirements. 40 | InadequateSecurity = 0xc, 41 | /// The endpoint requires that HTTP/1.1 be used instead of HTTP/2. 42 | Http11Required = 0xd 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2ProtocolException.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Runtime.Serialization; 6 | 7 | namespace System.Net.Http 8 | { 9 | [Serializable] 10 | internal abstract class Http2ProtocolException : Exception 11 | { 12 | public Http2ProtocolException(string message, Http2ProtocolErrorCode protocolError) 13 | : base(message) 14 | { 15 | ProtocolError = protocolError; 16 | } 17 | 18 | protected Http2ProtocolException(SerializationInfo info, StreamingContext context) : base(info, context) 19 | { 20 | ProtocolError = (Http2ProtocolErrorCode)info.GetInt32(nameof(ProtocolError)); 21 | } 22 | 23 | public override void GetObjectData(SerializationInfo info, StreamingContext context) 24 | { 25 | info.AddValue(nameof(ProtocolError), (int)ProtocolError); 26 | base.GetObjectData(info, context); 27 | } 28 | 29 | internal Http2ProtocolErrorCode ProtocolError { get; } 30 | 31 | protected static string GetName(Http2ProtocolErrorCode code) 32 | { 33 | // These strings are the names used in the HTTP2 spec and should not be localized. 34 | switch (code) 35 | { 36 | case Http2ProtocolErrorCode.NoError: 37 | return "NO_ERROR"; 38 | case Http2ProtocolErrorCode.ProtocolError: 39 | return "PROTOCOL_ERROR"; 40 | case Http2ProtocolErrorCode.InternalError: 41 | return "INTERNAL_ERROR"; 42 | case Http2ProtocolErrorCode.FlowControlError: 43 | return "FLOW_CONTROL_ERROR"; 44 | case Http2ProtocolErrorCode.SettingsTimeout: 45 | return "SETTINGS_TIMEOUT"; 46 | case Http2ProtocolErrorCode.StreamClosed: 47 | return "STREAM_CLOSED"; 48 | case Http2ProtocolErrorCode.FrameSizeError: 49 | return "FRAME_SIZE_ERROR"; 50 | case Http2ProtocolErrorCode.RefusedStream: 51 | return "REFUSED_STREAM"; 52 | case Http2ProtocolErrorCode.Cancel: 53 | return "CANCEL"; 54 | case Http2ProtocolErrorCode.CompressionError: 55 | return "COMPRESSION_ERROR"; 56 | case Http2ProtocolErrorCode.ConnectError: 57 | return "CONNECT_ERROR"; 58 | case Http2ProtocolErrorCode.EnhanceYourCalm: 59 | return "ENHANCE_YOUR_CALM"; 60 | case Http2ProtocolErrorCode.InadequateSecurity: 61 | return "INADEQUATE_SECURITY"; 62 | case Http2ProtocolErrorCode.Http11Required: 63 | return "HTTP_1_1_REQUIRED"; 64 | default: 65 | return "(unknown error)"; 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2StreamException.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Runtime.Serialization; 6 | 7 | namespace System.Net.Http 8 | { 9 | [Serializable] 10 | internal sealed class Http2StreamException : Http2ProtocolException 11 | { 12 | public Http2StreamException(Http2ProtocolErrorCode protocolError) 13 | : base(SR.Format(SR.net_http_http2_stream_error, GetName(protocolError), ((int)protocolError).ToString("x")), protocolError) 14 | { 15 | } 16 | 17 | private Http2StreamException(SerializationInfo info, StreamingContext context) : base(info, context) { } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpAuthenticatedConnectionHandler.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace System.Net.Http 9 | { 10 | internal sealed class HttpAuthenticatedConnectionHandler : HttpMessageHandler 11 | { 12 | private readonly HttpConnectionPoolManager _poolManager; 13 | 14 | public HttpAuthenticatedConnectionHandler(HttpConnectionPoolManager poolManager) 15 | { 16 | _poolManager = poolManager; 17 | } 18 | 19 | protected internal override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 20 | { 21 | return _poolManager.SendAsync(request, doRequestAuth:true, cancellationToken); 22 | } 23 | 24 | protected override void Dispose(bool disposing) 25 | { 26 | if (disposing) 27 | { 28 | _poolManager.Dispose(); 29 | } 30 | 31 | base.Dispose(disposing); 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionHandler.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace System.Net.Http 9 | { 10 | internal sealed class HttpConnectionHandler : HttpMessageHandler 11 | { 12 | private readonly HttpConnectionPoolManager _poolManager; 13 | 14 | public HttpConnectionHandler(HttpConnectionPoolManager poolManager) 15 | { 16 | _poolManager = poolManager; 17 | } 18 | 19 | protected internal override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 20 | { 21 | return _poolManager.SendAsync(request, doRequestAuth:false, cancellationToken); 22 | } 23 | 24 | protected override void Dispose(bool disposing) 25 | { 26 | if (disposing) 27 | { 28 | _poolManager.Dispose(); 29 | } 30 | 31 | base.Dispose(disposing); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionKind.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace System.Net.Http 6 | { 7 | internal enum HttpConnectionKind : byte 8 | { 9 | Http, // Non-secure connection with no proxy. 10 | Https, // Secure connection with no proxy. 11 | Proxy, // HTTP proxy usage for non-secure (HTTP) requests. 12 | ProxyTunnel, // Non-secure websocket (WS) connection using CONNECT tunneling through proxy. 13 | SslProxyTunnel, // HTTP proxy usage for secure (HTTPS/WSS) requests using SSL and proxy CONNECT. 14 | ProxyConnect // Connection used for proxy CONNECT. Tunnel will be established on top of this. 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionResponseContent.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | using System.IO; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | 10 | namespace System.Net.Http 11 | { 12 | internal sealed class HttpConnectionResponseContent : HttpContent 13 | { 14 | private Stream _stream; 15 | private bool _consumedStream; // separate from _stream so that Dispose can drain _stream 16 | 17 | public void SetStream(Stream stream) 18 | { 19 | Debug.Assert(stream != null); 20 | Debug.Assert(stream.CanRead); 21 | Debug.Assert(!_consumedStream); 22 | 23 | _stream = stream; 24 | } 25 | 26 | private Stream ConsumeStream() 27 | { 28 | if (_consumedStream || _stream == null) 29 | { 30 | throw new InvalidOperationException(SR.net_http_content_stream_already_read); 31 | } 32 | _consumedStream = true; 33 | 34 | return _stream; 35 | } 36 | 37 | protected sealed override Task SerializeToStreamAsync(Stream stream, TransportContext context) => 38 | SerializeToStreamAsync(stream, context, CancellationToken.None); 39 | 40 | internal sealed override async Task SerializeToStreamAsync(Stream stream, TransportContext context, CancellationToken cancellationToken) 41 | { 42 | Debug.Assert(stream != null); 43 | 44 | using (Stream contentStream = ConsumeStream()) 45 | { 46 | const int BufferSize = 8192; 47 | await contentStream.CopyToAsync(stream, BufferSize, cancellationToken).ConfigureAwait(false); 48 | } 49 | } 50 | 51 | protected internal sealed override bool TryComputeLength(out long length) 52 | { 53 | length = 0; 54 | return false; 55 | } 56 | 57 | protected sealed override Task CreateContentReadStreamAsync() => 58 | Task.FromResult(ConsumeStream()); 59 | 60 | internal sealed override Stream TryCreateContentReadStream() => 61 | ConsumeStream(); 62 | 63 | internal override bool AllowDuplex => false; 64 | 65 | protected sealed override void Dispose(bool disposing) 66 | { 67 | if (disposing) 68 | { 69 | if (_stream != null) 70 | { 71 | _stream.Dispose(); 72 | _stream = null; 73 | } 74 | } 75 | 76 | base.Dispose(disposing); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpContentStream.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace System.Net.Http 6 | { 7 | internal abstract class HttpContentStream : HttpBaseStream 8 | { 9 | protected HttpConnection _connection; 10 | 11 | public HttpContentStream(HttpConnection connection) 12 | { 13 | _connection = connection; 14 | } 15 | 16 | protected override void Dispose(bool disposing) 17 | { 18 | if (disposing) 19 | { 20 | if (_connection != null) 21 | { 22 | _connection.Dispose(); 23 | _connection = null; 24 | } 25 | } 26 | 27 | base.Dispose(disposing); 28 | } 29 | 30 | protected HttpConnection GetConnectionOrThrow() 31 | { 32 | return _connection ?? 33 | // This should only ever happen if the user-code that was handed this instance disposed of 34 | // it, which is misuse, or held onto it and tried to use it later after we've disposed of it, 35 | // which is also misuse. 36 | ThrowObjectDisposedException(); 37 | } 38 | 39 | private HttpConnection ThrowObjectDisposedException() => throw new ObjectDisposedException(GetType().Name); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpContentWriteStream.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | using System.IO; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | 10 | namespace System.Net.Http 11 | { 12 | internal partial class HttpConnection : IDisposable 13 | { 14 | private abstract class HttpContentWriteStream : HttpContentStream 15 | { 16 | public HttpContentWriteStream(HttpConnection connection) : base(connection) => 17 | Debug.Assert(connection != null); 18 | 19 | public sealed override bool CanRead => false; 20 | public sealed override bool CanWrite => true; 21 | 22 | public sealed override void Flush() => 23 | _connection?.Flush(); 24 | 25 | public sealed override Task FlushAsync(CancellationToken ignored) 26 | { 27 | HttpConnection connection = _connection; 28 | return connection != null ? 29 | connection.FlushAsync().AsTask() : 30 | default; 31 | } 32 | 33 | public sealed override int Read(Span buffer) => throw new NotSupportedException(); 34 | 35 | public sealed override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken) => throw new NotSupportedException(); 36 | 37 | public sealed override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) => throw new NotSupportedException(); 38 | 39 | public abstract Task FinishAsync(); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpEnvironmentProxy.Unix.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace System.Net.Http 6 | { 7 | internal sealed partial class HttpEnvironmentProxy : IWebProxy 8 | { 9 | public static bool TryCreate(out IWebProxy proxy) 10 | { 11 | // Get environment variables. Protocol specific take precedence over 12 | // general all_*, lower case variable has precedence over upper case. 13 | // Note that curl uses HTTPS_PROXY but not HTTP_PROXY. 14 | 15 | Uri httpProxy = GetUriFromString(Environment.GetEnvironmentVariable(EnvHttpProxyLC)); 16 | if (httpProxy == null && Environment.GetEnvironmentVariable(EnvCGI) == null) 17 | { 18 | httpProxy = GetUriFromString(Environment.GetEnvironmentVariable(EnvHttpProxyUC)); 19 | } 20 | 21 | Uri httpsProxy = GetUriFromString(Environment.GetEnvironmentVariable(EnvHttpsProxyLC)) ?? 22 | GetUriFromString(Environment.GetEnvironmentVariable(EnvHttpsProxyUC)); 23 | 24 | if (httpProxy == null || httpsProxy == null) 25 | { 26 | Uri allProxy = GetUriFromString(Environment.GetEnvironmentVariable(EnvAllProxyLC)) ?? 27 | GetUriFromString(Environment.GetEnvironmentVariable(EnvAllProxyUC)); 28 | 29 | if (httpProxy == null) 30 | { 31 | httpProxy = allProxy; 32 | } 33 | 34 | if (httpsProxy == null) 35 | { 36 | httpsProxy = allProxy; 37 | } 38 | } 39 | 40 | // Do not instantiate if nothing is set. 41 | // Caller may pick some other proxy type. 42 | if (httpProxy == null && httpsProxy == null) 43 | { 44 | proxy = null; 45 | return false; 46 | } 47 | 48 | string noProxy = Environment.GetEnvironmentVariable(EnvNoProxyLC) ?? 49 | Environment.GetEnvironmentVariable(EnvNoProxyUC); 50 | proxy = new HttpEnvironmentProxy(httpProxy, httpsProxy, noProxy); 51 | 52 | return true; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpEnvironmentProxy.Windows.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace System.Net.Http 6 | { 7 | internal sealed partial class HttpEnvironmentProxy : IWebProxy 8 | { 9 | public static bool TryCreate(out IWebProxy proxy) 10 | { 11 | // Get environment variables. Protocol specific take precedence over 12 | // general all_*. On Windows, environment variables are case insensitive. 13 | 14 | Uri httpProxy = null; 15 | if (Environment.GetEnvironmentVariable(EnvCGI) == null) 16 | { 17 | httpProxy = GetUriFromString(Environment.GetEnvironmentVariable(EnvHttpProxyUC)); 18 | } 19 | 20 | Uri httpsProxy = GetUriFromString(Environment.GetEnvironmentVariable(EnvHttpsProxyUC)); 21 | 22 | if (httpProxy == null || httpsProxy == null) 23 | { 24 | Uri allProxy = GetUriFromString(Environment.GetEnvironmentVariable(EnvAllProxyUC)); 25 | 26 | if (httpProxy == null) 27 | { 28 | httpProxy = allProxy; 29 | } 30 | 31 | if (httpsProxy == null) 32 | { 33 | httpsProxy = allProxy; 34 | } 35 | } 36 | 37 | // Do not instantiate if nothing is set. 38 | // Caller may pick some other proxy type. 39 | if (httpProxy == null && httpsProxy == null) 40 | { 41 | proxy = null; 42 | return false; 43 | } 44 | 45 | string noProxy = Environment.GetEnvironmentVariable(EnvNoProxyUC); 46 | proxy = new HttpEnvironmentProxy(httpProxy, httpsProxy, noProxy); 47 | 48 | return true; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpNoProxy.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace System.Net.Http 6 | { 7 | internal sealed class HttpNoProxy : IWebProxy 8 | { 9 | public ICredentials Credentials { get; set; } 10 | public Uri GetProxy(Uri destination) => null; 11 | public bool IsBypassed(Uri host) => true; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/IHttpTrace.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Runtime.CompilerServices; 6 | 7 | namespace System.Net.Http 8 | { 9 | internal interface IHttpTrace 10 | { 11 | void Trace(string message, [CallerMemberName] string memberName = null); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SystemProxyInfo.OSX.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace System.Net.Http 6 | { 7 | internal static partial class SystemProxyInfo 8 | { 9 | // On OSX we get default proxy configuration from either environment variables or the OSX system proxy. 10 | public static IWebProxy ConstructSystemProxy() 11 | { 12 | return HttpEnvironmentProxy.TryCreate(out IWebProxy proxy) ? proxy : new MacProxy(); 13 | } 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SystemProxyInfo.Unix.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace System.Net.Http 6 | { 7 | internal static partial class SystemProxyInfo 8 | { 9 | // On Unix (except for OSX) we get default proxy configuration from environment variables. If the 10 | // environment variables are not defined, we return an IWebProxy object that effectively is 11 | // the "no proxy" object. 12 | public static IWebProxy ConstructSystemProxy() 13 | { 14 | return HttpEnvironmentProxy.TryCreate(out IWebProxy proxy) ? proxy : new HttpNoProxy(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SystemProxyInfo.Windows.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace System.Net.Http 6 | { 7 | internal static partial class SystemProxyInfo 8 | { 9 | // On Windows we get default proxy configuration from either environment variables or the Windows system proxy. 10 | public static IWebProxy ConstructSystemProxy() 11 | { 12 | if (!HttpEnvironmentProxy.TryCreate(out IWebProxy proxy)) 13 | { 14 | HttpWindowsProxy.TryCreate(out proxy); 15 | } 16 | 17 | return proxy ?? new HttpNoProxy(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SystemProxyInfo.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace System.Net.Http 6 | { 7 | internal static partial class SystemProxyInfo 8 | { 9 | public static IWebProxy Proxy => s_proxy.Value; 10 | 11 | private static readonly Lazy s_proxy = new Lazy(ConstructSystemProxy); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SystemProxyInfo.uap.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace System.Net.Http 6 | { 7 | internal static partial class SystemProxyInfo 8 | { 9 | public static IWebProxy ConstructSystemProxy() 10 | { 11 | // For UAP this is currently not implemented. 12 | return new HttpNoProxy(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/TaskCompletionSourceWithCancellation.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace System.Net.Http 9 | { 10 | internal class TaskCompletionSourceWithCancellation : TaskCompletionSource 11 | { 12 | private CancellationToken _cancellationToken; 13 | 14 | public TaskCompletionSourceWithCancellation() : base(TaskCreationOptions.RunContinuationsAsynchronously) 15 | { 16 | } 17 | 18 | private void OnCancellation() 19 | { 20 | TrySetCanceled(_cancellationToken); 21 | } 22 | 23 | public async Task WaitWithCancellationAsync(CancellationToken cancellationToken) 24 | { 25 | _cancellationToken = cancellationToken; 26 | using (cancellationToken.UnsafeRegister(s => ((TaskCompletionSourceWithCancellation)s).OnCancellation(), this)) 27 | { 28 | return await Task.ConfigureAwait(false); 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/System/Net/Http/StringContent.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.IO; 6 | using System.Net.Http.Headers; 7 | using System.Text; 8 | using System.Threading; 9 | using System.Threading.Tasks; 10 | 11 | namespace System.Net.Http 12 | { 13 | public class StringContent : ByteArrayContent 14 | { 15 | private const string DefaultMediaType = "text/plain"; 16 | 17 | public StringContent(string content) 18 | : this(content, null, null) 19 | { 20 | } 21 | 22 | public StringContent(string content, Encoding encoding) 23 | : this(content, encoding, null) 24 | { 25 | } 26 | 27 | public StringContent(string content, Encoding encoding, string mediaType) 28 | : base(GetContentByteArray(content, encoding)) 29 | { 30 | // Initialize the 'Content-Type' header with information provided by parameters. 31 | MediaTypeHeaderValue headerValue = new MediaTypeHeaderValue((mediaType == null) ? DefaultMediaType : mediaType); 32 | headerValue.CharSet = (encoding == null) ? HttpContent.DefaultStringEncoding.WebName : encoding.WebName; 33 | 34 | Headers.ContentType = headerValue; 35 | } 36 | 37 | // A StringContent is essentially a ByteArrayContent. We serialize the string into a byte-array in the 38 | // constructor using encoding information provided by the caller (if any). When this content is sent, the 39 | // Content-Length can be retrieved easily (length of the array). 40 | private static byte[] GetContentByteArray(string content, Encoding encoding) 41 | { 42 | // In this case we treat 'null' strings different from string.Empty in order to be consistent with our 43 | // other *Content constructors: 'null' throws, empty values are allowed. 44 | if (content == null) 45 | { 46 | throw new ArgumentNullException(nameof(content)); 47 | } 48 | 49 | if (encoding == null) 50 | { 51 | encoding = HttpContent.DefaultStringEncoding; 52 | } 53 | 54 | return encoding.GetBytes(content); 55 | } 56 | 57 | internal override Task SerializeToStreamAsync(Stream stream, TransportContext context, CancellationToken cancellationToken) => 58 | // Only skip the original protected virtual SerializeToStreamAsync if this 59 | // isn't a derived type that may have overridden the behavior. 60 | GetType() == typeof(StringContent) ? SerializeToStreamAsyncCore(stream, cancellationToken) : 61 | base.SerializeToStreamAsync(stream, context, cancellationToken); 62 | 63 | internal override Stream TryCreateContentReadStream() => 64 | GetType() == typeof(StringContent) ? CreateMemoryStreamForByteArray() : // type check ensures we use possible derived type's CreateContentReadStreamAsync override 65 | null; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/uap/System/Net/CookieHelper.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Net.Internal; 8 | using InternalCookieException = System.Net.Internal.CookieException; 9 | 10 | namespace System.Net 11 | { 12 | internal static class CookieHelper 13 | { 14 | internal static IEnumerable GetCookiesFromHeader(string setCookieHeader) 15 | { 16 | List cookieStrings = new List(); 17 | 18 | try 19 | { 20 | CookieParser parser = new CookieParser(setCookieHeader); 21 | string cookieString; 22 | 23 | while ((cookieString = parser.GetString()) != null) 24 | { 25 | cookieStrings.Add(cookieString); 26 | } 27 | } 28 | catch (InternalCookieException) 29 | { 30 | // TODO (#7856): We should log this. But there isn't much we can do about it other 31 | // than to drop the rest of the cookies. 32 | } 33 | 34 | return cookieStrings; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/System.Net.Http/src/uap/System/Net/cookieexception.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics.CodeAnalysis; 6 | 7 | // The uap #define is used in some source files to indicate we are compiling classes 8 | // directly into the UWP System.Net.Http.dll implementation assembly in order to use internal class 9 | // methods. Internal methods are needed in order to map cookie response headers from the WinRT Windows.Web.Http APIs. 10 | // Windows.Web.Http is used underneath the System.Net.Http classes on .NET Native. Having other similarly 11 | // named classes would normally conflict with the public System.Net namespace classes. 12 | // So, we need to move the classes to a different namespace. Those classes are never 13 | // exposed up to user code so there isn't a problem. In the future, we might expose some of the internal methods 14 | // as new public APIs and then we can remove this duplicate source code inclusion in the binaries. 15 | #if uap 16 | namespace System.Net.Internal 17 | #else 18 | namespace System.Net 19 | #endif 20 | { 21 | /// 22 | /// [To be supplied.] 23 | /// 24 | public class CookieException : FormatException 25 | { 26 | /// 27 | /// [To be supplied.] 28 | /// 29 | public CookieException() : base() 30 | { 31 | } 32 | 33 | internal CookieException(string message) : base(message) 34 | { 35 | } 36 | 37 | internal CookieException(string message, Exception inner) : base(message, inner) 38 | { 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/ByteAtATimeContent.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.IO; 6 | using System.Threading.Tasks; 7 | 8 | namespace System.Net.Http.Functional.Tests 9 | { 10 | internal sealed class ByteAtATimeContent : HttpContent 11 | { 12 | private readonly Task _waitToSend; 13 | private readonly TaskCompletionSource _startedSend; 14 | private readonly int _length; 15 | private readonly int _millisecondDelayBetweenBytes; 16 | 17 | public ByteAtATimeContent(int length) : this(length, Task.CompletedTask, new TaskCompletionSource(), millisecondDelayBetweenBytes: 0) { } 18 | 19 | public ByteAtATimeContent(int length, Task waitToSend, TaskCompletionSource startedSend, int millisecondDelayBetweenBytes) 20 | { 21 | _length = length; 22 | _waitToSend = waitToSend; 23 | _startedSend = startedSend; 24 | _millisecondDelayBetweenBytes = millisecondDelayBetweenBytes; 25 | } 26 | 27 | protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context) 28 | { 29 | await _waitToSend; 30 | _startedSend.SetResult(true); 31 | 32 | var buffer = new byte[1]; 33 | for (int i = 0; i < _length; i++) 34 | { 35 | buffer[0] = (byte)i; 36 | await stream.WriteAsync(buffer); 37 | await stream.FlushAsync(); 38 | await Task.Delay(_millisecondDelayBetweenBytes); 39 | } 40 | } 41 | 42 | protected override bool TryComputeLength(out long length) 43 | { 44 | length = _length; 45 | return true; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/ChannelBindingAwareContent.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.IO; 6 | using System.Security.Authentication.ExtendedProtection; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace System.Net.Http.Functional.Tests 11 | { 12 | internal sealed class ChannelBindingAwareContent : HttpContent 13 | { 14 | private readonly byte[] _content; 15 | 16 | public ChannelBindingAwareContent(string content) 17 | { 18 | _content = Encoding.UTF8.GetBytes(content); 19 | } 20 | 21 | public ChannelBinding ChannelBinding { get ; private set; } 22 | 23 | protected override Task SerializeToStreamAsync(Stream stream, TransportContext context) 24 | { 25 | ChannelBinding = context.GetChannelBinding(ChannelBindingKind.Endpoint); 26 | return stream.WriteAsync(_content, 0, _content.Length); 27 | } 28 | 29 | protected override bool TryComputeLength(out long length) 30 | { 31 | length = _content.Length; 32 | return true; 33 | } 34 | 35 | protected override Task CreateContentReadStreamAsync() 36 | { 37 | return Task.FromResult(new MemoryStream(_content, 0, _content.Length, writable: false)); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/Configurations.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp-Windows_NT; 5 | netcoreapp-Unix; 6 | uap-Windows_NT; 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/CustomContent.netcore.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.IO; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace System.Net.Http.Functional.Tests 10 | { 11 | internal partial class CustomContent : HttpContent 12 | { 13 | internal class SlowTestStream : CustomStream 14 | { 15 | private int _delay = 1000; 16 | private int _count; 17 | private int _trigger; 18 | private byte[] _content; 19 | private readonly TaskCompletionSource _sendingDone; 20 | private int _iteration; 21 | 22 | internal SlowTestStream(byte[] content, TaskCompletionSource tsc, int count=10, int trigger=1) : base(content, false) 23 | { 24 | _sendingDone = tsc; 25 | _trigger = trigger; 26 | _count = count; 27 | _content = content; 28 | } 29 | 30 | public override async Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) 31 | { 32 | var buffer = new byte[bufferSize]; 33 | int bytesRead; 34 | while ((bytesRead = await ReadAsync(buffer, cancellationToken)) != 0) 35 | { 36 | await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken); 37 | await destination.FlushAsync(); // some tests rely on data being written promptly to coordinate between client/server sides of test 38 | } 39 | } 40 | 41 | public async override ValueTask ReadAsync(Memory destination, CancellationToken cancellationToken) 42 | { 43 | if (_failException != null) 44 | { 45 | throw _failException; 46 | } 47 | 48 | if (_delay > 0) 49 | { 50 | await Task.Delay(_delay, cancellationToken); 51 | } 52 | 53 | _iteration++; 54 | if (_iteration == _trigger) 55 | { 56 | _sendingDone?.TrySetResult(true); 57 | } 58 | 59 | if (_count == _iteration) 60 | { 61 | return 0; 62 | } 63 | 64 | return _content.Length; 65 | } 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/DribbleStream.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.IO; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace System.Net.Http.Functional.Tests 10 | { 11 | public sealed class DribbleStream : Stream 12 | { 13 | private readonly Stream _wrapped; 14 | private readonly bool _clientDisconnectAllowed; 15 | 16 | public DribbleStream(Stream wrapped, bool clientDisconnectAllowed = false) 17 | { 18 | _wrapped = wrapped; 19 | _clientDisconnectAllowed = clientDisconnectAllowed; 20 | } 21 | 22 | public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) 23 | { 24 | try 25 | { 26 | for (int i = 0; i < count; i++) 27 | { 28 | await _wrapped.WriteAsync(buffer, offset + i, 1); 29 | await _wrapped.FlushAsync(); 30 | await Task.Yield(); // introduce short delays, enough to send packets individually but not so long as to extend test duration significantly 31 | } 32 | } 33 | catch (IOException) when (_clientDisconnectAllowed) 34 | { 35 | } 36 | } 37 | 38 | public override void Write(byte[] buffer, int offset, int count) 39 | { 40 | try 41 | { 42 | for (int i = 0; i < count; i++) 43 | { 44 | _wrapped.Write(buffer, offset + i, 1); 45 | _wrapped.Flush(); 46 | } 47 | } 48 | catch (IOException) when (_clientDisconnectAllowed) 49 | { 50 | } 51 | } 52 | 53 | public override bool CanRead => _wrapped.CanRead; 54 | public override bool CanSeek => _wrapped.CanSeek; 55 | public override bool CanWrite => _wrapped.CanWrite; 56 | public override long Length => _wrapped.Length; 57 | public override long Position { get => _wrapped.Position; set => _wrapped.Position = value; } 58 | public override void Flush() => _wrapped.Flush(); 59 | public override Task FlushAsync(CancellationToken cancellationToken) => _wrapped.FlushAsync(cancellationToken); 60 | public override int Read(byte[] buffer, int offset, int count) => _wrapped.Read(buffer, offset, count); 61 | public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => _wrapped.ReadAsync(buffer, offset, count, cancellationToken); 62 | public override long Seek(long offset, SeekOrigin origin) => _wrapped.Seek(offset, origin); 63 | public override void SetLength(long value) => _wrapped.SetLength(value); 64 | public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) => _wrapped.CopyToAsync(destination, bufferSize, cancellationToken); 65 | public override void Close() => _wrapped.Close(); 66 | protected override void Dispose(bool disposing) => _wrapped.Dispose(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/FakeDiagnosticSourceListenerObserver.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using System.Diagnostics; 7 | 8 | namespace System.Net.Http.Functional.Tests 9 | { 10 | public sealed class FakeDiagnosticListenerObserver : IObserver 11 | { 12 | private class FakeDiagnosticSourceWriteObserver : IObserver> 13 | { 14 | private readonly Action> _writeCallback; 15 | 16 | public FakeDiagnosticSourceWriteObserver(Action> writeCallback) 17 | { 18 | _writeCallback = writeCallback; 19 | } 20 | 21 | public void OnCompleted() 22 | { 23 | } 24 | 25 | public void OnError(Exception error) 26 | { 27 | } 28 | 29 | public void OnNext(KeyValuePair value) 30 | { 31 | _writeCallback(value); 32 | } 33 | } 34 | 35 | private readonly Action> _writeCallback; 36 | 37 | private Func _writeObserverEnabled = (name, arg1, arg2) => false; 38 | 39 | public FakeDiagnosticListenerObserver(Action> writeCallback) 40 | { 41 | _writeCallback = writeCallback; 42 | } 43 | 44 | public void OnCompleted() 45 | { 46 | } 47 | 48 | public void OnError(Exception error) 49 | { 50 | } 51 | 52 | public void OnNext(DiagnosticListener value) 53 | { 54 | if (value.Name.Equals("HttpHandlerDiagnosticListener")) 55 | { 56 | value.Subscribe(new FakeDiagnosticSourceWriteObserver(_writeCallback), IsEnabled); 57 | } 58 | } 59 | 60 | public void Enable() 61 | { 62 | _writeObserverEnabled = (name, arg1, arg2) => true; 63 | } 64 | 65 | public void Enable(Func writeObserverEnabled) 66 | { 67 | _writeObserverEnabled = (name, arg1, arg2) => writeObserverEnabled(name); 68 | } 69 | 70 | public void Enable(Func writeObserverEnabled) 71 | { 72 | _writeObserverEnabled = writeObserverEnabled; 73 | } 74 | 75 | public void Disable() 76 | { 77 | _writeObserverEnabled = (name, arg1, arg2) => false; 78 | } 79 | 80 | private bool IsEnabled(string s, object arg1, object arg2) 81 | { 82 | return _writeObserverEnabled.Invoke(s, arg1, arg2); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/HPackTest.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Diagnostics; 10 | using System.IO; 11 | using System.Net.Test.Common; 12 | using System.Text; 13 | using System.Threading; 14 | using System.Threading.Tasks; 15 | using Xunit; 16 | using Xunit.Abstractions; 17 | using System.Data; 18 | using System.Runtime.InteropServices.ComTypes; 19 | 20 | namespace System.Net.Http.Functional.Tests 21 | { 22 | public class HPackTest : HttpClientHandlerTestBase 23 | { 24 | protected override bool UseSocketsHttpHandler => true; 25 | protected override bool UseHttp2 => true; 26 | 27 | public HPackTest(ITestOutputHelper output) : base(output) 28 | { 29 | } 30 | 31 | private const string LiteralHeaderName = "x-literal-header"; 32 | private const string LiteralHeaderValue = "testing 456"; 33 | 34 | [Theory] 35 | [MemberData(nameof(HeaderEncodingTestData))] 36 | public async Task HPack_HeaderEncoding(string headerName, string expectedValue, byte[] expectedEncoding) 37 | { 38 | await Http2LoopbackServer.CreateClientAndServerAsync( 39 | async uri => 40 | { 41 | using HttpClient client = CreateHttpClient(); 42 | 43 | using HttpRequestMessage request = new HttpRequestMessage(); 44 | request.Method = HttpMethod.Post; 45 | request.RequestUri = uri; 46 | request.Version = HttpVersion.Version20; 47 | request.Content = new StringContent("testing 123"); 48 | request.Headers.Add(LiteralHeaderName, LiteralHeaderValue); 49 | 50 | (await client.SendAsync(request)).Dispose(); 51 | }, 52 | async server => 53 | { 54 | Http2LoopbackConnection connection = await server.EstablishConnectionAsync(); 55 | (int streamId, HttpRequestData requestData) = await connection.ReadAndParseRequestHeaderAsync(); 56 | 57 | HttpHeaderData header = requestData.Headers.Single(x => x.Name == headerName); 58 | Assert.Equal(expectedValue, header.Value); 59 | Assert.True(expectedEncoding.AsSpan().SequenceEqual(header.Raw)); 60 | 61 | await connection.SendDefaultResponseAsync(streamId); 62 | }); 63 | } 64 | 65 | public static IEnumerable HeaderEncodingTestData() 66 | { 67 | // Indexed name, indexed value. 68 | yield return new object[] { ":method", "POST", new byte[] { 0x83 } }; 69 | yield return new object[] { ":path", "/", new byte[] { 0x84 } }; 70 | 71 | // Indexed name, literal value. 72 | yield return new object[] { "content-type", "text/plain; charset=utf-8", new byte[] { 0x0F, 0x10, 0x19, 0x74, 0x65, 0x78, 0x74, 0x2F, 0x70, 0x6C, 0x61, 0x69, 0x6E, 0x3B, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3D, 0x75, 0x74, 0x66, 0x2D, 0x38 } }; 73 | 74 | // Literal name, literal value. 75 | yield return new object[] { LiteralHeaderName, LiteralHeaderValue, new byte[] { 0x00, 0x10, 0x78, 0x2D, 0x6C, 0x69, 0x74, 0x65, 0x72, 0x61, 0x6C, 0x2D, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x0B, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x34, 0x35, 0x36 } }; 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Finalization.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Net.Test.Common; 6 | using System.Runtime.CompilerServices; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | using Xunit; 10 | using Xunit.Abstractions; 11 | 12 | namespace System.Net.Http.Functional.Tests 13 | { 14 | public abstract class HttpClientHandler_Finalization_Test : HttpClientHandlerTestBase 15 | { 16 | public HttpClientHandler_Finalization_Test(ITestOutputHelper output) : base(output) { } 17 | 18 | [MethodImpl(MethodImplOptions.NoInlining)] 19 | private static Task GetAndDropResponse(HttpClient client, Uri url) 20 | { 21 | return Task.Run(async () => 22 | { 23 | // Get the response stream, but don't dispose it or return it. Just drop it. 24 | await client.GetStreamAsync(url); 25 | }); 26 | } 27 | 28 | [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.SupportsAlpn))] 29 | public async Task IncompleteResponseStream_ResponseDropped_CancelsRequestToServer() 30 | { 31 | using (HttpClient client = CreateHttpClient()) 32 | { 33 | bool stopGCs = false; 34 | await LoopbackServerFactory.CreateClientAndServerAsync(async url => 35 | { 36 | await GetAndDropResponse(client, url); 37 | 38 | while (!Volatile.Read(ref stopGCs)) 39 | { 40 | await Task.Delay(10); 41 | GC.Collect(); 42 | GC.WaitForPendingFinalizers(); 43 | } 44 | }, 45 | server => server.AcceptConnectionAsync(async connection => 46 | { 47 | try 48 | { 49 | HttpRequestData data = await connection.ReadRequestDataAsync(readBody: false); 50 | await connection.SendResponseHeadersAsync(headers: new HttpHeaderData[] { new HttpHeaderData("SomeHeaderName", "AndValue") }); 51 | await connection.WaitForCancellationAsync(); 52 | } 53 | finally 54 | { 55 | Volatile.Write(ref stopGCs, true); 56 | } 57 | })); 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http1.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using System.Diagnostics; 7 | using System.Net.Test.Common; 8 | using System.Threading.Tasks; 9 | 10 | using Xunit; 11 | using Xunit.Abstractions; 12 | 13 | namespace System.Net.Http.Functional.Tests 14 | { 15 | // This class is dedicated to SocketHttpHandler tests specific to HTTP/1.x. 16 | public class HttpClientHandlerTest_Http1 : HttpClientHandlerTestBase 17 | { 18 | protected override bool UseSocketsHttpHandler => true; 19 | 20 | public HttpClientHandlerTest_Http1(ITestOutputHelper output) : base(output) { } 21 | 22 | [Fact] 23 | public async Task SendAsync_HostHeader_First() 24 | { 25 | // RFC 7230 3.2.2. Field Order 26 | await LoopbackServer.CreateServerAsync(async (server, url) => 27 | { 28 | using (HttpClient client = CreateHttpClient()) 29 | { 30 | HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url) { Version = HttpVersion.Version11 }; 31 | request.Headers.Add("X-foo", "bar"); 32 | 33 | Task sendTask = client.SendAsync(request); 34 | 35 | string[] headers = (await server.AcceptConnectionSendResponseAndCloseAsync()).ToArray(); 36 | await sendTask; 37 | 38 | Assert.True(headers[1].StartsWith("Host")); 39 | } 40 | }); 41 | } 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ServerCertificates.Windows.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace System.Net.Http.Functional.Tests 6 | { 7 | public abstract partial class HttpClientHandler_ServerCertificates_Test 8 | { 9 | private static bool ShouldSuppressRevocationException => false; 10 | 11 | internal bool BackendSupportsCustomCertificateHandling => true; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.SslProtocols.Unix.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.IO; 6 | using System.Net.Security; 7 | using System.Net.Sockets; 8 | using System.Net.Test.Common; 9 | using System.Runtime.InteropServices; 10 | using System.Security.Authentication; 11 | using System.Threading; 12 | using System.Threading.Tasks; 13 | using Xunit; 14 | 15 | namespace System.Net.Http.Functional.Tests 16 | { 17 | public abstract partial class HttpClientHandler_SslProtocols_Test 18 | { 19 | private bool BackendSupportsSslConfiguration => 20 | UseSocketsHttpHandler || TestHelper.NativeHandlerSupportsSslConfiguration(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.SslProtocols.Windows.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | 6 | namespace System.Net.Http.Functional.Tests 7 | { 8 | public abstract partial class HttpClientHandler_SslProtocols_Test 9 | { 10 | private static bool BackendSupportsSslConfiguration => true; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/HttpMethodTest.netcoreapp.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | 7 | using Xunit; 8 | 9 | namespace System.Net.Http.Functional.Tests 10 | { 11 | public partial class HttpMethodTest 12 | { 13 | [Fact] 14 | public void Patch_VerifyValue_PropertyNameMatchesHttpMethodName() 15 | { 16 | Assert.Equal("PATCH", HttpMethod.Patch.Method); 17 | } 18 | 19 | static partial void AddStaticHttpMethods(List staticHttpMethods) 20 | { 21 | staticHttpMethods.Add(new object[] { HttpMethod.Patch }); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/MultiInterfaceStreamContent.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.IO; 6 | using System.Threading.Tasks; 7 | 8 | namespace System.Net.Http.Functional.Tests 9 | { 10 | public class MultiInterfaceStreamContent : StreamContent 11 | { 12 | Stream _content; 13 | 14 | public MultiInterfaceStreamContent(Stream content) : base(content) 15 | { 16 | _content = content; 17 | } 18 | 19 | protected override Task CreateContentReadStreamAsync() 20 | { 21 | return Task.FromResult(_content); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | ".NET Core xUnit Console": { 4 | "commandName": "Executable", 5 | "executablePath": "$(TestHostRootPath)dotnet.exe", 6 | "commandLineArgs": "$(RunArguments) -parallel none", 7 | "workingDirectory": "$(RunWorkingDirectory)" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/RepeatedFlushContent.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.IO; 7 | using System.Threading.Tasks; 8 | 9 | namespace System.Net.Http.Functional.Tests 10 | { 11 | public sealed class RepeatedFlushContent : StringContent 12 | { 13 | public RepeatedFlushContent(string content) : base(content) 14 | { 15 | } 16 | 17 | protected override Task SerializeToStreamAsync(Stream stream, TransportContext context) 18 | { 19 | stream.Flush(); 20 | stream.Flush(); 21 | return base.SerializeToStreamAsync(stream, context); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/SchSendAuxRecordHttpTest.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Net.Test.Common; 6 | using System.Security.Authentication; 7 | using System.Threading.Tasks; 8 | 9 | using Xunit; 10 | using Xunit.Abstractions; 11 | 12 | namespace System.Net.Http.Functional.Tests 13 | { 14 | [ActiveIssue(26539)] // Flaky test 15 | [SkipOnTargetFramework(TargetFrameworkMonikers.Uap, "HttpsTestServer not compatible on UAP")] 16 | public abstract class SchSendAuxRecordHttpTest : HttpClientHandlerTestBase 17 | { 18 | public SchSendAuxRecordHttpTest(ITestOutputHelper output) : base(output) { } 19 | 20 | [Fact] 21 | [PlatformSpecific(TestPlatforms.Windows)] 22 | public async Task HttpClient_ClientUsesAuxRecord_Ok() 23 | { 24 | var options = new HttpsTestServer.Options(); 25 | options.AllowedProtocols = SslProtocols.Tls; 26 | 27 | using (var server = new HttpsTestServer(options)) 28 | using (HttpClientHandler handler = CreateHttpClientHandler()) 29 | using (HttpClient client = CreateHttpClient(handler)) 30 | { 31 | handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates; 32 | server.Start(); 33 | 34 | var tasks = new Task[2]; 35 | 36 | bool serverAuxRecordDetected = false; 37 | bool serverAuxRecordDetectedInconclusive = false; 38 | int serverTotalBytesReceived = 0; 39 | int serverChunks = 0; 40 | 41 | tasks[0] = server.AcceptHttpsClientAsync((requestString) => 42 | { 43 | serverTotalBytesReceived += requestString.Length; 44 | 45 | if (serverTotalBytesReceived == 1 && serverChunks == 0) 46 | { 47 | serverAuxRecordDetected = true; 48 | } 49 | 50 | serverChunks++; 51 | 52 | // Test is inconclusive if any non-CBC cipher is used: 53 | if (server.Stream.CipherAlgorithm == CipherAlgorithmType.None || 54 | server.Stream.CipherAlgorithm == CipherAlgorithmType.Null || 55 | server.Stream.CipherAlgorithm == CipherAlgorithmType.Rc4) 56 | { 57 | serverAuxRecordDetectedInconclusive = true; 58 | } 59 | 60 | if (serverTotalBytesReceived < 5) 61 | { 62 | return Task.FromResult(null); 63 | } 64 | else 65 | { 66 | return Task.FromResult(HttpsTestServer.Options.DefaultResponseString); 67 | } 68 | }); 69 | 70 | string requestUriString = "https://localhost:" + server.Port.ToString(); 71 | tasks[1] = client.GetStringAsync(requestUriString); 72 | 73 | await tasks.WhenAllOrAnyFailed(15 * 1000); 74 | 75 | if (serverAuxRecordDetectedInconclusive) 76 | { 77 | _output.WriteLine("Test inconclusive: The Operating system preferred a non-CBC or Null cipher."); 78 | } 79 | else 80 | { 81 | Assert.True(serverAuxRecordDetected, "Server reports: Client auxiliary record not detected."); 82 | } 83 | } 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/SelectedSitesTest.txt: -------------------------------------------------------------------------------- 1 | http://facebook.com 2 | http://google.com 3 | http://youtube.com 4 | http://live.com 5 | http://yahoo.com 6 | http://wikipedia.org 7 | http://msn.com 8 | http://blogger.com 9 | http://microsoft.com 10 | http://bing.com 11 | http://qq.com 12 | http://baidu.com 13 | http://ask.com 14 | http://wordpress.com 15 | http://mozilla.com 16 | http://apple.com 17 | http://taobao.com 18 | http://amazon.com 19 | http://twitter.com 20 | http://ebay.com 21 | http://myspace.com 22 | http://ehow.com 23 | http://cnet.com 24 | http://flickr.com 25 | http://aol.com 26 | http://google.com.hk 27 | http://sohu.com 28 | http://yahoo.co.jp 29 | http://cnn.com 30 | http://bbc.co.uk 31 | http://linkedin.com 32 | http://craigslist.org 33 | http://google.fr 34 | http://nytimes.com 35 | http://msnbc.com 36 | http://skype.com 37 | http://mapquest.com 38 | http://uol.com.br 39 | http://alibaba.com 40 | http://paypal.com 41 | http://espn.com 42 | http://real.com 43 | http://hp.com 44 | http://dictionary.com 45 | http://sourceforge.net 46 | http://terra.com.br 47 | http://opera.com 48 | http://google.es 49 | http://walmart.com 50 | http://dailymail.co.uk -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/StringContentTest.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.IO; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | using Xunit; 11 | using Xunit.Abstractions; 12 | 13 | namespace System.Net.Http.Functional.Tests 14 | { 15 | public class StringContentTest 16 | { 17 | [Fact] 18 | public void Ctor_NullString_ThrowsArgumentNullException() 19 | { 20 | Assert.Throws(() => new StringContent(null)); 21 | } 22 | 23 | [Fact] 24 | public async Task Ctor_EmptyString_Accept() 25 | { 26 | // Consider empty strings like null strings (null and empty strings should be treated equally). 27 | var content = new StringContent(string.Empty); 28 | Stream result = await content.ReadAsStreamAsync(); 29 | Assert.Equal(0, result.Length); 30 | } 31 | 32 | [Fact] 33 | public async Task Ctor_UseCustomEncodingAndMediaType_EncodingUsedAndContentTypeHeaderUpdated() 34 | { 35 | // Use UTF-8 encoding to serialize a chinese string. 36 | string sourceString = "\u4f1a\u5458\u670d\u52a1"; 37 | 38 | var content = new StringContent(sourceString, Encoding.UTF8, "application/custom"); 39 | 40 | Assert.Equal("application/custom", content.Headers.ContentType.MediaType); 41 | Assert.Equal("utf-8", content.Headers.ContentType.CharSet); 42 | 43 | var destination = new MemoryStream(12); 44 | await content.CopyToAsync(destination); 45 | 46 | string destinationString = Encoding.UTF8.GetString(destination.ToArray(), 0, (int)destination.Length); 47 | 48 | Assert.Equal(sourceString, destinationString); 49 | } 50 | 51 | [Fact] 52 | public async Task Ctor_DefineNoEncoding_DefaultEncodingUsed() 53 | { 54 | string sourceString = "\u00C4\u00E4\u00FC\u00DC"; 55 | var content = new StringContent(sourceString); 56 | Encoding defaultStringEncoding = Encoding.GetEncoding("utf-8"); 57 | 58 | // If no encoding is defined, the default encoding is used: utf-8 59 | Assert.Equal("text/plain", content.Headers.ContentType.MediaType); 60 | Assert.Equal(defaultStringEncoding.WebName, content.Headers.ContentType.CharSet); 61 | 62 | // Make sure the default encoding is also used when serializing the content. 63 | var destination = new MemoryStream(); 64 | await content.CopyToAsync(destination); 65 | 66 | Assert.Equal(8, destination.Length); 67 | 68 | destination.Seek(0, SeekOrigin.Begin); 69 | string roundTrip = new StreamReader(destination, defaultStringEncoding).ReadToEnd(); 70 | Assert.Equal(sourceString, roundTrip); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/SyncBlockingContent.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.IO; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace System.Net.Http.Functional.Tests 11 | { 12 | public sealed class SyncBlockingContent : StringContent 13 | { 14 | byte[] _content; 15 | 16 | public SyncBlockingContent(string content) : base(content) 17 | { 18 | _content = Encoding.UTF8.GetBytes(content); 19 | } 20 | 21 | protected override Task SerializeToStreamAsync(Stream stream, TransportContext context) 22 | { 23 | stream.Write(_content, 0, _content.Length); 24 | return Task.CompletedTask; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/ThrowingContent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace System.Net.Http.Functional.Tests 8 | { 9 | /// HttpContent that mocks exceptions on serialization. 10 | public class ThrowingContent : HttpContent 11 | { 12 | private readonly Func _exnFactory; 13 | private readonly int _length; 14 | 15 | public ThrowingContent(Func exnFactory, int length = 10) 16 | { 17 | _exnFactory = exnFactory; 18 | _length = length; 19 | } 20 | 21 | protected override Task SerializeToStreamAsync(Stream stream, TransportContext context) 22 | { 23 | throw _exnFactory(); 24 | } 25 | 26 | protected override bool TryComputeLength(out long length) 27 | { 28 | length = _length; 29 | return true; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/Watchdog.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Runtime.CompilerServices; 8 | using System.Text; 9 | using System.Threading; 10 | using System.Threading.Tasks; 11 | using Xunit; 12 | 13 | namespace System.Net.Http.Functional.Tests 14 | { 15 | /// 16 | /// This is using similar trick to GetStateMachineData 17 | /// If marked test runs for more than 60s it will print machine state and make sure it fails 18 | /// Usage (await MUST be run directly in the test, should not be called from other async method): 19 | /// using (await Watchdog.CreateAsync()) 20 | /// { 21 | /// // test code 22 | /// } 23 | /// 24 | internal class Watchdog : ICriticalNotifyCompletion 25 | { 26 | private object _box; 27 | 28 | private Watchdog() { } 29 | 30 | public static Watchdog CreateAsync() 31 | => new Watchdog(); 32 | 33 | public IDisposable GetResult() 34 | => new WatchdogImpl(_box); 35 | 36 | public Watchdog GetAwaiter() => this; 37 | public bool IsCompleted => false; 38 | public void OnCompleted(Action continuation) => UnsafeOnCompleted(continuation); 39 | public void UnsafeOnCompleted(Action continuation) 40 | { 41 | _box = continuation.Target; 42 | Task.Run(continuation); 43 | } 44 | 45 | private class WatchdogImpl : IDisposable 46 | { 47 | private bool _passed = true; 48 | private Timer _timer; 49 | 50 | public WatchdogImpl(object stateMachineData) 51 | { 52 | _timer = new Timer(s => 53 | { 54 | _passed = false; 55 | Console.WriteLine(GetStateMachineData.Describe(s)); 56 | }, 57 | stateMachineData, 58 | 60_000, 59 | 60_000); 60 | } 61 | 62 | public void Dispose() 63 | { 64 | _timer.Dispose(); 65 | Assert.True(_passed); 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/XUnitAssemblyAttributes.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using Xunit; 6 | 7 | // [ActiveIssue(35002)]: Disable parallel execution of System.Net.Http.FunctionalTests on UAP test runs 8 | [assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly, DisableTestParallelization = true)] 9 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/prerequisites/ShowIdentity.ashx: -------------------------------------------------------------------------------- 1 | <%@ WebHandler Language="C#" Class="ShowIdentity" %> 2 | 3 | using System; 4 | using System.Web; 5 | 6 | public class ShowIdentity : IHttpHandler 7 | { 8 | public void ProcessRequest (HttpContext context) 9 | { 10 | bool isAuthenticated = context.Request.IsAuthenticated; 11 | string user = isAuthenticated ? context.Request.LogonUserIdentity.Name : string.Empty; 12 | 13 | context.Response.ContentType = "application/json"; 14 | string json = 15 | "{\r\n" + 16 | " \"Authenticated\": \"" + isAuthenticated + "\",\r\n" + 17 | " \"User\": \""+ user + "\"\r\n" + 18 | "}\r\n"; 19 | 20 | context.Response.Write(json); 21 | } 22 | 23 | public bool IsReusable 24 | { 25 | get 26 | { 27 | return true; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/prerequisites/Web.config: -------------------------------------------------------------------------------- 1 |  5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/FunctionalTests/prerequisites/readme.txt: -------------------------------------------------------------------------------- 1 | // TODO: Add more details and scripts. 2 | // Issue #4989 (Provide a way for developers to self-instantiate a server for networking API tests) 3 | 4 | Some Windows tests require an Active Directory domain. Both the client machine running the tests and the server endpoint need to be on the same domain. 5 | 6 | Set up IIS and ASP.NET on the test server. Create two application directories with the following paths: 7 | 8 | /test/auth/negotiate 9 | /test/auth/multipleschemes 10 | 11 | Set authentication on both application directories to use integrated Windows authentication. Disable Anonymous access. 12 | 13 | In the 'multipleschemes' application, you'll use the BasicAuthModule.cs and web.config files in a compiled ASP.NET project. This allows Basic auth to 14 | be offered as well but ensures that it is listed first in the response headers. 15 | 16 | Create an additional local user account on the test machine with a specific username and password (see DefaultCredentialsTest.cs). 17 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/StressTests/HttpStress/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/StressTests/HttpStress/Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/StressTests/HttpStress/HttpStress.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.0 6 | preview 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/StressTests/HttpStress/HttpStress.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29021.251 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpStress", "HttpStress.csproj", "{6B32E657-6B17-419F-A5CA-1981CE7E05AE}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {6B32E657-6B17-419F-A5CA-1981CE7E05AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {6B32E657-6B17-419F-A5CA-1981CE7E05AE}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {6B32E657-6B17-419F-A5CA-1981CE7E05AE}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {6B32E657-6B17-419F-A5CA-1981CE7E05AE}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {BE19C273-6157-47D5-8616-1FA48989F91B} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/UnitTests/Configurations.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp-OSX; 5 | netcoreapp-Unix; 6 | netcoreapp-Windows_NT; 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/UnitTests/Fakes/MacProxy.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace System.Net.Http 6 | { 7 | internal sealed class MacProxy : IWebProxy 8 | { 9 | public ICredentials Credentials 10 | { 11 | get => throw NotImplemented.ByDesignWithMessage("Mac Proxy not implemented"); 12 | set => throw NotImplemented.ByDesignWithMessage("Mac Proxy not implemented"); 13 | } 14 | 15 | public Uri GetProxy(Uri targetUri) 16 | { 17 | throw NotImplemented.ByDesignWithMessage("Mac Proxy not implemented"); 18 | } 19 | 20 | public bool IsBypassed(Uri targetUri) 21 | { 22 | throw NotImplemented.ByDesignWithMessage("Mac Proxy not implemented"); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/UnitTests/Headers/CacheControlHeaderParserTest.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Net.Http.Headers; 6 | 7 | using Xunit; 8 | 9 | namespace System.Net.Http.Tests 10 | { 11 | public class CacheControlHeaderParserTest 12 | { 13 | [Fact] 14 | public void Properties_ReadValues_MatchExpectation() 15 | { 16 | HttpHeaderParser parser = CacheControlHeaderParser.Parser; 17 | Assert.True(parser.SupportsMultipleValues); 18 | Assert.Null(parser.Comparer); 19 | } 20 | 21 | [Fact] 22 | public void TryParse_SetOfValidValueStrings_ParsedCorrectly() 23 | { 24 | // Just verify parser is implemented correctly. Don't try to test syntax parsed by CacheControlHeaderValue. 25 | CacheControlHeaderValue expected = new CacheControlHeaderValue(); 26 | expected.NoStore = true; 27 | expected.MinFresh = new TimeSpan(0, 2, 3); 28 | CheckValidParsedValue("X , , no-store, min-fresh=123", 1, expected, 29); 29 | 30 | expected = new CacheControlHeaderValue(); 31 | expected.MaxStale = true; 32 | expected.NoCache = true; 33 | expected.NoCacheHeaders.Add("t"); 34 | CheckValidParsedValue("max-stale, no-cache=\"t\", ,,", 0, expected, 27); 35 | } 36 | 37 | [Fact] 38 | public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() 39 | { 40 | CheckInvalidParsedValue("no-cache,=", 0); 41 | CheckInvalidParsedValue("max-age=123x", 0); 42 | CheckInvalidParsedValue("=no-cache", 0); 43 | CheckInvalidParsedValue("no-cache no-store", 0); 44 | CheckInvalidParsedValue("invalid =", 0); 45 | CheckInvalidParsedValue("\u4F1A", 0); 46 | } 47 | 48 | #region Helper methods 49 | 50 | private void CheckValidParsedValue(string input, int startIndex, CacheControlHeaderValue expectedResult, 51 | int expectedIndex) 52 | { 53 | HttpHeaderParser parser = CacheControlHeaderParser.Parser; 54 | object result = null; 55 | Assert.True(parser.TryParseValue(input, null, ref startIndex, out result)); 56 | Assert.Equal(expectedIndex, startIndex); 57 | Assert.Equal(result, expectedResult); 58 | } 59 | 60 | private void CheckInvalidParsedValue(string input, int startIndex) 61 | { 62 | HttpHeaderParser parser = CacheControlHeaderParser.Parser; 63 | object result = null; 64 | int newIndex = startIndex; 65 | Assert.False(parser.TryParseValue(input, null, ref newIndex, out result)); 66 | Assert.Equal(null, result); 67 | Assert.Equal(startIndex, newIndex); 68 | } 69 | #endregion 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/UnitTests/Headers/DateHeaderParserTest.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Net.Http.Headers; 9 | using System.Text; 10 | 11 | using Xunit; 12 | 13 | namespace System.Net.Http.Tests 14 | { 15 | public class DateHeaderParserTest 16 | { 17 | [Fact] 18 | public void Properties_ReadValues_MatchExpectation() 19 | { 20 | DateHeaderParser parser = DateHeaderParser.Parser; 21 | Assert.False(parser.SupportsMultipleValues); 22 | Assert.Null(parser.Comparer); 23 | } 24 | 25 | [Fact] 26 | public void TryParse_SetOfValidValueStrings_ParsedCorrectly() 27 | { 28 | // We don't need to validate all possible date values, since they're already tested in HttpRuleParserTest. 29 | // Just make sure the parser calls HttpRuleParser methods correctly. 30 | CheckValidParsedValue("Tue, 15 Nov 1994 08:12:31 GMT", 0, 31 | new DateTimeOffset(1994, 11, 15, 8, 12, 31, TimeSpan.Zero), 29); 32 | CheckValidParsedValue("!! Sunday, 06-Nov-94 08:49:37 GMT ", 2, 33 | new DateTimeOffset(1994, 11, 6, 8, 49, 37, TimeSpan.Zero), 41); 34 | CheckValidParsedValue("\r\n Tue,\r\n 15 Nov\r\n 1994 08:12:31 GMT ", 2, 35 | new DateTimeOffset(1994, 11, 15, 8, 12, 31, TimeSpan.Zero), 39); 36 | } 37 | 38 | [Fact] 39 | public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() 40 | { 41 | CheckInvalidParsedValue(null, 0); 42 | CheckInvalidParsedValue(string.Empty, 0); 43 | CheckInvalidParsedValue(" ", 2); 44 | CheckInvalidParsedValue("!!Sunday, 06-Nov-94 08:49:37 GMT", 0); 45 | } 46 | 47 | [Fact] 48 | public void ToString_UseDifferentValues_MatchExpectation() 49 | { 50 | DateHeaderParser parser = DateHeaderParser.Parser; 51 | 52 | Assert.Equal("Sat, 31 Jul 2010 15:38:57 GMT", 53 | parser.ToString(new DateTimeOffset(2010, 7, 31, 15, 38, 57, TimeSpan.Zero))); 54 | 55 | Assert.Equal("Fri, 01 Jan 2010 01:01:01 GMT", 56 | parser.ToString(new DateTimeOffset(2010, 1, 1, 1, 1, 1, TimeSpan.Zero))); 57 | } 58 | 59 | #region Helper methods 60 | 61 | private void CheckValidParsedValue(string input, int startIndex, DateTimeOffset expectedResult, 62 | int expectedIndex) 63 | { 64 | DateHeaderParser parser = DateHeaderParser.Parser; 65 | object result = null; 66 | Assert.True(parser.TryParseValue(input, null, ref startIndex, out result)); 67 | Assert.Equal(expectedIndex, startIndex); 68 | Assert.Equal(expectedResult, result); 69 | } 70 | 71 | private void CheckInvalidParsedValue(string input, int startIndex) 72 | { 73 | DateHeaderParser parser = DateHeaderParser.Parser; 74 | object result = null; 75 | int newIndex = startIndex; 76 | Assert.False(parser.TryParseValue(input, null, ref newIndex, out result)); 77 | Assert.Equal(null, result); 78 | Assert.Equal(startIndex, newIndex); 79 | } 80 | #endregion 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/ContentRangeParserTest.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Net.Http.Headers; 9 | using System.Text; 10 | 11 | using Xunit; 12 | 13 | namespace System.Net.Http.Tests 14 | { 15 | public class ContentRangeParserTest 16 | { 17 | [Fact] 18 | public void Properties_ReadValues_MatchExpectation() 19 | { 20 | HttpHeaderParser parser = GenericHeaderParser.ContentRangeParser; 21 | Assert.False(parser.SupportsMultipleValues); 22 | Assert.Null(parser.Comparer); 23 | } 24 | 25 | [Fact] 26 | public void TryParse_SetOfValidValueStrings_ParsedCorrectly() 27 | { 28 | // Only verify parser functionality (i.e. ContentRangeHeaderParser.TryParse()). We don't need to validate 29 | // all possible range values (verification done by tests for ContentRangeHeaderValue.GetContentRangeLength()). 30 | CheckValidParsedValue("X bytes 1-2/3 ", 1, new ContentRangeHeaderValue(1, 2, 3), 14); 31 | CheckValidParsedValue("bytes * / 3", 0, new ContentRangeHeaderValue(3), 14); 32 | } 33 | 34 | [Fact] 35 | public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() 36 | { 37 | CheckInvalidParsedValue("bytes 1-2/3,", 0); // no character after 'length' allowed 38 | CheckInvalidParsedValue("x bytes 1-2/3", 0); 39 | CheckInvalidParsedValue("bytes 1-2/3.4", 0); 40 | CheckInvalidParsedValue(null, 0); 41 | CheckInvalidParsedValue(string.Empty, 0); 42 | } 43 | 44 | #region Helper methods 45 | 46 | private void CheckValidParsedValue(string input, int startIndex, ContentRangeHeaderValue expectedResult, 47 | int expectedIndex) 48 | { 49 | HttpHeaderParser parser = GenericHeaderParser.ContentRangeParser; 50 | object result = null; 51 | Assert.True(parser.TryParseValue(input, null, ref startIndex, out result), 52 | string.Format("TryParse returned false. Input: '{0}'", input)); 53 | Assert.Equal(expectedIndex, startIndex); 54 | Assert.Equal(expectedResult, result); 55 | } 56 | 57 | private void CheckInvalidParsedValue(string input, int startIndex) 58 | { 59 | HttpHeaderParser parser = GenericHeaderParser.ContentRangeParser; 60 | object result = null; 61 | int newIndex = startIndex; 62 | Assert.False(parser.TryParseValue(input, null, ref newIndex, out result), 63 | string.Format("TryParse returned true. Input: '{0}'", input)); 64 | Assert.Equal(null, result); 65 | Assert.Equal(startIndex, newIndex); 66 | } 67 | #endregion 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/MailAddressParserTest.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Net.Mail; 9 | using System.Net.Http.Headers; 10 | using System.Text; 11 | 12 | using Xunit; 13 | 14 | namespace System.Net.Http.Tests 15 | { 16 | public class MailAddressParserTest 17 | { 18 | [Fact] 19 | public void Properties_ReadValues_MatchExpectation() 20 | { 21 | HttpHeaderParser parser = GenericHeaderParser.MailAddressParser; 22 | Assert.False(parser.SupportsMultipleValues); 23 | Assert.Null(parser.Comparer); 24 | } 25 | 26 | [Fact] 27 | public void TryParse_SetOfValidValueStrings_ParsedCorrectly() 28 | { 29 | // We don't need to validate all possible date values, since they're already tested MailAddress. 30 | // Just make sure the parser calls MailAddressParser with correct parameters (like startIndex must be 31 | // honored). 32 | 33 | // Note that we still have trailing whitespace since we don't do the parsing of the email address. 34 | CheckValidParsedValue("!! info@example.com ", 2, "info@example.com ", 27); 35 | CheckValidParsedValue("\r\n \"My name\" info@example.com", 0, 36 | "\"My name\" info@example.com", 29); 37 | } 38 | 39 | [Fact] 40 | public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() 41 | { 42 | CheckInvalidParsedValue("[info@example.com", 0); 43 | CheckInvalidParsedValue("info@example.com\r\nother", 0); 44 | CheckInvalidParsedValue("info@example.com\r\n other", 0); 45 | CheckInvalidParsedValue("info@example.com\r\n", 0); 46 | CheckInvalidParsedValue("info@example.com,", 0); 47 | CheckInvalidParsedValue("\r\ninfo@example.com", 0); 48 | CheckInvalidParsedValue(null, 0); 49 | CheckInvalidParsedValue(string.Empty, 0); 50 | CheckInvalidParsedValue(" ", 2); 51 | } 52 | 53 | #region Helper methods 54 | 55 | private void CheckValidParsedValue(string input, int startIndex, string expectedResult, 56 | int expectedIndex) 57 | { 58 | HttpHeaderParser parser = GenericHeaderParser.MailAddressParser; 59 | object result = null; 60 | Assert.True(parser.TryParseValue(input, null, ref startIndex, out result), 61 | string.Format("TryParse returned false: {0}", input)); 62 | Assert.Equal(expectedIndex, startIndex); 63 | Assert.Equal(expectedResult, result); 64 | } 65 | 66 | private void CheckInvalidParsedValue(string input, int startIndex) 67 | { 68 | HttpHeaderParser parser = GenericHeaderParser.MailAddressParser; 69 | object result = null; 70 | int newIndex = startIndex; 71 | Assert.False(parser.TryParseValue(input, null, ref newIndex, out result), 72 | string.Format("TryParse returned true: {0}", input)); 73 | Assert.Equal(null, result); 74 | Assert.Equal(startIndex, newIndex); 75 | } 76 | #endregion 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/NameValueParserTest.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Net.Http.Headers; 9 | using System.Text; 10 | 11 | using Xunit; 12 | 13 | namespace System.Net.Http.Tests 14 | { 15 | public class NameValueParserTest 16 | { 17 | [Fact] 18 | public void Properties_ReadValues_MatchExpectation() 19 | { 20 | HttpHeaderParser parser = GenericHeaderParser.MultipleValueNameValueParser; 21 | Assert.True(parser.SupportsMultipleValues); 22 | Assert.Null(parser.Comparer); 23 | 24 | parser = GenericHeaderParser.SingleValueNameValueParser; 25 | Assert.False(parser.SupportsMultipleValues); 26 | Assert.Null(parser.Comparer); 27 | } 28 | 29 | [Fact] 30 | public void TryParse_SetOfValidValueStrings_ParsedCorrectly() 31 | { 32 | CheckValidParsedValue("X , , name = value , ,next", 1, new NameValueHeaderValue("name", "value"), 24); 33 | CheckValidParsedValue("X name,", 1, new NameValueHeaderValue("name"), 7); 34 | CheckValidParsedValue(" ,name=\"value\"", 0, new NameValueHeaderValue("name", "\"value\""), 14); 35 | CheckValidParsedValue("name=value", 0, new NameValueHeaderValue("name", "value"), 10); 36 | 37 | CheckValidParsedValue(null, 0, null, 0); 38 | CheckValidParsedValue(string.Empty, 0, null, 0); 39 | CheckValidParsedValue(" ", 0, null, 2); 40 | CheckValidParsedValue(" ,,", 0, null, 4); 41 | } 42 | 43 | [Fact] 44 | public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() 45 | { 46 | CheckInvalidParsedValue("name[value", 0); 47 | CheckInvalidParsedValue("name=value=", 0); 48 | CheckInvalidParsedValue("name=会", 0); 49 | CheckInvalidParsedValue("name==value", 0); 50 | CheckInvalidParsedValue("=value", 0); 51 | CheckInvalidParsedValue("name value", 0); 52 | CheckInvalidParsedValue("name=,value", 0); 53 | CheckInvalidParsedValue("会", 0); 54 | } 55 | 56 | #region Helper methods 57 | 58 | private void CheckValidParsedValue(string input, int startIndex, NameValueHeaderValue expectedResult, 59 | int expectedIndex) 60 | { 61 | HttpHeaderParser parser = GenericHeaderParser.MultipleValueNameValueParser; 62 | object result = null; 63 | Assert.True(parser.TryParseValue(input, null, ref startIndex, out result), 64 | string.Format("TryParse returned false: {0}", input)); 65 | Assert.Equal(expectedIndex, startIndex); 66 | Assert.Equal(result, expectedResult); 67 | } 68 | 69 | private void CheckInvalidParsedValue(string input, int startIndex) 70 | { 71 | HttpHeaderParser parser = GenericHeaderParser.MultipleValueNameValueParser; 72 | object result = null; 73 | int newIndex = startIndex; 74 | Assert.False(parser.TryParseValue(input, null, ref newIndex, out result), 75 | string.Format("TryParse returned true: {0}", input)); 76 | Assert.Equal(null, result); 77 | Assert.Equal(startIndex, newIndex); 78 | } 79 | #endregion 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/ProductParserTest.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Net.Http.Headers; 9 | using System.Text; 10 | 11 | using Xunit; 12 | 13 | namespace System.Net.Http.Tests 14 | { 15 | public class ProductParserTest 16 | { 17 | [Fact] 18 | public void Properties_ReadValues_MatchExpectation() 19 | { 20 | HttpHeaderParser parser = GenericHeaderParser.MultipleValueProductParser; 21 | Assert.True(parser.SupportsMultipleValues); 22 | Assert.Null(parser.Comparer); 23 | 24 | parser = GenericHeaderParser.SingleValueProductParser; 25 | Assert.False(parser.SupportsMultipleValues); 26 | Assert.Null(parser.Comparer); 27 | } 28 | 29 | [Fact] 30 | public void TryParse_SetOfValidValueStrings_ParsedCorrectly() 31 | { 32 | CheckValidParsedValue("X y/1 ", 1, new ProductHeaderValue("y", "1"), 6); 33 | CheckValidParsedValue(", , custom / 1.0 ,,Y", 0, new ProductHeaderValue("custom", "1.0"), 19); 34 | CheckValidParsedValue(", , custom / 1.0 ,,", 0, new ProductHeaderValue("custom", "1.0"), 19); 35 | CheckValidParsedValue(", , custom / 1.0", 0, new ProductHeaderValue("custom", "1.0"), 16); 36 | 37 | CheckValidParsedValue(null, 0, null, 0); 38 | CheckValidParsedValue(string.Empty, 0, null, 0); 39 | CheckValidParsedValue(" ", 0, null, 2); 40 | CheckValidParsedValue(" ,,", 0, null, 4); 41 | } 42 | 43 | [Fact] 44 | public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() 45 | { 46 | CheckInvalidParsedValue("product/version=", 0); // only delimiter ',' allowed after last product 47 | CheckInvalidParsedValue("product otherproduct", 0); 48 | CheckInvalidParsedValue("product[", 0); 49 | CheckInvalidParsedValue("=", 0); 50 | } 51 | 52 | #region Helper methods 53 | 54 | private void CheckValidParsedValue(string input, int startIndex, ProductHeaderValue expectedResult, 55 | int expectedIndex) 56 | { 57 | HttpHeaderParser parser = GenericHeaderParser.MultipleValueProductParser; 58 | object result = null; 59 | Assert.True(parser.TryParseValue(input, null, ref startIndex, out result), 60 | string.Format("TryParse returned false. Input: '{0}'", input)); 61 | Assert.Equal(expectedIndex, startIndex); 62 | Assert.Equal(result, expectedResult); 63 | } 64 | 65 | private void CheckInvalidParsedValue(string input, int startIndex) 66 | { 67 | HttpHeaderParser parser = GenericHeaderParser.MultipleValueProductParser; 68 | object result = null; 69 | int newIndex = startIndex; 70 | Assert.False(parser.TryParseValue(input, null, ref newIndex, out result), 71 | string.Format("TryParse returned true. Input: '{0}'", input)); 72 | Assert.Equal(null, result); 73 | Assert.Equal(startIndex, newIndex); 74 | } 75 | #endregion 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/RangeConditionParserTest.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Net.Http.Headers; 9 | using System.Text; 10 | 11 | using Xunit; 12 | 13 | namespace System.Net.Http.Tests 14 | { 15 | public class RangeConditionParserTest 16 | { 17 | [Fact] 18 | public void Properties_ReadValues_MatchExpectation() 19 | { 20 | HttpHeaderParser parser = GenericHeaderParser.RangeConditionParser; 21 | Assert.False(parser.SupportsMultipleValues); 22 | Assert.Null(parser.Comparer); 23 | } 24 | 25 | [Fact] 26 | public void TryParse_SetOfValidValueStrings_ParsedCorrectly() 27 | { 28 | CheckValidParsedValue("X \"x\" ", 1, new RangeConditionHeaderValue("\"x\""), 7); 29 | CheckValidParsedValue(" Sun, 06 Nov 1994 08:49:37 GMT ", 0, 30 | new RangeConditionHeaderValue(new DateTimeOffset(1994, 11, 6, 8, 49, 37, TimeSpan.Zero)), 32); 31 | } 32 | 33 | [Fact] 34 | public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() 35 | { 36 | CheckInvalidParsedValue("\"x\" ,", 0); // no delimiter allowed 37 | CheckInvalidParsedValue("Sun, 06 Nov 1994 08:49:37 GMT ,", 0); // no delimiter allowed 38 | CheckInvalidParsedValue("\"x\" Sun, 06 Nov 1994 08:49:37 GMT", 0); 39 | CheckInvalidParsedValue("Sun, 06 Nov 1994 08:49:37 GMT \"x\"", 0); 40 | CheckInvalidParsedValue(null, 0); 41 | CheckInvalidParsedValue(string.Empty, 0); 42 | } 43 | 44 | #region Helper methods 45 | 46 | private void CheckValidParsedValue(string input, int startIndex, RangeConditionHeaderValue expectedResult, 47 | int expectedIndex) 48 | { 49 | HttpHeaderParser parser = GenericHeaderParser.RangeConditionParser; 50 | object result = null; 51 | Assert.True(parser.TryParseValue(input, null, ref startIndex, out result), 52 | string.Format("TryParse returned false. Input: '{0}'", input)); 53 | Assert.Equal(expectedIndex, startIndex); 54 | Assert.Equal(expectedResult, result); 55 | } 56 | 57 | private void CheckInvalidParsedValue(string input, int startIndex) 58 | { 59 | HttpHeaderParser parser = GenericHeaderParser.RangeConditionParser; 60 | object result = null; 61 | int newIndex = startIndex; 62 | Assert.False(parser.TryParseValue(input, null, ref newIndex, out result), 63 | string.Format("TryParse returned true. Input: '{0}'", input)); 64 | Assert.Equal(null, result); 65 | Assert.Equal(startIndex, newIndex); 66 | } 67 | #endregion 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/RangeParserTest.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Text; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Net.Http.Headers; 10 | 11 | using Xunit; 12 | 13 | namespace System.Net.Http.Tests 14 | { 15 | public class RangeParserTest 16 | { 17 | [Fact] 18 | public void Properties_ReadValues_MatchExpectation() 19 | { 20 | HttpHeaderParser parser = GenericHeaderParser.RangeParser; 21 | Assert.False(parser.SupportsMultipleValues); 22 | Assert.Null(parser.Comparer); 23 | } 24 | 25 | [Fact] 26 | public void TryParse_SetOfValidValueStrings_ParsedCorrectly() 27 | { 28 | CheckValidParsedValue("X bytes=1-2 ", 1, new RangeHeaderValue(1, 2), 12); 29 | 30 | RangeHeaderValue expected = new RangeHeaderValue(); 31 | expected.Unit = "custom"; 32 | expected.Ranges.Add(new RangeItemHeaderValue(null, 5)); 33 | expected.Ranges.Add(new RangeItemHeaderValue(1, 4)); 34 | CheckValidParsedValue("custom = - 5 , 1 - 4 ,,", 0, expected, 24); 35 | } 36 | 37 | [Fact] 38 | public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() 39 | { 40 | CheckInvalidParsedValue("bytes=1-2x", 0); // only delimiter ',' allowed after last range 41 | CheckInvalidParsedValue("x bytes=1-2", 0); 42 | CheckInvalidParsedValue("bytes=1-2.4", 0); 43 | CheckInvalidParsedValue(null, 0); 44 | CheckInvalidParsedValue(string.Empty, 0); 45 | } 46 | 47 | #region Helper methods 48 | 49 | private void CheckValidParsedValue(string input, int startIndex, RangeHeaderValue expectedResult, 50 | int expectedIndex) 51 | { 52 | HttpHeaderParser parser = GenericHeaderParser.RangeParser; 53 | object result = null; 54 | Assert.True(parser.TryParseValue(input, null, ref startIndex, out result), 55 | string.Format("TryParse returned false. Input: '{0}'", input)); 56 | Assert.Equal(expectedIndex, startIndex); 57 | Assert.Equal(expectedResult, result); 58 | } 59 | 60 | private void CheckInvalidParsedValue(string input, int startIndex) 61 | { 62 | HttpHeaderParser parser = GenericHeaderParser.RangeParser; 63 | object result = null; 64 | int newIndex = startIndex; 65 | Assert.False(parser.TryParseValue(input, null, ref newIndex, out result), 66 | string.Format("TryParse returned true. Input: '{0}'", input)); 67 | Assert.Equal(null, result); 68 | Assert.Equal(startIndex, newIndex); 69 | } 70 | #endregion 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/RetryConditionParserTest.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Net.Http.Headers; 9 | using System.Text; 10 | 11 | using Xunit; 12 | 13 | namespace System.Net.Http.Tests 14 | { 15 | public class RetryConditionParserTest 16 | { 17 | [Fact] 18 | public void Properties_ReadValues_MatchExpectation() 19 | { 20 | HttpHeaderParser parser = GenericHeaderParser.RetryConditionParser; 21 | Assert.False(parser.SupportsMultipleValues); 22 | Assert.Null(parser.Comparer); 23 | } 24 | 25 | [Fact] 26 | public void TryParse_SetOfValidValueStrings_ParsedCorrectly() 27 | { 28 | CheckValidParsedValue("X 123456789 ", 1, new RetryConditionHeaderValue(new TimeSpan(0, 0, 123456789)), 13); 29 | CheckValidParsedValue(" Sun, 06 Nov 1994 08:49:37 GMT ", 0, 30 | new RetryConditionHeaderValue(new DateTimeOffset(1994, 11, 6, 8, 49, 37, TimeSpan.Zero)), 32); 31 | } 32 | 33 | [Fact] 34 | public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() 35 | { 36 | CheckInvalidParsedValue("123 ,", 0); // no delimiter allowed 37 | CheckInvalidParsedValue("Sun, 06 Nov 1994 08:49:37 GMT ,", 0); // no delimiter allowed 38 | CheckInvalidParsedValue("123 Sun, 06 Nov 1994 08:49:37 GMT", 0); 39 | CheckInvalidParsedValue("Sun, 06 Nov 1994 08:49:37 GMT \"x\"", 0); 40 | CheckInvalidParsedValue(null, 0); 41 | CheckInvalidParsedValue(string.Empty, 0); 42 | } 43 | 44 | #region Helper methods 45 | 46 | private void CheckValidParsedValue(string input, int startIndex, RetryConditionHeaderValue expectedResult, 47 | int expectedIndex) 48 | { 49 | HttpHeaderParser parser = GenericHeaderParser.RetryConditionParser; 50 | object result = null; 51 | Assert.True(parser.TryParseValue(input, null, ref startIndex, out result), 52 | string.Format("TryParse returned false. Input: '{0}'", input)); 53 | Assert.Equal(expectedIndex, startIndex); 54 | Assert.Equal(expectedResult, result); 55 | } 56 | 57 | private void CheckInvalidParsedValue(string input, int startIndex) 58 | { 59 | HttpHeaderParser parser = GenericHeaderParser.RetryConditionParser; 60 | object result = null; 61 | int newIndex = startIndex; 62 | Assert.False(parser.TryParseValue(input, null, ref newIndex, out result), 63 | string.Format("TryParse returned true. Input: '{0}'", input)); 64 | Assert.Equal(null, result); 65 | Assert.Equal(startIndex, newIndex); 66 | } 67 | #endregion 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/UnitTests/Headers/GenericHeaderParserTest/TokenListParserTest.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Net.Http.Headers; 6 | 7 | using Xunit; 8 | 9 | namespace System.Net.Http.Tests 10 | { 11 | public class TokenListParserTest 12 | { 13 | [Fact] 14 | public void Properties_ReadValues_MatchExpectation() 15 | { 16 | HttpHeaderParser parser = GenericHeaderParser.TokenListParser; 17 | Assert.True(parser.SupportsMultipleValues); 18 | Assert.Equal(StringComparer.OrdinalIgnoreCase, parser.Comparer); 19 | } 20 | 21 | [Fact] 22 | public void TryParse_SetOfValidValueStrings_ParsedCorrectly() 23 | { 24 | CheckValidParsedValue("text", 0, "text", 4); 25 | CheckValidParsedValue("text,", 0, "text", 5); 26 | CheckValidParsedValue("\r\n text , next_text ", 0, "text", 10); 27 | CheckValidParsedValue(" text,next_text ", 2, "text", 7); 28 | CheckValidParsedValue(" ,, text, , ,next", 0, "text", 13); 29 | CheckValidParsedValue(" ,, text, , ,", 0, "text", 13); 30 | 31 | CheckValidParsedValue(null, 0, null, 0); 32 | CheckValidParsedValue(string.Empty, 0, null, 0); 33 | CheckValidParsedValue(" ", 0, null, 3); 34 | CheckValidParsedValue(" ,,", 0, null, 4); 35 | } 36 | 37 | [Fact] 38 | public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() 39 | { 40 | CheckInvalidParsedValue("teäxt", 0); 41 | CheckInvalidParsedValue("text会", 0); 42 | CheckInvalidParsedValue("会", 0); 43 | } 44 | 45 | #region Helper methods 46 | 47 | private void CheckValidParsedValue(string input, int startIndex, string expectedResult, int expectedIndex) 48 | { 49 | HttpHeaderParser parser = GenericHeaderParser.TokenListParser; 50 | object result = null; 51 | Assert.True(parser.TryParseValue(input, null, ref startIndex, out result), 52 | string.Format("TryParse returned false: {0}", input)); 53 | Assert.Equal(expectedIndex, startIndex); 54 | Assert.Equal(result, expectedResult); 55 | } 56 | 57 | private void CheckInvalidParsedValue(string input, int startIndex) 58 | { 59 | HttpHeaderParser parser = GenericHeaderParser.TokenListParser; 60 | object result = null; 61 | int newIndex = startIndex; 62 | Assert.False(parser.TryParseValue(input, null, ref newIndex, out result), 63 | string.Format("TryParse returned true: {0}", input)); 64 | Assert.Equal(null, result); 65 | Assert.Equal(startIndex, newIndex); 66 | } 67 | #endregion 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/UnitTests/Headers/ObjectCollectionTest.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Net.Http.Headers; 7 | 8 | using Xunit; 9 | 10 | namespace System.Net.Http.Tests 11 | { 12 | public class ObjectCollectionTest 13 | { 14 | [Fact] 15 | public void Ctor_ExecuteBothOverloads_MatchExpectation() 16 | { 17 | // Use default validator 18 | ObjectCollection c = new ObjectCollection(); 19 | 20 | c.Add("value1"); 21 | c.Insert(0, "value2"); 22 | 23 | Assert.Throws(() => { c.Add(null); }); 24 | Assert.Throws(() => { c[0] = null; }); 25 | 26 | Assert.Equal(2, c.Count); 27 | Assert.Equal("value2", c[0]); 28 | Assert.Equal("value1", c[1]); 29 | 30 | // Use custom validator 31 | c = new ObjectCollection(item => 32 | { 33 | if (item == null) 34 | { 35 | throw new InvalidOperationException("custom"); 36 | } 37 | }); 38 | 39 | c.Add("value1"); 40 | c[0] = "value2"; 41 | 42 | Assert.Throws(() => { c.Add(null); }); 43 | Assert.Throws(() => { c[0] = null; }); 44 | 45 | Assert.Equal(1, c.Count); 46 | Assert.Equal("value2", c[0]); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/UnitTests/Headers/UriHeaderParserTest.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Net.Http.Headers; 6 | 7 | using Xunit; 8 | 9 | namespace System.Net.Http.Tests 10 | { 11 | public class UriHeaderParserTest 12 | { 13 | [Fact] 14 | public void Properties_ReadValues_MatchExpectation() 15 | { 16 | UriHeaderParser parser = UriHeaderParser.RelativeOrAbsoluteUriParser; 17 | Assert.False(parser.SupportsMultipleValues); 18 | Assert.Null(parser.Comparer); 19 | } 20 | 21 | [Fact] 22 | public void TryParse_SetOfValidValueStrings_ParsedCorrectly() 23 | { 24 | // We don't need to validate all possible Uri values, since we use Uri.TryParse(). 25 | // Just make sure the parser calls Uri.TryParse() correctly. 26 | CheckValidParsedValue("/this/is/a/rel/uri", 0, new Uri("/this/is/a/rel/uri", UriKind.Relative), 18); 27 | CheckValidParsedValue("!! http://example.com/path,/ ", 2, new Uri("http://example.com/path,/"), 30); 28 | 29 | // Note that Uri.TryParse(.., UriKind.Relative) doesn't remove whitespace 30 | CheckValidParsedValue("!! /path/x,/ ", 2, new Uri(" /path/x,/ ", UriKind.Relative), 15); 31 | CheckValidParsedValue(" http://example.com/path/?query=value ", 2, new Uri("http://example.com/path/?query=value"), 41); 32 | CheckValidParsedValue(" http://example.com/path/?query=value \r\n ", 2, new Uri("http://example.com/path/?query=value"), 43); 33 | CheckValidParsedValue("http://idn-iis1.\u65E5\u672C\u56FD.microsoft.com/", 0, new Uri("http://idn-iis1.\u65E5\u672C\u56FD.microsoft.com/"), 34); 34 | CheckValidParsedValue("http://idn-iis1.\u00E6\u0097\u00A5\u00E6\u009C\u00AC\u00E5\u009B\u00BD.microsoft.com/", 0, new Uri("http://idn-iis1.\u65E5\u672C\u56FD.microsoft.com/"), 40); 35 | } 36 | 37 | [Fact] 38 | public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() 39 | { 40 | CheckInvalidParsedValue("http://example.com,", 0); 41 | 42 | CheckInvalidParsedValue(null, 0); 43 | CheckInvalidParsedValue(null, 0); 44 | CheckInvalidParsedValue(string.Empty, 0); 45 | CheckInvalidParsedValue(string.Empty, 0); 46 | CheckInvalidParsedValue(" ", 2); 47 | CheckInvalidParsedValue(" ", 2); 48 | } 49 | 50 | #region Helper methods 51 | 52 | private void CheckValidParsedValue(string input, int startIndex, Uri expectedResult, int expectedIndex) 53 | { 54 | UriHeaderParser parser = UriHeaderParser.RelativeOrAbsoluteUriParser; 55 | 56 | object result = null; 57 | Assert.True(parser.TryParseValue(input, null, ref startIndex, out result), 58 | string.Format("TryParse returned false: {0}", input)); 59 | Assert.Equal(expectedIndex, startIndex); 60 | Assert.Equal(expectedResult, result); 61 | } 62 | 63 | private void CheckInvalidParsedValue(string input, int startIndex) 64 | { 65 | UriHeaderParser parser = UriHeaderParser.RelativeOrAbsoluteUriParser; 66 | 67 | object result = null; 68 | int newIndex = startIndex; 69 | Assert.False(parser.TryParseValue(input, null, ref newIndex, out result), 70 | string.Format("TryParse returned true: {0}", input)); 71 | Assert.Equal(null, result); 72 | Assert.Equal(startIndex, newIndex); 73 | } 74 | #endregion 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/UnitTests/HttpContentTest.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.IO; 6 | using System.Reflection; 7 | using System.Threading.Tasks; 8 | using Xunit; 9 | 10 | namespace System.Net.Http.Tests 11 | { 12 | public class HttpContentTest 13 | { 14 | [Fact] 15 | public async Task Dispose_BufferContentThenDisposeContent_BufferedStreamGetsDisposed() 16 | { 17 | MockContent content = new MockContent(); 18 | await content.LoadIntoBufferAsync(); 19 | 20 | Type type = typeof(HttpContent); 21 | TypeInfo typeInfo = type.GetTypeInfo(); 22 | FieldInfo bufferedContentField = typeof(HttpContent).GetField("_bufferedContent", 23 | BindingFlags.Instance | BindingFlags.NonPublic); 24 | Assert.NotNull(bufferedContentField); 25 | 26 | MemoryStream bufferedContentStream = bufferedContentField.GetValue(content) as MemoryStream; 27 | Assert.NotNull(bufferedContentStream); 28 | 29 | content.Dispose(); 30 | 31 | // The following line will throw an ObjectDisposedException if the buffered-stream was correctly disposed. 32 | Assert.Throws(() => { string str = bufferedContentStream.Length.ToString(); }); 33 | } 34 | 35 | [Theory] 36 | [InlineData(1, 100, 99, 1)] 37 | [InlineData(1, 100, 50, 99)] 38 | [InlineData(1, 100, 98, 98)] 39 | [InlineData(1, 100, 99, 99)] 40 | [InlineData(1, 100, 99, 98)] 41 | [InlineData(3, 50, 100, 149)] 42 | [InlineData(3, 50, 149, 149)] 43 | public async Task LoadIntoBufferAsync_ContentLengthSmallerThanActualData_ActualDataLargerThanMaxSize_ThrowsException( 44 | int numberOfWrites, int sizeOfEachWrite, int reportedLength, int maxSize) 45 | { 46 | Assert.InRange(maxSize, 1, (numberOfWrites * sizeOfEachWrite) - 1); 47 | 48 | LieAboutLengthContent c = new LieAboutLengthContent(numberOfWrites, sizeOfEachWrite, reportedLength); 49 | Task t = c.LoadIntoBufferAsync(maxSize); 50 | await Assert.ThrowsAsync(() => t); 51 | } 52 | 53 | private sealed class LieAboutLengthContent : HttpContent 54 | { 55 | private readonly int _numberOfWrites, _sizeOfEachWrite, _reportedLength; 56 | 57 | public LieAboutLengthContent(int numberOfWrites, int sizeOfEachWrite, int reportedLength) 58 | { 59 | _numberOfWrites = numberOfWrites; 60 | _sizeOfEachWrite = sizeOfEachWrite; 61 | _reportedLength = reportedLength; 62 | } 63 | 64 | protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context) 65 | { 66 | byte[] bytes = new byte[_sizeOfEachWrite]; 67 | for (int i = 0; i < _numberOfWrites; i++) 68 | { 69 | await stream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); 70 | } 71 | } 72 | 73 | protected internal override bool TryComputeLength(out long length) 74 | { 75 | length = _reportedLength; 76 | return true; 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/UnitTests/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | ".NET Core xUnit Console": { 4 | "commandName": "Executable", 5 | "executablePath": "$(TestHostRootPath)dotnet.exe", 6 | "commandLineArgs": "$(RunArguments) -parallel none", 7 | "workingDirectory": "$(RunWorkingDirectory)" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/System.Net.Http/tests/UnitTests/SystemProxyInfoTest.cs: -------------------------------------------------------------------------------- 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 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using System.Net.Http; 7 | using Microsoft.DotNet.RemoteExecutor; 8 | using Xunit; 9 | 10 | namespace System.Net.Http.Tests 11 | { 12 | public class SystemProxyInfoTest 13 | { 14 | // This will clean specific environmental variables 15 | // to be sure they do not interfere with the test. 16 | private void CleanEnv() 17 | { 18 | var envVars = new List { "http_proxy", "HTTP_PROXY", 19 | "https_proxy", "HTTPS_PROXY", 20 | "all_proxy", "ALL_PROXY", 21 | "no_proxy", "NO_PROXY", 22 | "GATEWAY_INTERFACE" }; 23 | 24 | foreach (string v in envVars) 25 | { 26 | Environment.SetEnvironmentVariable(v, null); 27 | } 28 | } 29 | 30 | public SystemProxyInfoTest() 31 | { 32 | CleanEnv(); 33 | } 34 | 35 | [Fact] 36 | public void Ctor_NoEnvironmentVariables_NotHttpEnvironmentProxy() 37 | { 38 | RemoteExecutor.Invoke(() => 39 | { 40 | IWebProxy proxy = SystemProxyInfo.ConstructSystemProxy(); 41 | Assert.NotNull(proxy); 42 | 43 | HttpEnvironmentProxy envProxy = proxy as HttpEnvironmentProxy; 44 | Assert.Null(envProxy); 45 | 46 | return RemoteExecutor.SuccessExitCode; 47 | }).Dispose(); 48 | } 49 | 50 | [Fact] 51 | public void Ctor_ProxyEnvironmentVariableSet_IsHttpEnvironmentProxy() 52 | { 53 | var options = new RemoteInvokeOptions(); 54 | options.StartInfo.EnvironmentVariables.Add("http_proxy", "http://proxy.contoso.com"); 55 | RemoteExecutor.Invoke(() => 56 | { 57 | IWebProxy proxy = SystemProxyInfo.ConstructSystemProxy(); 58 | HttpEnvironmentProxy envProxy = proxy as HttpEnvironmentProxy; 59 | Assert.NotNull(envProxy); 60 | 61 | return RemoteExecutor.SuccessExitCode; 62 | }, options).Dispose(); 63 | } 64 | } 65 | } 66 | --------------------------------------------------------------------------------