Prototype IServerFactory

This commit is contained in:
Chris Ross 2014-02-20 13:42:04 -08:00
parent 2dac6756dc
commit ab7e4cb3c8
20 changed files with 312 additions and 529 deletions

View File

@ -170,7 +170,7 @@ namespace Microsoft.AspNet.Server.WebListener
} }
return _hash; return _hash;
} }
#if NET45
internal IPAddress GetIPAddress() internal IPAddress GetIPAddress()
{ {
if (Family == AddressFamily.InterNetworkV6) if (Family == AddressFamily.InterNetworkV6)
@ -200,7 +200,7 @@ namespace Microsoft.AspNet.Server.WebListener
Contract.Assert(Size >= IPv4AddressSize); Contract.Assert(Size >= IPv4AddressSize);
return new IPAddress(new byte[] { _buffer[4], _buffer[5], _buffer[6], _buffer[7] }); return new IPAddress(new byte[] { _buffer[4], _buffer[5], _buffer[6], _buffer[7] });
} }
#endif
public override string ToString() public override string ToString()
{ {
StringBuilder bytes = new StringBuilder(); StringBuilder bytes = new StringBuilder();

View File

@ -1,108 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="ServerFactory.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
// Copyright 2011-2012 Katana contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Server.WebListener
{
using AppFunc = Func<object, Task>;
using LoggerFactoryFunc = Func<string, Func<TraceEventType, int, object, Exception, Func<object, Exception, string>, bool>>;
/// <summary>
/// Implements the Katana setup pattern for this server.
/// </summary>
public static class OwinServerFactory
{
/// <summary>
/// Populates the server capabilities.
/// Also included is a configurable instance of the server.
/// </summary>
/// <param name="properties"></param>
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Disposed by caller")]
public static void Initialize(IDictionary<string, object> properties)
{
if (properties == null)
{
throw new ArgumentNullException("properties");
}
properties[Constants.VersionKey] = Constants.OwinVersion;
IDictionary<string, object> capabilities =
properties.Get<IDictionary<string, object>>(Constants.ServerCapabilitiesKey)
?? new Dictionary<string, object>();
properties[Constants.ServerCapabilitiesKey] = capabilities;
// SendFile
capabilities[Constants.SendFileVersionKey] = Constants.SendFileVersion;
IDictionary<string, object> sendfileSupport = new Dictionary<string, object>();
sendfileSupport[Constants.SendFileConcurrencyKey] = Constants.Overlapped;
capabilities[Constants.SendFileSupportKey] = sendfileSupport;
// Opaque
if (ComNetOS.IsWin8orLater)
{
capabilities[Constants.OpaqueVersionKey] = Constants.OpaqueVersion;
}
// Directly expose the server for advanced configuration.
properties[typeof(OwinWebListener).FullName] = new OwinWebListener();
}
/// <summary>
/// Creates a server and starts listening on the given addresses.
/// </summary>
/// <param name="app">The application entry point.</param>
/// <param name="properties">The configuration.</param>
/// <returns>The server. Invoke Dispose to shut down.</returns>
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "By design")]
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Disposed by caller")]
public static IDisposable Create(AppFunc app, IDictionary<string, object> properties)
{
if (app == null)
{
throw new ArgumentNullException("app");
}
if (properties == null)
{
throw new ArgumentNullException("properties");
}
var addresses = properties.Get<IList<IDictionary<string, object>>>("host.Addresses")
?? new List<IDictionary<string, object>>();
OwinWebListener server = properties.Get<OwinWebListener>(typeof(OwinWebListener).FullName)
?? new OwinWebListener();
var capabilities =
properties.Get<IDictionary<string, object>>(Constants.ServerCapabilitiesKey)
?? new Dictionary<string, object>();
var loggerFactory = properties.Get<LoggerFactoryFunc>(Constants.ServerLoggerFactoryKey);
server.Start(app, addresses, capabilities, loggerFactory);
return server;
}
}
}

View File

