Exclude the upgrade feature if the OS does not support it #427

This commit is contained in:
Chris Ross (ASP.NET) 2018-03-06 20:25:51 -08:00
parent 336e85d19a
commit dbd557c965
3 changed files with 136 additions and 1 deletions

View File

@ -22,7 +22,6 @@ namespace Microsoft.AspNetCore.Server.HttpSys
// { typeof(ITlsTokenBindingFeature), ctx => ctx.GetTlsTokenBindingFeature() }, TODO: https://github.com/aspnet/HttpSysServer/issues/231
{ typeof(IHttpBufferingFeature), _identityFunc },
{ typeof(IHttpRequestLifetimeFeature), _identityFunc },
{ typeof(IHttpUpgradeFeature), _identityFunc },
{ typeof(IHttpAuthenticationFeature), _identityFunc },
{ typeof(IHttpRequestIdentifierFeature), _identityFunc },
{ typeof(RequestContext), ctx => ctx.RequestContext },
@ -32,6 +31,17 @@ namespace Microsoft.AspNetCore.Server.HttpSys
private readonly FeatureContext _featureContext;
static StandardFeatureCollection()
{
if (ComNetOS.IsWin8orLater)
{
// Only add the upgrade feature if it stands a chance of working.
// SignalR uses the presence of the feature to detect feature support.
// https://github.com/aspnet/HttpSysServer/issues/427
_featureFuncLookup[typeof(IHttpUpgradeFeature)] = _identityFunc;
}
}
public StandardFeatureCollection(FeatureContext featureContext)
{
_featureContext = featureContext;

View File

@ -0,0 +1,99 @@
// 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.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
namespace Microsoft.AspNetCore.Testing.xunit
{
// Skip except on a specific OS and version
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly, AllowMultiple = true)]
public class OSDontSkipConditionAttribute : Attribute, ITestCondition
{
private readonly OperatingSystems _includedOperatingSystem;
private readonly IEnumerable<string> _includedVersions;
private readonly OperatingSystems _osPlatform;
private readonly string _osVersion;
public OSDontSkipConditionAttribute(OperatingSystems operatingSystem, params string[] versions) :
this(
operatingSystem,
GetCurrentOS(),
GetCurrentOSVersion(),
versions)
{
}
// to enable unit testing
internal OSDontSkipConditionAttribute(
OperatingSystems operatingSystem, OperatingSystems osPlatform, string osVersion, params string[] versions)
{
_includedOperatingSystem = operatingSystem;
_includedVersions = versions ?? Enumerable.Empty<string>();
_osPlatform = osPlatform;
_osVersion = osVersion;
}
public bool IsMet
{
get
{
var currentOSInfo = new OSInfo()
{
OperatingSystem = _osPlatform,
Version = _osVersion,
};
var skip = (_includedOperatingSystem & currentOSInfo.OperatingSystem) != currentOSInfo.OperatingSystem;
if (!skip && _includedVersions.Any())
{
skip = !_includedVersions.Any(inc => _osVersion.StartsWith(inc, StringComparison.OrdinalIgnoreCase));
}
// Since a test would be excuted only if 'IsMet' is true, return false if we want to skip
return !skip;
}
}
public string SkipReason { get; set; } = "Test cannot run on this operating system.";
static private OperatingSystems GetCurrentOS()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return OperatingSystems.Windows;
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return OperatingSystems.Linux;
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
return OperatingSystems.MacOSX;
}
throw new PlatformNotSupportedException();
}
static private string GetCurrentOSVersion()
{
// currently not used on other OS's
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return Environment.OSVersion.Version.ToString();
}
else
{
return string.Empty;
}
}
private class OSInfo
{
public OperatingSystems OperatingSystem { get; set; }
public string Version { get; set; }
}
}
}

View File

@ -17,6 +17,32 @@ namespace Microsoft.AspNetCore.Server.HttpSys
{
public class OpaqueUpgradeTests
{
[ConditionalFact]
[OSDontSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, WindowsVersions.Win2008R2)]
public async Task OpaqueUpgrade_DownLevel_FeatureIsAbsent()
{
using (Utilities.CreateHttpServer(out var address, httpContext =>
{
try
{
var opaqueFeature = httpContext.Features.Get<IHttpUpgradeFeature>();
Assert.Null(opaqueFeature);
}
catch (Exception ex)
{
return httpContext.Response.WriteAsync(ex.ToString());
}
return Task.FromResult(0);
}))
{
HttpResponseMessage response = await SendRequestAsync(address);
Assert.Equal(200, (int)response.StatusCode);
Assert.False(response.Headers.TransferEncodingChunked.HasValue, "Chunked");
Assert.Equal(0, response.Content.Headers.ContentLength);
Assert.Equal(string.Empty, await response.Content.ReadAsStringAsync());
}
}
[ConditionalFact]
[OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, WindowsVersions.Win2008R2)]
public async Task OpaqueUpgrade_SupportKeys_Present()