public void DefaultConfigSectionCanSetProtocols_MacAndWin7(string input, HttpProtocols expected) => DefaultConfigSectionCanSetProtocols(input, expected);
internal static void ConfigureAlpn(SslServerAuthenticationOptions serverOptions, HttpProtocols httpProtocols) { serverOptions.ApplicationProtocols = new List <SslApplicationProtocol>(); // This is order sensitive if ((httpProtocols & HttpProtocols.Http2) != 0) { serverOptions.ApplicationProtocols.Add(SslApplicationProtocol.Http2); // https://tools.ietf.org/html/rfc7540#section-9.2.1 serverOptions.AllowRenegotiation = false; } if ((httpProtocols & HttpProtocols.Http1) != 0) { serverOptions.ApplicationProtocols.Add(SslApplicationProtocol.Http11); } }
public abstract string GetUrl(HttpProtocols httpProtocol);
public static IMultiplexedConnectionBuilder UseHttp3Server <TContext>(this IMultiplexedConnectionBuilder builder, ServiceContext serviceContext, IHttpApplication <TContext> application, HttpProtocols protocols, bool addAltSvcHeader) where TContext : notnull { var middleware = new HttpMultiplexedConnectionMiddleware <TContext>(serviceContext, application, protocols, addAltSvcHeader); return(builder.Use(next => { return middleware.OnConnectionAsync; })); }
public HttpConnectionMiddleware(IList <IConnectionAdapter> adapters, ServiceContext serviceContext, IHttpApplication <TContext> application, HttpProtocols protocols) { _serviceContext = serviceContext; _application = application; _protocols = protocols; // Keeping these around for now so progress can be made without updating tests _connectionAdapters = adapters; }
public SniOptions(SslServerAuthenticationOptions sslOptions, HttpProtocols httpProtocols, ClientCertificateMode clientCertificateMode) { SslOptions = sslOptions; HttpProtocols = httpProtocols; ClientCertificateMode = clientCertificateMode; }
public static IConnectionBuilder UseHttpServer <TContext>(this IConnectionBuilder builder, ServiceContext serviceContext, IHttpApplication <TContext> application, HttpProtocols protocols) { var middleware = new HttpConnectionMiddleware <TContext>(serviceContext, application, protocols); return(builder.Use(next => { return middleware.OnConnectionAsync; })); }
public void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, RequestDelegate del, int port, HttpProtocols protocols) { _builder = new WebHostBuilder() .UseUrls(baseUrl) .UseKestrel() .ConfigureKestrel(serverOptions => { serverOptions.Listen(IPAddress.Loopback, port, listenOptions => { listenOptions.UseHttps("idsrv3test.pfx", "idsrv3test"); listenOptions.Protocols = protocols; }); }) .UseContentRoot(Directory.GetCurrentDirectory()) .UseIISIntegration() .Configure(app => { app.UsePathBase(basePath); app.Run(del); }) .Build(); _builder.Start(); }
public async Task UsesVersion(HttpProtocols protocols, bool tls, bool allowUnencryptedHttp2, string specified, string expectedVersion, string expectedResponse, bool failure = false) { // wheeee, macOS doesn't support ALPN so it can't do HTTP/2 over TLS // it also misbehaves when requesting HTTP/2 over non-TLS // so let's skip all those tests on macOS. Skip.If( RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && tls && (protocols == HttpProtocols.Http2 || protocols == HttpProtocols.Http1AndHttp2) && specified == "2.0", "HTTP/2 over TLS is not currently supported on MacOS" ); bool oldMode = HttpSettings.GlobalAllowUnencryptedHttp2; try { HttpSettings.GlobalAllowUnencryptedHttp2 = allowUnencryptedHttp2; var uri = _server.GetUri(protocols, tls); Log($"Server is on {uri}; specifying: '{specified}'"); var request = Http.Request(uri, new HttpSettings { ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator }); if (specified is object) { request = request.WithProtocolVersion(new Version(specified)); } HttpCallResponse <string> result; try { result = await request.ExpectString().GetAsync(); } catch (Exception ex) { if (failure) { Log(ex.ToString()); return; } else { throw; } } Log($"As sent: {result?.RawRequest?.Version}, received: {result?.RawResponse?.Version}"); if (failure) { Assert.NotNull(result.Error); Log(result.Error.ToString()); } else { Assert.Null(result.Error); Assert.Equal(expectedVersion, result.RawResponse?.Version?.ToString()); Assert.Equal(expectedResponse, result.Data); } } finally { HttpSettings.GlobalAllowUnencryptedHttp2 = oldMode; } }
public async Task PostExpect100_BodyNotUploadedIfFailed(HttpProtocols proxyProtocol, HttpProtocols destProtocol, bool useContentLength, int destResponseCode) { var headerTcs = new TaskCompletionSource <StringValues>(TaskCreationOptions.RunContinuationsAsynchronously); var bodyTcs = new TaskCompletionSource <string>(TaskCreationOptions.RunContinuationsAsynchronously); var contentString = new string('a', 1024 * 1024 * 10); var test = new TestEnvironment( async context => { if ((context.Request.Protocol == "HTTP/1.1" && destProtocol != HttpProtocols.Http1) || (context.Request.Protocol == "HTTP/2.0" && destProtocol != HttpProtocols.Http2)) { headerTcs.SetException(new Exception($"Unexpected request protocol {context.Request.Protocol}")); return; } else if (context.Request.Headers.TryGetValue(HeaderNames.Expect, out var expectHeader)) { headerTcs.SetResult(expectHeader); } else { headerTcs.SetException(new Exception("Missing 'Expect' header in request")); return; } if (destResponseCode == 200) { // 100 response code is sent automatically on reading Body. await ReadContent(context, bodyTcs, Encoding.UTF8.GetByteCount(contentString)); } context.Response.StatusCode = destResponseCode; }, proxyBuilder => { proxyBuilder.Services.AddSingleton <IForwarderHttpClientFactory, TestForwarderHttpClientFactory>(); }, proxyApp => { }, proxyProtocol: proxyProtocol, useHttpsOnDestination: true, useHttpsOnProxy: true, configTransformer: (c, r) => { c = c with { HttpRequest = new ForwarderRequestConfig { Version = destProtocol == HttpProtocols.Http2 ? HttpVersion.Version20 : HttpVersion.Version11, } }; return(c, r); }); await test.Invoke(async uri => { await ProcessHttpRequest(new Uri(uri), proxyProtocol, contentString, useContentLength, destResponseCode, false, destResponseCode == 200); Assert.True(headerTcs.Task.IsCompleted); var expectHeader = await headerTcs.Task; var expectValue = Assert.Single(expectHeader); Assert.Equal("100-continue", expectValue); if (destResponseCode == 200) { Assert.True(bodyTcs.Task.IsCompleted); var actualString = await bodyTcs.Task; Assert.Equal(contentString, actualString); } else { Assert.False(bodyTcs.Task.IsCompleted); } }); }
public static IConnectionBuilder UseHttpServer <TContext>(this IConnectionBuilder builder, ServiceContext serviceContext, IHttpApplication <TContext> application, HttpProtocols protocols) { return(builder.UseHttpServer(Array.Empty <IConnectionAdapter>(), serviceContext, application, protocols)); }
private async Task ProcessHttpRequest( Uri proxyHostUri, HttpProtocols protocol, string contentString, bool useContentLength, int expectedCode, bool cancelResponse, bool contentRead, Func <HttpResponseMessage, Task> responseAction = null) { using var handler = new SocketsHttpHandler() { Expect100ContinueTimeout = TimeSpan.FromSeconds(60) }; handler.UseProxy = false; handler.AllowAutoRedirect = false; handler.SslOptions.RemoteCertificateValidationCallback = delegate { return(true); }; using var client = new HttpClient(handler); using var message = new HttpRequestMessage(HttpMethod.Post, proxyHostUri); message.Version = protocol == HttpProtocols.Http2 ? HttpVersion.Version20 : HttpVersion.Version11; message.Headers.ExpectContinue = true; var content = Encoding.UTF8.GetBytes(contentString); using var contentStream = new MemoryStream(content); message.Content = new StreamContent(contentStream); if (useContentLength) { message.Content.Headers.ContentLength = content.Length; } else { message.Headers.TransferEncodingChunked = true; } if (!cancelResponse) { using var response = await client.SendAsync(message); Assert.Equal(expectedCode, (int)response.StatusCode); if (contentRead) { Assert.Equal(content.Length, contentStream.Position); } else { Assert.Equal(0, contentStream.Position); } if (responseAction is not null) { await responseAction(response); } } else { var exception = await Assert.ThrowsAsync <HttpRequestException>(() => client.SendAsync(message)); Assert.Equal(typeof(IOException), exception.InnerException.GetType()); Assert.Equal(content.Length, contentStream.Position); } }
public async Task PostExpect100_SkipRequestBodyWithUnsuccesfulResponseCode(HttpProtocols proxyProtocol, HttpProtocols destProtocol, bool useContentLength) { var requestBodyTcs = new TaskCompletionSource <string>(TaskCreationOptions.RunContinuationsAsynchronously); var contentString = new string('a', 1024 * 1024 * 10); var test = new TestEnvironment( async context => { context.Response.StatusCode = 400; var responseBody = Encoding.UTF8.GetBytes(contentString + "Response"); if (useContentLength) { context.Response.Headers.ContentLength = responseBody.Length; } await context.Response.Body.WriteAsync(responseBody.AsMemory()); }, proxyBuilder => { proxyBuilder.Services.AddSingleton <IForwarderHttpClientFactory, TestForwarderHttpClientFactory>(); }, proxyApp => { }, proxyProtocol: proxyProtocol, useHttpsOnDestination: true, useHttpsOnProxy: true, configTransformer: (c, r) => { c = c with { HttpRequest = new ForwarderRequestConfig { Version = destProtocol == HttpProtocols.Http2 ? HttpVersion.Version20 : HttpVersion.Version11, } }; return(c, r); }); await test.Invoke(async uri => { await ProcessHttpRequest(new Uri(uri), proxyProtocol, contentString, useContentLength, 400, cancelResponse: false, contentRead: false, async response => { Assert.Equal(400, (int)response.StatusCode); var actualResponse = await response.Content.ReadAsStringAsync(); Assert.Equal(contentString + "Response", actualResponse); }); }); }
public HttpConnectionMiddleware(ServiceContext serviceContext, IHttpApplication <TContext> application, HttpProtocols protocols) { _serviceContext = serviceContext; _application = application; _protocols = protocols; }
public void EndpointConfigSectionCanSetProtocols_NonMacAndWin7(string input, HttpProtocols expected) => EndpointConfigSectionCanSetProtocols(input, expected);
public HttpProtocolsFeature(HttpProtocols httpProtocols) { HttpProtocols = httpProtocols; }
public HttpMultiplexedConnectionMiddleware(ServiceContext serviceContext, IHttpApplication <TContext> application, HttpProtocols protocols, bool addAltSvcHeader) { _serviceContext = serviceContext; _application = application; _protocols = protocols; _addAltSvcHeader = addAltSvcHeader; }
private IHost BuildWebHost( IEnvelopeSerializer envelopeSerializer, X509Certificate2 tlsCertificate, int bufferSize, ITraceWriter traceWriter, HttpProtocols httpProtocols, SslProtocols sslProtocols, Func <X509Certificate2, X509Chain, SslPolicyErrors, bool> clientCertificateValidationCallback, TimeSpan?keepAliveInterval) { HttpConnectionDispatcherOptions httpConnectionDispatcherOptions = null; HubOptions hubOptions = null; return(Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseKestrel(serverOptions => { foreach (var listenerUri in ListenerUris) { if (!IPAddress.TryParse(listenerUri.Host, out var ipAddress)) { ipAddress = IPAddress.Any; } var endPoint = new IPEndPoint(ipAddress, listenerUri.Port); serverOptions.Listen(endPoint, listenOptions => { listenOptions.Protocols = httpProtocols; if (listenerUri.Scheme == Uri.UriSchemeHttps) { listenOptions.UseHttps(tlsCertificate, httpsOptions => { httpsOptions.SslProtocols = sslProtocols; httpsOptions.ClientCertificateValidation = clientCertificateValidationCallback; }); } }); } serverOptions.AddServerHeader = false; }) .SuppressStatusMessages(true) .ConfigureServices(services => { services .AddLogging() .AddSingleton(sp => _transportChannel) .AddSingleton(sp => httpConnectionDispatcherOptions) .AddSingleton(sp => hubOptions) .AddSingleton(envelopeSerializer) .AddSingleton(new EnvelopeHubOptions { BoundedCapacity = _backpressureLimit }) .AddSingleton(new ConcurrentDictionary <string, Channel <string> >()) .AddSignalR().AddHubOptions <EnvelopeHub>(options => { hubOptions = options; options.KeepAliveInterval = keepAliveInterval; }); if (traceWriter != null) { services.AddSingleton(traceWriter); } }) .Configure(app => { app.UseRouting().UseEndpoints(endpoints => { endpoints.MapHub <EnvelopeHub>("/envelope", options => { httpConnectionDispatcherOptions = options; options.TransportMaxBufferSize = bufferSize; }); }); }); }) .Build()); }
public SniOptionsSelector( string endpointName, Dictionary <string, SniConfig> sniDictionary, ICertificateConfigLoader certifcateConfigLoader, HttpsConnectionAdapterOptions fallbackHttpsOptions, HttpProtocols fallbackHttpProtocols, ILogger <HttpsConnectionMiddleware> logger) { _endpointName = endpointName; _fallbackServerCertificateSelector = fallbackHttpsOptions.ServerCertificateSelector; _onAuthenticateCallback = fallbackHttpsOptions.OnAuthenticate; foreach (var(name, sniConfig) in sniDictionary) { var sslOptions = new SslServerAuthenticationOptions { ServerCertificate = certifcateConfigLoader.LoadCertificate(sniConfig.Certificate, $"{endpointName}:Sni:{name}"), EnabledSslProtocols = sniConfig.SslProtocols ?? fallbackHttpsOptions.SslProtocols, CertificateRevocationCheckMode = fallbackHttpsOptions.CheckCertificateRevocation ? X509RevocationMode.Online : X509RevocationMode.NoCheck, }; if (sslOptions.ServerCertificate is null) { if (fallbackHttpsOptions.ServerCertificate is null && _fallbackServerCertificateSelector is null) { throw new InvalidOperationException(CoreStrings.NoCertSpecifiedNoDevelopmentCertificateFound); } if (_fallbackServerCertificateSelector is null) { // Cache the fallback ServerCertificate since there's no fallback ServerCertificateSelector taking precedence. sslOptions.ServerCertificate = fallbackHttpsOptions.ServerCertificate; } } if (sslOptions.ServerCertificate != null) { // This might be do blocking IO but it'll resolve the certificate chain up front before any connections are // made to the server sslOptions.ServerCertificateContext = SslStreamCertificateContext.Create((X509Certificate2)sslOptions.ServerCertificate, additionalCertificates: null); } if (!certifcateConfigLoader.IsTestMock && sslOptions.ServerCertificate is X509Certificate2 cert2) { HttpsConnectionMiddleware.EnsureCertificateIsAllowedForServerAuth(cert2); } var clientCertificateMode = sniConfig.ClientCertificateMode ?? fallbackHttpsOptions.ClientCertificateMode; if (clientCertificateMode != ClientCertificateMode.NoCertificate) { sslOptions.ClientCertificateRequired = clientCertificateMode == ClientCertificateMode.AllowCertificate || clientCertificateMode == ClientCertificateMode.RequireCertificate; sslOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => HttpsConnectionMiddleware.RemoteCertificateValidationCallback( clientCertificateMode, fallbackHttpsOptions.ClientCertificateValidation, certificate, chain, sslPolicyErrors); } var httpProtocols = sniConfig.Protocols ?? fallbackHttpProtocols; httpProtocols = HttpsConnectionMiddleware.ValidateAndNormalizeHttpProtocols(httpProtocols, logger); HttpsConnectionMiddleware.ConfigureAlpn(sslOptions, httpProtocols); var sniOptions = new SniOptions(sslOptions, httpProtocols, clientCertificateMode); if (name.Equals(WildcardHost, StringComparison.Ordinal)) { _wildcardOptions = sniOptions; } else if (name.StartsWith(WildcardPrefix, StringComparison.Ordinal)) { // Only slice off 1 character, the `*`. We want to match the leading `.` also. _wildcardPrefixOptions.Add(name.Substring(1), sniOptions); } else { _exactNameOptions.Add(name, sniOptions); } } }
public HttpConnectionMiddleware(ServiceContext serviceContext, IHttpApplication <TContext> application, HttpProtocols protocols, bool addAltSvcHeader) { _serviceContext = serviceContext; _application = application; _endpointDefaultProtocols = protocols; _addAltSvcHeader = addAltSvcHeader; }
public async Task EndpointDefaultsConfig_CanSetProtocolForUrlsConfig(string input, HttpProtocols expected) { KestrelServerOptions capturedOptions = null; var hostBuilder = TransportSelector.GetHostBuilder() .ConfigureWebHost(webHostBuilder => { webHostBuilder .UseKestrel(options => { var config = new ConfigurationBuilder().AddInMemoryCollection(new[] { new KeyValuePair <string, string>("EndpointDefaults:Protocols", input), }).Build(); options.Configure(config); capturedOptions = options; }) .UseUrls("http://127.0.0.1:0") .Configure(ConfigureEchoAddress); }) .ConfigureServices(AddTestLogging); using (var host = hostBuilder.Build()) { await host.StartAsync(); Assert.Single(capturedOptions.OptionsInUse); Assert.Equal(expected, capturedOptions.OptionsInUse[0].Protocols); await host.StopAsync(); } }
private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, int port, HttpProtocols protocols) { _serviceHandler.GivenThereIsAServiceRunningOn(baseUrl, basePath, async context => { context.Response.StatusCode = 200; var reader = new StreamReader(context.Request.Body); var body = await reader.ReadToEndAsync(); await context.Response.WriteAsync(body); }, port, protocols); }