@ -1,115 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="NilEnvDictionary.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
// Copyright 2011-2012 Katana contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
namespace Microsoft.AspNet.Server.WebListener
{
internal class NilEnvDictionary : IDictionary<string, object>
{
private static readonly string[] EmptyKeys = new string[0];
private static readonly object[] EmptyValues = new object[0];
private static readonly IEnumerable<KeyValuePair<string, object>> EmptyKeyValuePairs = Enumerable.Empty<KeyValuePair<string, object>>();
public int Count
{
get { return 0; }
}
public bool IsReadOnly
{
get { return false; }
}
public ICollection<string> Keys
{
get { return EmptyKeys; }
}
public ICollection<object> Values
{
get { return EmptyValues; }
}
[SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations", Justification = "Not Implemented")]
public object this[string key]
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
{
return EmptyKeyValuePairs.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return EmptyKeyValuePairs.GetEnumerator();
}
public void Add(KeyValuePair<string, object> item)
{
throw new NotImplementedException();
}
public void Clear()
{
}
public bool Contains(KeyValuePair<string, object> item)
{
return false;
}
public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
{
}
public bool Remove(KeyValuePair<string, object> item)
{
return false;
}
public bool ContainsKey(string key)
{
return false;
}
public void Add(string key, object value)
{
throw new NotImplementedException();
}
public bool Remove(string key)
{
return false;
}
public bool TryGetValue(string key, out object value)
{
value = null;
return false;
}
}
}

View File

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Hosting.Server;
namespace Microsoft.AspNet.Server.WebListener
{
internal class ServerConfiguration : IServerConfiguration
{
internal ServerConfiguration()
{
Addresses = new List<IDictionary<string, object>>(1);
}
public IList<IDictionary<string, object>> Addresses
{
get;
internal set;
}
public object AdvancedConfiguration
{
get;
internal set;
}
}
}

View File

@ -0,0 +1,83 @@
// -----------------------------------------------------------------------
// <copyright file="ServerFactory.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
// Copyright 2011-2012 Katana contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNet.Hosting.Server;
namespace Microsoft.AspNet.Server.WebListener
{
using AppFunc = Func<object, Task>;
using LoggerFactoryFunc = Func<string, Func<TraceEventType, int, object, Exception, Func<object, Exception, string>, bool>>;
/// <summary>
/// Implements the Katana setup pattern for this server.
/// </summary>
public class ServerFactory : IServerFactory
{
private LoggerFactoryFunc _loggerFactory;
public ServerFactory()
{
// TODO: Get services from DI, like logger factory.
}
/// <summary>
/// Populates the server capabilities.
/// Also included is a configurable instance of the server.
/// </summary>
/// <param name="properties"></param>
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Disposed by caller")]
public IServerConfiguration CreateConfiguration()
{
ServerConfiguration serverConfig = new ServerConfiguration();
serverConfig.AdvancedConfiguration = new OwinWebListener();
return serverConfig;
}
/// <summary>
/// Creates a server and starts listening on the given addresses.
/// </summary>
/// <param name="app">The application entry point.</param>
/// <param name="properties">The configuration.</param>
/// <returns>The server. Invoke Dispose to shut down.</returns>
public IDisposable Start(IServerConfiguration serverConfig, AppFunc app)
{
if (serverConfig == null)
{
throw new ArgumentNullException("serverConfig");
}
if (app == null)
{
throw new ArgumentNullException("app");
}
OwinWebListener server = (OwinWebListener)serverConfig.AdvancedConfiguration;
var capabilities = new Dictionary<string, object>();
server.Start(app, serverConfig.Addresses, capabilities, _loggerFactory);
return server;
}
}
}

View File

@ -0,0 +1,10 @@
using System;
namespace Microsoft.Net.Runtime
{
[AssemblyNeutralAttribute]
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
public sealed class AssemblyNeutralAttribute : Attribute
{
}
}

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Net.Runtime;
namespace Microsoft.AspNet.Hosting.Server
{
[AssemblyNeutral]
public interface IServerConfiguration
{
IList<IDictionary<string, object>> Addresses { get; }
object AdvancedConfiguration { get; }
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Threading.Tasks;
using Microsoft.Net.Runtime;
namespace Microsoft.AspNet.Hosting.Server
{
[AssemblyNeutral]
public interface IServerFactory
{
IServerConfiguration CreateConfiguration();
IDisposable Start(IServerConfiguration serverConfig, Func<object, Task> app);
}
}

View File

@ -14,7 +14,7 @@ using Microsoft.AspNet.PipelineCore;
using Xunit; using Xunit;
using Xunit.Extensions; using Xunit.Extensions;
namespace Microsoft.AspNet.Server.WebListener.Tests namespace Microsoft.AspNet.Server.WebListener.Test
{ {
using AppFunc = Func<object, Task>; using AppFunc = Func<object, Task>;
@ -31,7 +31,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[InlineData(AuthenticationType.Kerberos | AuthenticationType.Negotiate | AuthenticationType.Ntlm | AuthenticationType.Digest | AuthenticationType.Basic)] [InlineData(AuthenticationType.Kerberos | AuthenticationType.Negotiate | AuthenticationType.Ntlm | AuthenticationType.Digest | AuthenticationType.Basic)]
public async Task AuthTypes_EnabledButNotChalleneged_PassThrough(AuthenticationType authType) public async Task AuthTypes_EnabledButNotChalleneged_PassThrough(AuthenticationType authType)
{ {
using (CreateServer(authType, env => using (Utilities.CreateAuthServer(authType, env =>
{ {
return Task.FromResult(0); return Task.FromResult(0);
})) }))
@ -49,7 +49,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[InlineData(AuthenticationType.Basic)] [InlineData(AuthenticationType.Basic)]
public async Task AuthType_Specify401_ChallengesAdded(AuthenticationType authType) public async Task AuthType_Specify401_ChallengesAdded(AuthenticationType authType)
{ {
using (CreateServer(authType, env => using (Utilities.CreateAuthServer(authType, env =>
{ {
new DefaultHttpContext((IFeatureCollection)env).Response.StatusCode = 401; new DefaultHttpContext((IFeatureCollection)env).Response.StatusCode = 401;
return Task.FromResult(0); return Task.FromResult(0);
@ -64,8 +64,13 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task MultipleAuthTypes_Specify401_ChallengesAdded() public async Task MultipleAuthTypes_Specify401_ChallengesAdded()
{ {
// TODO: Not implemented - Digest using (Utilities.CreateAuthServer(
using (CreateServer(AuthenticationType.Kerberos | AuthenticationType.Negotiate | AuthenticationType.Ntlm | /*AuthenticationType.Digest |*/ AuthenticationType.Basic, env => AuthenticationType.Kerberos
| AuthenticationType.Negotiate
| AuthenticationType.Ntlm
/* | AuthenticationType.Digest TODO: Not implemented */
| AuthenticationType.Basic,
env =>
{ {
new DefaultHttpContext((IFeatureCollection)env).Response.StatusCode = 401; new DefaultHttpContext((IFeatureCollection)env).Response.StatusCode = 401;
return Task.FromResult(0); return Task.FromResult(0);
@ -87,7 +92,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
public async Task AuthTypes_Login_Success(AuthenticationType authType) public async Task AuthTypes_Login_Success(AuthenticationType authType)
{ {
int requestCount = 0; int requestCount = 0;
using (CreateServer(authType, env => using (Utilities.CreateAuthServer(authType, env =>
{ {
requestCount++; requestCount++;
/ * // TODO: Expose user as feature. / * // TODO: Expose user as feature.
@ -105,26 +110,6 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
} }
} }
*/ */
private IDisposable CreateServer(AuthenticationType authType, AppFunc app)
{
IDictionary<string, object> properties = new Dictionary<string, object>();
OwinServerFactory.Initialize(properties);
OwinWebListener listener = (OwinWebListener)properties[typeof(OwinWebListener).FullName];
listener.AuthenticationManager.AuthenticationTypes = authType;
IList<IDictionary<string, object>> addresses = new List<IDictionary<string, object>>();
properties["host.Addresses"] = addresses;
IDictionary<string, object> address = new Dictionary<string, object>();
addresses.Add(address);
address["scheme"] = "http";
address["host"] = "localhost";
address["port"] = "8080";
address["path"] = string.Empty;
return OwinServerFactory.Create(app, properties);
}
private async Task<HttpResponseMessage> SendRequestAsync(string uri, bool useDefaultCredentials = false) private async Task<HttpResponseMessage> SendRequestAsync(string uri, bool useDefaultCredentials = false)
{ {

View File

@ -1,31 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="DictionaryExtensions.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace System.Collections.Generic
{
internal static class DictionaryExtensions
{
internal static string Get(this IDictionary<string, string[]> dictionary, string key)
{
string[] values;
if (dictionary.TryGetValue(key, out values))
{
return string.Join(", ", values);
}
return null;
}
internal static T Get<T>(this IDictionary<string, object> dictionary, string key)
{
object values;
if (dictionary.TryGetValue(key, out values))
{
return (T)values;
}
return default(T);
}
}
}

View File

@ -16,7 +16,7 @@ using Microsoft.AspNet.HttpFeature;
using Microsoft.AspNet.PipelineCore; using Microsoft.AspNet.PipelineCore;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Server.WebListener.Tests namespace Microsoft.AspNet.Server.WebListener.Test
{ {
using AppFunc = Func<object, Task>; using AppFunc = Func<object, Task>;
@ -27,7 +27,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task Https_200OK_Success() public async Task Https_200OK_Success()
{ {
using (CreateServer(env => using (Utilities.CreateHttpsServer(env =>
{ {
return Task.FromResult(0); return Task.FromResult(0);
})) }))
@ -40,7 +40,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task Https_SendHelloWorld_Success() public async Task Https_SendHelloWorld_Success()
{ {
using (CreateServer(env => using (Utilities.CreateHttpsServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
byte[] body = Encoding.UTF8.GetBytes("Hello World"); byte[] body = Encoding.UTF8.GetBytes("Hello World");
@ -56,7 +56,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task Https_EchoHelloWorld_Success() public async Task Https_EchoHelloWorld_Success()
{ {
using (CreateServer(env => using (Utilities.CreateHttpsServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
string input = new StreamReader(httpContext.Request.Body).ReadToEnd(); string input = new StreamReader(httpContext.Request.Body).ReadToEnd();
@ -75,7 +75,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task Https_ClientCertNotSent_ClientCertNotPresent() public async Task Https_ClientCertNotSent_ClientCertNotPresent()
{ {
using (CreateServer(async env => using (Utilities.CreateHttpsServer(async env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
var tls = httpContext.GetFeature<IHttpTransportLayerSecurity>(); var tls = httpContext.GetFeature<IHttpTransportLayerSecurity>();
@ -92,7 +92,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task Https_ClientCertRequested_ClientCertPresent() public async Task Https_ClientCertRequested_ClientCertPresent()
{ {
using (CreateServer(async env => using (Utilities.CreateHttpsServer(async env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
var tls = httpContext.GetFeature<IHttpTransportLayerSecurity>(); var tls = httpContext.GetFeature<IHttpTransportLayerSecurity>();
@ -108,23 +108,6 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
} }
} }
private IDisposable CreateServer(AppFunc app)
{
IDictionary<string, object> properties = new Dictionary<string, object>();
IList<IDictionary<string, object>> addresses = new List<IDictionary<string, object>>();
properties["host.Addresses"] = addresses;
IDictionary<string, object> address = new Dictionary<string, object>();
addresses.Add(address);
address["scheme"] = "https";
address["host"] = "localhost";
address["port"] = "9090";
address["path"] = string.Empty;
return OwinServerFactory.Create(app, properties);
}
private async Task<string> SendRequestAsync(string uri, private async Task<string> SendRequestAsync(string uri,
X509Certificate cert = null) X509Certificate cert = null)
{ {

View File

@ -15,7 +15,7 @@ using Microsoft.AspNet.FeatureModel;
using Microsoft.AspNet.PipelineCore; using Microsoft.AspNet.PipelineCore;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Server.WebListener.Tests namespace Microsoft.AspNet.Server.WebListener.Test
{ {
using AppFunc = Func<object, Task>; using AppFunc = Func<object, Task>;
@ -26,7 +26,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task RequestBody_ReadSync_Success() public async Task RequestBody_ReadSync_Success()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
byte[] input = new byte[100]; byte[] input = new byte[100];
@ -44,7 +44,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task RequestBody_ReadAync_Success() public async Task RequestBody_ReadAync_Success()
{ {
using (CreateServer(async env => using (Utilities.CreateHttpServer(async env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
byte[] input = new byte[100]; byte[] input = new byte[100];
@ -61,7 +61,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task RequestBody_ReadBeginEnd_Success() public async Task RequestBody_ReadBeginEnd_Success()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
byte[] input = new byte[100]; byte[] input = new byte[100];
@ -80,7 +80,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
public async Task RequestBody_ReadSyncPartialBody_Success() public async Task RequestBody_ReadSyncPartialBody_Success()
{ {
StaggardContent content = new StaggardContent(); StaggardContent content = new StaggardContent();
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
byte[] input = new byte[10]; byte[] input = new byte[10];
@ -101,7 +101,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
public async Task RequestBody_ReadAsyncPartialBody_Success() public async Task RequestBody_ReadAsyncPartialBody_Success()
{ {
StaggardContent content = new StaggardContent(); StaggardContent content = new StaggardContent();
using (CreateServer(async env => using (Utilities.CreateHttpServer(async env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
byte[] input = new byte[10]; byte[] input = new byte[10];
@ -117,23 +117,6 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
} }
} }
private IDisposable CreateServer(AppFunc app)
{
IDictionary<string, object> properties = new Dictionary<string, object>();
IList<IDictionary<string, object>> addresses = new List<IDictionary<string, object>>();
properties["host.Addresses"] = addresses;
IDictionary<string, object> address = new Dictionary<string, object>();
addresses.Add(address);
address["scheme"] = "http";
address["host"] = "localhost";
address["port"] = "8080";
address["path"] = string.Empty;
return OwinServerFactory.Create(app, properties);
}
private Task<string> SendRequestAsync(string uri, string upload) private Task<string> SendRequestAsync(string uri, string upload)
{ {
return SendRequestAsync(uri, new StringContent(upload)); return SendRequestAsync(uri, new StringContent(upload));

View File

@ -14,7 +14,7 @@ using Microsoft.AspNet.FeatureModel;
using Microsoft.AspNet.PipelineCore; using Microsoft.AspNet.PipelineCore;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Server.WebListener.Tests namespace Microsoft.AspNet.Server.WebListener.Test
{ {
using AppFunc = Func<object, Task>; using AppFunc = Func<object, Task>;
@ -25,7 +25,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task RequestHeaders_ClientSendsDefaultHeaders_Success() public async Task RequestHeaders_ClientSendsDefaultHeaders_Success()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var requestHeaders = new DefaultHttpContext((IFeatureCollection)env).Request.Headers; var requestHeaders = new DefaultHttpContext((IFeatureCollection)env).Request.Headers;
// NOTE: The System.Net client only sends the Connection: keep-alive header on the first connection per service-point. // NOTE: The System.Net client only sends the Connection: keep-alive header on the first connection per service-point.
@ -44,7 +44,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task RequestHeaders_ClientSendsCustomHeaders_Success() public async Task RequestHeaders_ClientSendsCustomHeaders_Success()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var requestHeaders = new DefaultHttpContext((IFeatureCollection)env).Request.Headers; var requestHeaders = new DefaultHttpContext((IFeatureCollection)env).Request.Headers;
Assert.Equal(4, requestHeaders.Count); Assert.Equal(4, requestHeaders.Count);
@ -64,23 +64,6 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
} }
} }
private IDisposable CreateServer(AppFunc app)
{
IDictionary<string, object> properties = new Dictionary<string, object>();
IList<IDictionary<string, object>> addresses = new List<IDictionary<string, object>>();
properties["host.Addresses"] = addresses;
IDictionary<string, object> address = new Dictionary<string, object>();
addresses.Add(address);
address["scheme"] = "http";
address["host"] = "localhost";
address["port"] = "8080";
address["path"] = string.Empty;
return OwinServerFactory.Create(app, properties);
}
private async Task<string> SendRequestAsync(string uri) private async Task<string> SendRequestAsync(string uri)
{ {
using (HttpClient client = new HttpClient()) using (HttpClient client = new HttpClient())

View File

@ -12,12 +12,13 @@ using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.FeatureModel; using Microsoft.AspNet.FeatureModel;
using Microsoft.AspNet.Hosting.Server;
using Microsoft.AspNet.HttpFeature; using Microsoft.AspNet.HttpFeature;
using Microsoft.AspNet.PipelineCore; using Microsoft.AspNet.PipelineCore;
using Xunit; using Xunit;
using Xunit.Extensions; using Xunit.Extensions;
namespace Microsoft.AspNet.Server.WebListener.Tests namespace Microsoft.AspNet.Server.WebListener.Test
{ {
using AppFunc = Func<object, Task>; using AppFunc = Func<object, Task>;
@ -28,7 +29,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task Request_SimpleGet_Success() public async Task Request_SimpleGet_Success()
{ {
using (CreateServer(env => using (Utilities.CreateServer("http", "localhost", "8080", "/basepath", env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
try try
@ -66,7 +67,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
httpContext.Response.Body.Write(body, 0, body.Length); httpContext.Response.Body.Write(body, 0, body.Length);
} }
return Task.FromResult(0); return Task.FromResult(0);
}, "http", "localhost", "8080", "/basepath")) }))
{ {
string response = await SendRequestAsync(Address + "/basepath/SomePath?SomeQuery"); string response = await SendRequestAsync(Address + "/basepath/SomePath?SomeQuery");
Assert.Equal(string.Empty, response); Assert.Equal(string.Empty, response);
@ -74,16 +75,15 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
} }
[Theory] [Theory]
[InlineData("http", "localhost", "8080", "/", "http://localhost:8080/", "", "/")] [InlineData("/", "http://localhost:8080/", "", "/")]
[InlineData("http", "localhost", "8080", "/basepath/", "http://localhost:8080/basepath", "/basepath", "")] [InlineData("/basepath/", "http://localhost:8080/basepath", "/basepath", "")]
[InlineData("http", "localhost", "8080", "/basepath/", "http://localhost:8080/basepath/", "/basepath", "/")] [InlineData("/basepath/", "http://localhost:8080/basepath/", "/basepath", "/")]
[InlineData("http", "localhost", "8080", "/basepath/", "http://localhost:8080/basepath/subpath", "/basepath", "/subpath")] [InlineData("/basepath/", "http://localhost:8080/basepath/subpath", "/basepath", "/subpath")]
[InlineData("http", "localhost", "8080", "/base path/", "http://localhost:8080/base%20path/sub path", "/base path", "/sub path")] [InlineData("/base path/", "http://localhost:8080/base%20path/sub path", "/base path", "/sub path")]
[InlineData("http", "localhost", "8080", "/base葉path/", "http://localhost:8080/base%E8%91%89path/sub%E8%91%89path", "/base葉path", "/sub葉path")] [InlineData("/base葉path/", "http://localhost:8080/base%E8%91%89path/sub%E8%91%89path", "/base葉path", "/sub葉path")]
public async Task Request_PathSplitting(string scheme, string host, string port, string pathBase, string requestUri, public async Task Request_PathSplitting(string pathBase, string requestUri, string expectedPathBase, string expectedPath)
string expectedPathBase, string expectedPath)
{ {
using (CreateServer(env => using (Utilities.CreateServer("http", "localhost", "8080", pathBase, env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
try try
@ -92,11 +92,11 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
var connectionInfo = httpContext.GetFeature<IHttpConnection>(); var connectionInfo = httpContext.GetFeature<IHttpConnection>();
// Request Keys // Request Keys
Assert.Equal(scheme, requestInfo.Scheme); Assert.Equal("http", requestInfo.Scheme);
Assert.Equal(expectedPath, requestInfo.Path); Assert.Equal(expectedPath, requestInfo.Path);
Assert.Equal(expectedPathBase, requestInfo.PathBase); Assert.Equal(expectedPathBase, requestInfo.PathBase);
Assert.Equal(string.Empty, requestInfo.QueryString); Assert.Equal(string.Empty, requestInfo.QueryString);
Assert.Equal(port, connectionInfo.LocalPort.ToString()); Assert.Equal(8080, connectionInfo.LocalPort);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -104,7 +104,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
httpContext.Response.Body.Write(body, 0, body.Length); httpContext.Response.Body.Write(body, 0, body.Length);
} }
return Task.FromResult(0); return Task.FromResult(0);
}, scheme, host, port, pathBase)) }))
{ {
string response = await SendRequestAsync(requestUri); string response = await SendRequestAsync(requestUri);
Assert.Equal(string.Empty, response); Assert.Equal(string.Empty, response);
@ -148,41 +148,23 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
} }
} }
private IDisposable CreateServer(AppFunc app, string scheme, string host, string port, string path)
{
IDictionary<string, object> properties = new Dictionary<string, object>();
IList<IDictionary<string, object>> addresses = new List<IDictionary<string, object>>();
properties["host.Addresses"] = addresses;
IDictionary<string, object> address = new Dictionary<string, object>();
addresses.Add(address);
address["scheme"] = scheme;
address["host"] = host;
address["port"] = port;
address["path"] = path;
return OwinServerFactory.Create(app, properties);
}
private IDisposable CreateServer(AppFunc app) private IDisposable CreateServer(AppFunc app)
{ {
IDictionary<string, object> properties = new Dictionary<string, object>(); ServerFactory factory = new ServerFactory();
IList<IDictionary<string, object>> addresses = new List<IDictionary<string, object>>(); IServerConfiguration config = factory.CreateConfiguration();
properties["host.Addresses"] = addresses;
foreach (string path in new[] { "/", "/11", "/2/3", "/2", "/11/2" }) foreach (string path in new[] { "/", "/11", "/2/3", "/2", "/11/2" })
{ {
IDictionary<string, object> address = new Dictionary<string, object>(); IDictionary<string, object> address = new Dictionary<string, object>();
addresses.Add(address);
address["scheme"] = "http"; address["scheme"] = "http";
address["host"] = "localhost"; address["host"] = "localhost";
address["port"] = "8080"; address["port"] = "8080";
address["path"] = path; address["path"] = path;
config.Addresses.Add(address);
} }
return OwinServerFactory.Create(app, properties); return factory.Start(config, app);
} }
private async Task<string> SendRequestAsync(string uri) private async Task<string> SendRequestAsync(string uri)

View File

@ -16,7 +16,7 @@ using Microsoft.AspNet.HttpFeature;
using Microsoft.AspNet.PipelineCore; using Microsoft.AspNet.PipelineCore;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Server.WebListener.Tests namespace Microsoft.AspNet.Server.WebListener.Test
{ {
using AppFunc = Func<object, Task>; using AppFunc = Func<object, Task>;
@ -27,7 +27,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task ResponseBody_WriteNoHeaders_DefaultsToChunked() public async Task ResponseBody_WriteNoHeaders_DefaultsToChunked()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
httpContext.Response.Body.Write(new byte[10], 0, 10); httpContext.Response.Body.Write(new byte[10], 0, 10);
@ -47,7 +47,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task ResponseBody_WriteChunked_Chunked() public async Task ResponseBody_WriteChunked_Chunked()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
httpContext.Request.Headers["transfeR-Encoding"] = " CHunked "; httpContext.Request.Headers["transfeR-Encoding"] = " CHunked ";
@ -70,7 +70,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task ResponseBody_WriteContentLength_PassedThrough() public async Task ResponseBody_WriteContentLength_PassedThrough()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
httpContext.Response.Headers["Content-lenGth"] = " 30 "; httpContext.Response.Headers["Content-lenGth"] = " 30 ";
@ -94,7 +94,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task ResponseBody_Http10WriteNoHeaders_DefaultsConnectionClose() public async Task ResponseBody_Http10WriteNoHeaders_DefaultsConnectionClose()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
env["owin.ResponseProtocol"] = "HTTP/1.0"; env["owin.ResponseProtocol"] = "HTTP/1.0";
env.Get<Stream>("owin.ResponseBody").Write(new byte[10], 0, 10); env.Get<Stream>("owin.ResponseBody").Write(new byte[10], 0, 10);
@ -114,7 +114,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public void ResponseBody_WriteContentLengthNoneWritten_Throws() public void ResponseBody_WriteContentLengthNoneWritten_Throws()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
httpContext.Response.Headers["Content-lenGth"] = " 20 "; httpContext.Response.Headers["Content-lenGth"] = " 20 ";
@ -128,7 +128,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public void ResponseBody_WriteContentLengthNotEnoughWritten_Throws() public void ResponseBody_WriteContentLengthNotEnoughWritten_Throws()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
httpContext.Response.Headers["Content-lenGth"] = " 20 "; httpContext.Response.Headers["Content-lenGth"] = " 20 ";
@ -143,7 +143,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public void ResponseBody_WriteContentLengthTooMuchWritten_Throws() public void ResponseBody_WriteContentLengthTooMuchWritten_Throws()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
httpContext.Response.Headers["Content-lenGth"] = " 10 "; httpContext.Response.Headers["Content-lenGth"] = " 10 ";
@ -161,7 +161,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
{ {
ManualResetEvent waitHandle = new ManualResetEvent(false); ManualResetEvent waitHandle = new ManualResetEvent(false);
bool? appThrew = null; bool? appThrew = null;
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
try try
{ {
@ -195,23 +195,6 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
} }
} }
private IDisposable CreateServer(AppFunc app)
{
IDictionary<string, object> properties = new Dictionary<string, object>();
IList<IDictionary<string, object>> addresses = new List<IDictionary<string, object>>();
properties["host.Addresses"] = addresses;
IDictionary<string, object> address = new Dictionary<string, object>();
addresses.Add(address);
address["scheme"] = "http";
address["host"] = "localhost";
address["port"] = "8080";
address["path"] = string.Empty;
return OwinServerFactory.Create(app, properties);
}
private async Task<HttpResponseMessage> SendRequestAsync(string uri) private async Task<HttpResponseMessage> SendRequestAsync(string uri)
{ {
using (HttpClient client = new HttpClient()) using (HttpClient client = new HttpClient())

View File

@ -15,7 +15,7 @@ using Microsoft.AspNet.HttpFeature;
using Microsoft.AspNet.PipelineCore; using Microsoft.AspNet.PipelineCore;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Server.WebListener.Tests namespace Microsoft.AspNet.Server.WebListener.Test
{ {
using AppFunc = Func<object, Task>; using AppFunc = Func<object, Task>;
@ -26,7 +26,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task ResponseHeaders_ServerSendsDefaultHeaders_Success() public async Task ResponseHeaders_ServerSendsDefaultHeaders_Success()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
return Task.FromResult(0); return Task.FromResult(0);
})) }))
@ -45,7 +45,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task ResponseHeaders_ServerSendsCustomHeaders_Success() public async Task ResponseHeaders_ServerSendsCustomHeaders_Success()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
var responseInfo = httpContext.GetFeature<IHttpResponseInformation>(); var responseInfo = httpContext.GetFeature<IHttpResponseInformation>();
@ -69,7 +69,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task ResponseHeaders_ServerSendsConnectionClose_Closed() public async Task ResponseHeaders_ServerSendsConnectionClose_Closed()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
var responseInfo = httpContext.GetFeature<IHttpResponseInformation>(); var responseInfo = httpContext.GetFeature<IHttpResponseInformation>();
@ -88,7 +88,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task ResponseHeaders_SendsHttp10_Gets11Close() public async Task ResponseHeaders_SendsHttp10_Gets11Close()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
env["owin.ResponseProtocol"] = "HTTP/1.0"; env["owin.ResponseProtocol"] = "HTTP/1.0";
return Task.FromResult(0); return Task.FromResult(0);
@ -105,7 +105,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task ResponseHeaders_SendsHttp10WithBody_Gets11Close() public async Task ResponseHeaders_SendsHttp10WithBody_Gets11Close()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
env["owin.ResponseProtocol"] = "HTTP/1.0"; env["owin.ResponseProtocol"] = "HTTP/1.0";
return env.Get<Stream>("owin.ResponseBody").WriteAsync(new byte[10], 0, 10); return env.Get<Stream>("owin.ResponseBody").WriteAsync(new byte[10], 0, 10);
@ -125,7 +125,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task ResponseHeaders_HTTP10Request_Gets11Close() public async Task ResponseHeaders_HTTP10Request_Gets11Close()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
return Task.FromResult(0); return Task.FromResult(0);
})) }))
@ -146,7 +146,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task ResponseHeaders_HTTP10Request_RemovesChunkedHeader() public async Task ResponseHeaders_HTTP10Request_RemovesChunkedHeader()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
var responseInfo = httpContext.GetFeature<IHttpResponseInformation>(); var responseInfo = httpContext.GetFeature<IHttpResponseInformation>();
@ -173,7 +173,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task Headers_FlushSendsHeaders_Success() public async Task Headers_FlushSendsHeaders_Success()
{ {
using (CreateServer( using (Utilities.CreateHttpServer(
env => env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
@ -183,7 +183,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
responseHeaders.Add("Custom2", new string[] { "value2a, value2b" }); responseHeaders.Add("Custom2", new string[] { "value2a, value2b" });
var body = responseInfo.Body; var body = responseInfo.Body;
body.Flush(); body.Flush();
responseInfo.StatusCode = 404; // Ignored Assert.Throws<InvalidOperationException>(() => responseInfo.StatusCode = 404);
responseHeaders.Add("Custom3", new string[] { "value3a, value3b", "value3c" }); // Ignored responseHeaders.Add("Custom3", new string[] { "value3a, value3b", "value3c" }); // Ignored
return Task.FromResult(0); return Task.FromResult(0);
})) }))
@ -203,7 +203,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task Headers_FlushAsyncSendsHeaders_Success() public async Task Headers_FlushAsyncSendsHeaders_Success()
{ {
using (CreateServer( using (Utilities.CreateHttpServer(
async env => async env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
@ -213,7 +213,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
responseHeaders.Add("Custom2", new string[] { "value2a, value2b" }); responseHeaders.Add("Custom2", new string[] { "value2a, value2b" });
var body = responseInfo.Body; var body = responseInfo.Body;
await body.FlushAsync(); await body.FlushAsync();
responseInfo.StatusCode = 404; // Ignored Assert.Throws<InvalidOperationException>(() => responseInfo.StatusCode = 404);
responseHeaders.Add("Custom3", new string[] { "value3a, value3b", "value3c" }); // Ignored responseHeaders.Add("Custom3", new string[] { "value3a, value3b", "value3c" }); // Ignored
})) }))
{ {
@ -229,23 +229,6 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
} }
} }
private IDisposable CreateServer(AppFunc app)
{
IDictionary<string, object> properties = new Dictionary<string, object>();
IList<IDictionary<string, object>> addresses = new List<IDictionary<string, object>>();
properties["host.Addresses"] = addresses;
IDictionary<string, object> address = new Dictionary<string, object>();
addresses.Add(address);
address["scheme"] = "http";
address["host"] = "localhost";
address["port"] = "8080";
address["path"] = string.Empty;
return OwinServerFactory.Create(app, properties);
}
private async Task<HttpResponseMessage> SendRequestAsync(string uri) private async Task<HttpResponseMessage> SendRequestAsync(string uri)
{ {
using (HttpClient client = new HttpClient()) using (HttpClient client = new HttpClient())

View File

@ -18,7 +18,7 @@ using Microsoft.AspNet.HttpFeature;
using Microsoft.AspNet.PipelineCore; using Microsoft.AspNet.PipelineCore;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Server.WebListener.Tests namespace Microsoft.AspNet.Server.WebListener.Test
{ {
using AppFunc = Func<object, Task>; using AppFunc = Func<object, Task>;
@ -32,7 +32,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task ResponseSendFile_SupportKeys_Present() public async Task ResponseSendFile_SupportKeys_Present()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
try try
@ -75,7 +75,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
{ {
ManualResetEvent waitHandle = new ManualResetEvent(false); ManualResetEvent waitHandle = new ManualResetEvent(false);
bool? appThrew = null; bool? appThrew = null;
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
var sendFile = httpContext.GetFeature<IHttpSendFile>(); var sendFile = httpContext.GetFeature<IHttpSendFile>();
@ -107,7 +107,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task ResponseSendFile_NoHeaders_DefaultsToChunked() public async Task ResponseSendFile_NoHeaders_DefaultsToChunked()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
var sendFile = httpContext.GetFeature<IHttpSendFile>(); var sendFile = httpContext.GetFeature<IHttpSendFile>();
@ -126,7 +126,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task ResponseSendFile_RelativeFile_Success() public async Task ResponseSendFile_RelativeFile_Success()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
var sendFile = httpContext.GetFeature<IHttpSendFile>(); var sendFile = httpContext.GetFeature<IHttpSendFile>();
@ -145,7 +145,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task ResponseSendFile_Chunked_Chunked() public async Task ResponseSendFile_Chunked_Chunked()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
var sendFile = httpContext.GetFeature<IHttpSendFile>(); var sendFile = httpContext.GetFeature<IHttpSendFile>();
@ -165,7 +165,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task ResponseSendFile_MultipleChunks_Chunked() public async Task ResponseSendFile_MultipleChunks_Chunked()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
var sendFile = httpContext.GetFeature<IHttpSendFile>(); var sendFile = httpContext.GetFeature<IHttpSendFile>();
@ -186,7 +186,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task ResponseSendFile_ChunkedHalfOfFile_Chunked() public async Task ResponseSendFile_ChunkedHalfOfFile_Chunked()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
var sendFile = httpContext.GetFeature<IHttpSendFile>(); var sendFile = httpContext.GetFeature<IHttpSendFile>();
@ -205,7 +205,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task ResponseSendFile_ChunkedOffsetOutOfRange_Throws() public async Task ResponseSendFile_ChunkedOffsetOutOfRange_Throws()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
var sendFile = httpContext.GetFeature<IHttpSendFile>(); var sendFile = httpContext.GetFeature<IHttpSendFile>();
@ -220,7 +220,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task ResponseSendFile_ChunkedCountOutOfRange_Throws() public async Task ResponseSendFile_ChunkedCountOutOfRange_Throws()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
var sendFile = httpContext.GetFeature<IHttpSendFile>(); var sendFile = httpContext.GetFeature<IHttpSendFile>();
@ -235,7 +235,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task ResponseSendFile_ChunkedCount0_Chunked() public async Task ResponseSendFile_ChunkedCount0_Chunked()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
var sendFile = httpContext.GetFeature<IHttpSendFile>(); var sendFile = httpContext.GetFeature<IHttpSendFile>();
@ -254,7 +254,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task ResponseSendFile_ContentLength_PassedThrough() public async Task ResponseSendFile_ContentLength_PassedThrough()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
var sendFile = httpContext.GetFeature<IHttpSendFile>(); var sendFile = httpContext.GetFeature<IHttpSendFile>();
@ -275,7 +275,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task ResponseSendFile_ContentLengthSpecific_PassedThrough() public async Task ResponseSendFile_ContentLengthSpecific_PassedThrough()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
var sendFile = httpContext.GetFeature<IHttpSendFile>(); var sendFile = httpContext.GetFeature<IHttpSendFile>();
@ -296,7 +296,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task ResponseSendFile_ContentLength0_PassedThrough() public async Task ResponseSendFile_ContentLength0_PassedThrough()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
var sendFile = httpContext.GetFeature<IHttpSendFile>(); var sendFile = httpContext.GetFeature<IHttpSendFile>();
@ -314,25 +314,6 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
} }
} }
private IDisposable CreateServer(AppFunc app)
{
IList<IDictionary<string, object>> addresses = new List<IDictionary<string, object>>();
IDictionary<string, object> properties = new Dictionary<string, object>();
properties["host.Addresses"] = addresses;
IDictionary<string, object> address = new Dictionary<string, object>();
addresses.Add(address);
address["scheme"] = "http";
address["host"] = "localhost";
address["port"] = "8080";
address["path"] = string.Empty;
OwinServerFactory.Initialize(properties);
return OwinServerFactory.Create(app, properties);
}
private async Task<HttpResponseMessage> SendRequestAsync(string uri) private async Task<HttpResponseMessage> SendRequestAsync(string uri)
{ {
using (HttpClient client = new HttpClient()) using (HttpClient client = new HttpClient())

View File

@ -14,9 +14,10 @@ using Microsoft.AspNet.HttpFeature;
using Microsoft.AspNet.PipelineCore; using Microsoft.AspNet.PipelineCore;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Server.WebListener.Tests namespace Microsoft.AspNet.Server.WebListener.Test
{ {
using AppFunc = Func<object, Task>; using AppFunc = Func<object, Task>;
using Microsoft.AspNet.Hosting.Server;
public class ResponseTests public class ResponseTests
{ {
@ -25,7 +26,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task Response_ServerSendsDefaultResponse_ServerProvidesStatusCodeAndReasonPhrase() public async Task Response_ServerSendsDefaultResponse_ServerProvidesStatusCodeAndReasonPhrase()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
Assert.Equal(200, httpContext.Response.StatusCode); Assert.Equal(200, httpContext.Response.StatusCode);
@ -43,7 +44,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task Response_ServerSendsSpecificStatus_ServerProvidesReasonPhrase() public async Task Response_ServerSendsSpecificStatus_ServerProvidesReasonPhrase()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
httpContext.Response.StatusCode = 201; httpContext.Response.StatusCode = 201;
@ -62,7 +63,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task Response_ServerSendsSpecificStatusAndReasonPhrase_PassedThrough() public async Task Response_ServerSendsSpecificStatusAndReasonPhrase_PassedThrough()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
httpContext.Response.StatusCode = 201; httpContext.Response.StatusCode = 201;
@ -82,7 +83,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task Response_ServerSendsCustomStatus_NoReasonPhrase() public async Task Response_ServerSendsCustomStatus_NoReasonPhrase()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
httpContext.Response.StatusCode = 901; httpContext.Response.StatusCode = 901;
@ -99,7 +100,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task Response_100_Throws() public async Task Response_100_Throws()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
httpContext.Response.StatusCode = 100; httpContext.Response.StatusCode = 100;
@ -114,7 +115,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task Response_0_Throws() public async Task Response_0_Throws()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
httpContext.Response.StatusCode = 0; httpContext.Response.StatusCode = 0;
@ -126,23 +127,6 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
} }
} }
private IDisposable CreateServer(AppFunc app)
{
IDictionary<string, object> properties = new Dictionary<string, object>();
IList<IDictionary<string, object>> addresses = new List<IDictionary<string, object>>();
properties["host.Addresses"] = addresses;
IDictionary<string, object> address = new Dictionary<string, object>();
addresses.Add(address);
address["scheme"] = "http";
address["host"] = "localhost";
address["port"] = "8080";
address["path"] = string.Empty;
return OwinServerFactory.Create(app, properties);
}
private async Task<HttpResponseMessage> SendRequestAsync(string uri) private async Task<HttpResponseMessage> SendRequestAsync(string uri)
{ {
using (HttpClient client = new HttpClient()) using (HttpClient client = new HttpClient())

View File

@ -17,9 +17,10 @@ using Microsoft.AspNet.FeatureModel;
using Microsoft.AspNet.PipelineCore; using Microsoft.AspNet.PipelineCore;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Server.WebListener.Tests namespace Microsoft.AspNet.Server.WebListener.Test
{ {
using AppFunc = Func<object, Task>; using AppFunc = Func<object, Task>;
using Microsoft.AspNet.Hosting.Server;
public class ServerTests public class ServerTests
{ {
@ -28,7 +29,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task Server_200OK_Success() public async Task Server_200OK_Success()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
return Task.FromResult(0); return Task.FromResult(0);
})) }))
@ -41,7 +42,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task Server_SendHelloWorld_Success() public async Task Server_SendHelloWorld_Success()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
httpContext.Response.ContentLength = 11; httpContext.Response.ContentLength = 11;
@ -56,7 +57,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public async Task Server_EchoHelloWorld_Success() public async Task Server_EchoHelloWorld_Success()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
var httpContext = new DefaultHttpContext((IFeatureCollection)env); var httpContext = new DefaultHttpContext((IFeatureCollection)env);
string input = new StreamReader(httpContext.Request.Body).ReadToEnd(); string input = new StreamReader(httpContext.Request.Body).ReadToEnd();
@ -73,7 +74,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
[Fact] [Fact]
public void Server_AppException_ClientReset() public void Server_AppException_ClientReset()
{ {
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
throw new InvalidOperationException(); throw new InvalidOperationException();
})) }))
@ -94,7 +95,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
int requestCount = 0; int requestCount = 0;
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>(); TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
if (Interlocked.Increment(ref requestCount) == requestLimit) if (Interlocked.Increment(ref requestCount) == requestLimit)
{ {
@ -131,7 +132,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
int requestCount = 0; int requestCount = 0;
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>(); TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
using (CreateServer(async env => using (Utilities.CreateHttpServer(async env =>
{ {
if (Interlocked.Increment(ref requestCount) == requestLimit) if (Interlocked.Increment(ref requestCount) == requestLimit)
{ {
@ -161,7 +162,7 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
ManualResetEvent aborted = new ManualResetEvent(false); ManualResetEvent aborted = new ManualResetEvent(false);
ManualResetEvent canceled = new ManualResetEvent(false); ManualResetEvent canceled = new ManualResetEvent(false);
using (CreateServer(env => using (Utilities.CreateHttpServer(env =>
{ {
CancellationToken ct = env.Get<CancellationToken>("owin.CallCancelled"); CancellationToken ct = env.Get<CancellationToken>("owin.CallCancelled");
Assert.True(ct.CanBeCanceled, "CanBeCanceled"); Assert.True(ct.CanBeCanceled, "CanBeCanceled");
@ -185,39 +186,29 @@ namespace Microsoft.AspNet.Server.WebListener.Tests
Assert.True(canceled.WaitOne(interval), "canceled"); Assert.True(canceled.WaitOne(interval), "canceled");
} }
} }
*/
[Fact] [Fact]
public async Task Server_SetQueueLimit_Success() public async Task Server_SetQueueLimit_Success()
{ {
using (CreateServer(env =>
{
// There's no good way to validate this in code. Just execute it to make sure it doesn't crash.
// Run "netsh http show servicestate" to see the current value
var listener = env.Get<OwinWebListener>("Microsoft.AspNet.Server.WebListener.OwinWebListener");
listener.SetRequestQueueLimit(1001);
return Task.FromResult(0);
}))
{
string response = await SendRequestAsync(Address);
Assert.Equal(string.Empty, response);
}
}
*/
private IDisposable CreateServer(AppFunc app)
{
IDictionary<string, object> properties = new Dictionary<string, object>();
IList<IDictionary<string, object>> addresses = new List<IDictionary<string, object>>();
properties["host.Addresses"] = addresses;
IDictionary<string, object> address = new Dictionary<string, object>(); IDictionary<string, object> address = new Dictionary<string, object>();
addresses.Add(address);
address["scheme"] = "http"; address["scheme"] = "http";
address["host"] = "localhost"; address["host"] = "localhost";
address["port"] = "8080"; address["port"] = "8080";
address["path"] = string.Empty; address["path"] = string.Empty;
return OwinServerFactory.Create(app, properties); ServerFactory factory = new ServerFactory();
IServerConfiguration config = factory.CreateConfiguration();
config.Addresses.Add(address);
OwinWebListener listener = (OwinWebListener)config.AdvancedConfiguration;
listener.SetRequestQueueLimit(1001);
using (factory.Start(config, env => Task.FromResult(0)))
{
string response = await SendRequestAsync(Address);
Assert.Equal(string.Empty, response);
}
} }
private async Task<string> SendRequestAsync(string uri) private async Task<string> SendRequestAsync(string uri)

View File

@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNet.Hosting.Server;
namespace Microsoft.AspNet.Server.WebListener.Test
{
using AppFunc = Func<object, Task>;
internal static class Utilities
{
internal static IDisposable CreateHttpServer(AppFunc app)
{
return CreateServer("http", "localhost", "8080", string.Empty, app);
}
internal static IDisposable CreateHttpsServer(AppFunc app)
{
return CreateServer("https", "localhost", "9090", string.Empty, app);
}
internal static IDisposable CreateAuthServer(AuthenticationType authType, AppFunc app)
{
return CreateServer("http", "localhost", "8080", string.Empty, authType, app);
}
internal static IDisposable CreateServer(string scheme, string host, string port, string path, AppFunc app)
{
return CreateServer(scheme, host, port, path, AuthenticationType.None, app);
}
internal static IDisposable CreateServer(string scheme, string host, string port, string path, AuthenticationType authType, AppFunc app)
{
IDictionary<string, object> address = new Dictionary<string, object>();
address["scheme"] = scheme;
address["host"] = host;
address["port"] = port;
address["path"] = path;
ServerFactory factory = new ServerFactory();
IServerConfiguration config = factory.CreateConfiguration();
config.Addresses.Add(address);
OwinWebListener listener = (OwinWebListener)config.AdvancedConfiguration;
listener.AuthenticationManager.AuthenticationTypes = authType;
return factory.Start(config, app);
}
}
}