117 lines
4.3 KiB
C#
117 lines
4.3 KiB
C#
// Copyright (c) .NET Foundation. All rights reserved.
|
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
|
|
using System;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.Extensions.Internal;
|
|
|
|
namespace Microsoft.Net.Http.Server
|
|
{
|
|
internal static class Utilities
|
|
{
|
|
// When tests projects are run in parallel, overlapping port ranges can cause a race condition when looking for free
|
|
// ports during dynamic port allocation. To avoid this, make sure the port range here is different from the range in
|
|
// Microsoft.AspNetCore.Server.WebListener.
|
|
private const int BasePort = 8001;
|
|
private const int MaxPort = 11000;
|
|
private static int NextPort = BasePort;
|
|
private static object PortLock = new object();
|
|
|
|
internal static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(15);
|
|
// Minimum support for Windows 7 is assumed.
|
|
internal static readonly bool IsWin8orLater;
|
|
|
|
static Utilities()
|
|
{
|
|
var win8Version = new Version(6, 2);
|
|
|
|
#if NET451
|
|
IsWin8orLater = (Environment.OSVersion.Version >= win8Version);
|
|
#else
|
|
IsWin8orLater = (new Version(RuntimeEnvironment.OperatingSystemVersion) >= win8Version);
|
|
#endif
|
|
}
|
|
|
|
internal static WebListener CreateHttpAuthServer(AuthenticationSchemes authScheme, bool allowAnonymos, out string baseAddress)
|
|
{
|
|
var listener = CreateHttpServer(out baseAddress);
|
|
listener.Settings.Authentication.Schemes = authScheme;
|
|
listener.Settings.Authentication.AllowAnonymous = allowAnonymos;
|
|
return listener;
|
|
}
|
|
|
|
internal static WebListener CreateHttpServer(out string baseAddress)
|
|
{
|
|
string root;
|
|
return CreateDynamicHttpServer(string.Empty, out root, out baseAddress);
|
|
}
|
|
|
|
internal static WebListener CreateHttpServerReturnRoot(string path, out string root)
|
|
{
|
|
string baseAddress;
|
|
return CreateDynamicHttpServer(path, out root, out baseAddress);
|
|
}
|
|
|
|
internal static WebListener CreateDynamicHttpServer(string basePath, out string root, out string baseAddress)
|
|
{
|
|
lock (PortLock)
|
|
{
|
|
while (NextPort < MaxPort)
|
|
{
|
|
var port = NextPort++;
|
|
var prefix = UrlPrefix.Create("http", "localhost", port, basePath);
|
|
root = prefix.Scheme + "://" + prefix.Host + ":" + prefix.Port;
|
|
baseAddress = prefix.ToString();
|
|
var listener = new WebListener();
|
|
listener.Settings.UrlPrefixes.Add(prefix);
|
|
try
|
|
{
|
|
listener.Start();
|
|
return listener;
|
|
}
|
|
catch (WebListenerException)
|
|
{
|
|
listener.Dispose();
|
|
}
|
|
}
|
|
NextPort = BasePort;
|
|
}
|
|
throw new Exception("Failed to locate a free port.");
|
|
}
|
|
|
|
internal static WebListener CreateHttpsServer()
|
|
{
|
|
return CreateServer("https", "localhost", 9090, string.Empty);
|
|
}
|
|
|
|
internal static WebListener CreateServer(string scheme, string host, int port, string path)
|
|
{
|
|
WebListener listener = new WebListener();
|
|
listener.Settings.UrlPrefixes.Add(UrlPrefix.Create(scheme, host, port, path));
|
|
listener.Start();
|
|
return listener;
|
|
}
|
|
|
|
/// <summary>
|
|
/// AcceptAsync extension with timeout. This extension should be used in all tests to prevent
|
|
/// unexpected hangs when a request does not arrive.
|
|
/// </summary>
|
|
internal static async Task<RequestContext> AcceptAsync(this WebListener server, TimeSpan timeout)
|
|
{
|
|
var acceptTask = server.AcceptAsync();
|
|
var completedTask = await Task.WhenAny(acceptTask, Task.Delay(timeout));
|
|
|
|
if (completedTask == acceptTask)
|
|
{
|
|
return await acceptTask;
|
|
}
|
|
else
|
|
{
|
|
server.Dispose();
|
|
throw new TimeoutException("AcceptAsync has timed out.");
|
|
}
|
|
}
|
|
}
|
|
}
|