Throw InvalidOperationException from IHttpUpgradeFeature.UpgradeAsync when request is not upgradable

This commit is contained in:
Nate McMaster 2017-05-17 10:47:38 -07:00
parent 10f88aeafc
commit 7f0319f5dd
6 changed files with 61 additions and 1 deletions

View File

@ -306,4 +306,7 @@
<data name="RequestProcessingEndError" xml:space="preserve">
<value>Connection processing ended abnormally.</value>
</data>
<data name="CannotUpgradeNonUpgradableRequest" xml:space="preserve">
<value>Cannot upgrade a non-upgradable request. Check IHttpUpgradeFeature.IsUpgradableRequest to determine if a request can be upgraded.</value>
</data>
</root>

View File

@ -230,6 +230,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
async Task<Stream> IHttpUpgradeFeature.UpgradeAsync()
{
if (!((IHttpUpgradeFeature)this).IsUpgradableRequest)
{
throw new InvalidOperationException(CoreStrings.CannotUpgradeNonUpgradableRequest);
}
StatusCode = StatusCodes.Status101SwitchingProtocols;
ReasonPhrase = "Switching Protocols";
ResponseHeaders["Connection"] = "Upgrade";

View File

@ -892,6 +892,20 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
internal static string FormatRequestProcessingEndError()
=> GetString("RequestProcessingEndError");
/// <summary>
/// Cannot upgrade a non-upgradable request. Check IHttpUpgradeFeature.IsUpgradableRequest to determine if a request can be upgraded.
/// </summary>
internal static string CannotUpgradeNonUpgradableRequest
{
get => GetString("CannotUpgradeNonUpgradableRequest");
}
/// <summary>
/// Cannot upgrade a non-upgradable request. Check IHttpUpgradeFeature.IsUpgradableRequest to determine if a request can be upgraded.
/// </summary>
internal static string FormatCannotUpgradeNonUpgradableRequest()
=> GetString("CannotUpgradeNonUpgradableRequest");
private static string GetString(string name, params string[] formatterNames)
{
var value = _resourceManager.GetString(name);

View File

@ -162,6 +162,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
await connection.Send(
"GET /upgrade HTTP/1.1",
"Host:",
"Connection: Upgrade",
"",
"");
await connection.Receive(

View File

@ -1775,6 +1775,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
await connection.Send(
"GET / HTTP/1.1",
"Host:",
"Connection: Upgrade",
"",
"");
await connection.ReceiveForcedEnd(
@ -1789,7 +1790,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
{
await connection.Send(
"GET / HTTP/1.0",
"Connection: keep-alive",
"Connection: keep-alive, Upgrade",
"",
"");
await connection.ReceiveForcedEnd(

View File

@ -182,5 +182,41 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
"");
}
}
[Fact]
public async Task ThrowsWhenUpgradingNonUpgradableRequest()
{
var upgradeTcs = new TaskCompletionSource<bool>();
using (var server = new TestServer(async context =>
{
var feature = context.Features.Get<IHttpUpgradeFeature>();
Assert.False(feature.IsUpgradableRequest);
try
{
var stream = await feature.UpgradeAsync();
}
catch (Exception e)
{
upgradeTcs.TrySetException(e);
}
finally
{
upgradeTcs.TrySetResult(false);
}
}))
{
using (var connection = server.CreateConnection())
{
await connection.Send("GET / HTTP/1.1",
"Host:",
"",
"");
await connection.Receive("HTTP/1.1 200 OK");
}
}
var ex = await Assert.ThrowsAsync<InvalidOperationException>(async () => await upgradeTcs.Task).TimeoutAfter(TimeSpan.FromSeconds(15));
Assert.Equal(CoreStrings.CannotUpgradeNonUpgradableRequest, ex.Message);
}
}
}