Add opaque upgrade tests.
This commit is contained in:
parent
d1dab1665e
commit
6a810fd648
|
|
@ -15,7 +15,6 @@
|
||||||
// See the Apache 2 License for the specific language governing
|
// See the Apache 2 License for the specific language governing
|
||||||
// permissions and limitations under the License.
|
// permissions and limitations under the License.
|
||||||
|
|
||||||
/* TODO: Opaque
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
@ -24,14 +23,13 @@ using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.FeatureModel;
|
||||||
|
using Microsoft.AspNet.HttpFeature;
|
||||||
|
using Microsoft.AspNet.PipelineCore;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Xunit.Extensions;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Server.WebListener
|
namespace Microsoft.AspNet.Server.WebListener
|
||||||
{
|
{
|
||||||
using AppFunc = Func<object, Task>;
|
|
||||||
using OpaqueUpgrade = Action<IDictionary<string, object>, Func<IDictionary<string, object>, Task>>;
|
|
||||||
|
|
||||||
public class OpaqueUpgradeTests
|
public class OpaqueUpgradeTests
|
||||||
{
|
{
|
||||||
private const string Address = "http://localhost:8080/";
|
private const string Address = "http://localhost:8080/";
|
||||||
|
|
@ -39,22 +37,17 @@ namespace Microsoft.AspNet.Server.WebListener
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task OpaqueUpgrade_SupportKeys_Present()
|
public async Task OpaqueUpgrade_SupportKeys_Present()
|
||||||
{
|
{
|
||||||
using (CreateServer(env =>
|
using (Utilities.CreateHttpServer(env =>
|
||||||
{
|
{
|
||||||
|
var httpContext = new DefaultHttpContext((IFeatureCollection)env);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
IDictionary<string, object> capabilities = env.Get<IDictionary<string, object>>("server.Capabilities");
|
var opaqueFeature = httpContext.GetFeature<IHttpOpaqueUpgradeFeature>();
|
||||||
Assert.NotNull(capabilities);
|
Assert.NotNull(opaqueFeature);
|
||||||
|
|
||||||
Assert.Equal("1.0", capabilities.Get<string>("opaque.Version"));
|
|
||||||
|
|
||||||
OpaqueUpgrade opaqueUpgrade = env.Get<OpaqueUpgrade>("opaque.Upgrade");
|
|
||||||
Assert.NotNull(opaqueUpgrade);
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
byte[] body = Encoding.UTF8.GetBytes(ex.ToString());
|
return httpContext.Response.WriteAsync(ex.ToString());
|
||||||
env.Get<Stream>("owin.ResponseBody").Write(body, 0, body.Length);
|
|
||||||
}
|
}
|
||||||
return Task.FromResult(0);
|
return Task.FromResult(0);
|
||||||
}))
|
}))
|
||||||
|
|
@ -67,50 +60,25 @@ namespace Microsoft.AspNet.Server.WebListener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task OpaqueUpgrade_NullCallback_Throws()
|
|
||||||
{
|
|
||||||
using (CreateServer(env =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
OpaqueUpgrade opaqueUpgrade = env.Get<OpaqueUpgrade>("opaque.Upgrade");
|
|
||||||
opaqueUpgrade(new Dictionary<string, object>(), null);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
byte[] body = Encoding.UTF8.GetBytes(ex.ToString());
|
|
||||||
env.Get<Stream>("owin.ResponseBody").Write(body, 0, body.Length);
|
|
||||||
}
|
|
||||||
return Task.FromResult(0);
|
|
||||||
}))
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = await SendRequestAsync(Address);
|
|
||||||
Assert.Equal(200, (int)response.StatusCode);
|
|
||||||
Assert.True(response.Headers.TransferEncodingChunked.Value, "Chunked");
|
|
||||||
Assert.Contains("callback", response.Content.ReadAsStringAsync().Result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task OpaqueUpgrade_AfterHeadersSent_Throws()
|
public async Task OpaqueUpgrade_AfterHeadersSent_Throws()
|
||||||
{
|
{
|
||||||
bool? upgradeThrew = null;
|
bool? upgradeThrew = null;
|
||||||
using (CreateServer(env =>
|
using (Utilities.CreateHttpServer(async env =>
|
||||||
{
|
{
|
||||||
byte[] body = Encoding.UTF8.GetBytes("Hello World");
|
var httpContext = new DefaultHttpContext((IFeatureCollection)env);
|
||||||
env.Get<Stream>("owin.ResponseBody").Write(body, 0, body.Length);
|
await httpContext.Response.WriteAsync("Hello World");
|
||||||
OpaqueUpgrade opaqueUpgrade = env.Get<OpaqueUpgrade>("opaque.Upgrade");
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
opaqueUpgrade(null, _ => Task.FromResult(0));
|
var opaqueFeature = httpContext.GetFeature<IHttpOpaqueUpgradeFeature>();
|
||||||
|
Assert.NotNull(opaqueFeature);
|
||||||
|
await opaqueFeature.UpgradeAsync();
|
||||||
upgradeThrew = false;
|
upgradeThrew = false;
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException)
|
catch (InvalidOperationException)
|
||||||
{
|
{
|
||||||
upgradeThrew = true;
|
upgradeThrew = true;
|
||||||
}
|
}
|
||||||
return Task.FromResult(0);
|
|
||||||
}))
|
}))
|
||||||
{
|
{
|
||||||
HttpResponseMessage response = await SendRequestAsync(Address);
|
HttpResponseMessage response = await SendRequestAsync(Address);
|
||||||
|
|
@ -124,26 +92,24 @@ namespace Microsoft.AspNet.Server.WebListener
|
||||||
public async Task OpaqueUpgrade_GetUpgrade_Success()
|
public async Task OpaqueUpgrade_GetUpgrade_Success()
|
||||||
{
|
{
|
||||||
ManualResetEvent waitHandle = new ManualResetEvent(false);
|
ManualResetEvent waitHandle = new ManualResetEvent(false);
|
||||||
bool? callbackInvoked = null;
|
bool? upgraded = null;
|
||||||
using (CreateServer(env =>
|
using (Utilities.CreateHttpServer(async env =>
|
||||||
{
|
{
|
||||||
var responseHeaders = env.Get<IDictionary<string, string[]>>("owin.ResponseHeaders");
|
var httpContext = new DefaultHttpContext((IFeatureCollection)env);
|
||||||
responseHeaders["Upgrade"] = new string[] { "websocket" }; // Win8.1 blocks anything but WebSockets
|
httpContext.Response.Headers["Upgrade"] = "websocket"; // Win8.1 blocks anything but WebSockets
|
||||||
OpaqueUpgrade opaqueUpgrade = env.Get<OpaqueUpgrade>("opaque.Upgrade");
|
var opaqueFeature = httpContext.GetFeature<IHttpOpaqueUpgradeFeature>();
|
||||||
opaqueUpgrade(null, opqEnv =>
|
Assert.NotNull(opaqueFeature);
|
||||||
{
|
Assert.True(opaqueFeature.IsUpgradableRequest);
|
||||||
callbackInvoked = true;
|
await opaqueFeature.UpgradeAsync();
|
||||||
waitHandle.Set();
|
upgraded = true;
|
||||||
return Task.FromResult(0);
|
waitHandle.Set();
|
||||||
});
|
|
||||||
return Task.FromResult(0);
|
|
||||||
}))
|
}))
|
||||||
{
|
{
|
||||||
using (Stream stream = await SendOpaqueRequestAsync("GET", Address))
|
using (Stream stream = await SendOpaqueRequestAsync("GET", Address))
|
||||||
{
|
{
|
||||||
Assert.True(waitHandle.WaitOne(TimeSpan.FromSeconds(1)), "Timed out");
|
Assert.True(waitHandle.WaitOne(TimeSpan.FromSeconds(1)), "Timed out");
|
||||||
Assert.True(callbackInvoked.HasValue, "CallbackInvoked not set");
|
Assert.True(upgraded.HasValue, "Upgraded not set");
|
||||||
Assert.True(callbackInvoked.Value, "Callback not invoked");
|
Assert.True(upgraded.Value, "Upgrade failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -173,21 +139,26 @@ namespace Microsoft.AspNet.Server.WebListener
|
||||||
[InlineData("PUT", "Content-Length: 0")]
|
[InlineData("PUT", "Content-Length: 0")]
|
||||||
public async Task OpaqueUpgrade_VariousMethodsUpgradeSendAndReceive_Success(string method, string extraHeader)
|
public async Task OpaqueUpgrade_VariousMethodsUpgradeSendAndReceive_Success(string method, string extraHeader)
|
||||||
{
|
{
|
||||||
using (CreateServer(env =>
|
using (Utilities.CreateHttpServer(async env =>
|
||||||
{
|
{
|
||||||
var responseHeaders = env.Get<IDictionary<string, string[]>>("owin.ResponseHeaders");
|
var httpContext = new DefaultHttpContext((IFeatureCollection)env);
|
||||||
responseHeaders["Upgrade"] = new string[] { "WebSocket" }; // Win8.1 blocks anything but WebSockets
|
try
|
||||||
OpaqueUpgrade opaqueUpgrade = env.Get<OpaqueUpgrade>("opaque.Upgrade");
|
|
||||||
opaqueUpgrade(null, async opqEnv =>
|
|
||||||
{
|
{
|
||||||
Stream opaqueStream = opqEnv.Get<Stream>("opaque.Stream");
|
httpContext.Response.Headers["Upgrade"] = "websocket"; // Win8.1 blocks anything but WebSockets
|
||||||
|
var opaqueFeature = httpContext.GetFeature<IHttpOpaqueUpgradeFeature>();
|
||||||
|
Assert.NotNull(opaqueFeature);
|
||||||
|
Assert.True(opaqueFeature.IsUpgradableRequest);
|
||||||
|
var opaqueStream = await opaqueFeature.UpgradeAsync();
|
||||||
|
|
||||||
byte[] buffer = new byte[100];
|
byte[] buffer = new byte[100];
|
||||||
int read = await opaqueStream.ReadAsync(buffer, 0, buffer.Length);
|
int read = await opaqueStream.ReadAsync(buffer, 0, buffer.Length);
|
||||||
|
|
||||||
await opaqueStream.WriteAsync(buffer, 0, read);
|
await opaqueStream.WriteAsync(buffer, 0, read);
|
||||||
});
|
}
|
||||||
return Task.FromResult(0);
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await httpContext.Response.WriteAsync(ex.ToString());
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
{
|
{
|
||||||
using (Stream stream = await SendOpaqueRequestAsync(method, Address, extraHeader))
|
using (Stream stream = await SendOpaqueRequestAsync(method, Address, extraHeader))
|
||||||
|
|
@ -208,54 +179,27 @@ namespace Microsoft.AspNet.Server.WebListener
|
||||||
[InlineData("PUT", "Transfer-Encoding: chunked")]
|
[InlineData("PUT", "Transfer-Encoding: chunked")]
|
||||||
[InlineData("CUSTOMVERB", "Content-Length: 10")]
|
[InlineData("CUSTOMVERB", "Content-Length: 10")]
|
||||||
[InlineData("CUSTOMVERB", "Transfer-Encoding: chunked")]
|
[InlineData("CUSTOMVERB", "Transfer-Encoding: chunked")]
|
||||||
public void OpaqueUpgrade_InvalidMethodUpgrade_Disconnected(string method, string extraHeader)
|
public async Task OpaqueUpgrade_InvalidMethodUpgrade_Disconnected(string method, string extraHeader)
|
||||||
{
|
{
|
||||||
OpaqueUpgrade opaqueUpgrade = null;
|
using (Utilities.CreateHttpServer(async env =>
|
||||||
using (CreateServer(env =>
|
|
||||||
{
|
{
|
||||||
opaqueUpgrade = env.Get<OpaqueUpgrade>("opaque.Upgrade");
|
var httpContext = new DefaultHttpContext((IFeatureCollection)env);
|
||||||
if (opaqueUpgrade == null)
|
try
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
var opaqueFeature = httpContext.GetFeature<IHttpOpaqueUpgradeFeature>();
|
||||||
|
Assert.NotNull(opaqueFeature);
|
||||||
|
Assert.False(opaqueFeature.IsUpgradableRequest);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await httpContext.Response.WriteAsync(ex.ToString());
|
||||||
}
|
}
|
||||||
opaqueUpgrade(null, opqEnv => Task.FromResult(0));
|
|
||||||
return Task.FromResult(0);
|
|
||||||
}))
|
}))
|
||||||
{
|
{
|
||||||
Assert.Throws<InvalidOperationException>(() =>
|
await Assert.ThrowsAsync<InvalidOperationException>(async () => await SendOpaqueRequestAsync(method, Address, extraHeader));
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return SendOpaqueRequestAsync(method, Address, extraHeader).Result;
|
|
||||||
}
|
|
||||||
catch (AggregateException ag)
|
|
||||||
{
|
|
||||||
throw ag.GetBaseException();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Assert.Null(opaqueUpgrade);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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())
|
||||||
|
|
@ -333,5 +277,4 @@ namespace Microsoft.AspNet.Server.WebListener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
@ -1,135 +1,57 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||||
|
|
||||||
/* TODO: Opaque
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Xunit.Extensions;
|
|
||||||
|
|
||||||
namespace Microsoft.Net.Server
|
namespace Microsoft.Net.Server
|
||||||
{
|
{
|
||||||
using AppFunc = Func<object, Task>;
|
|
||||||
using OpaqueUpgrade = Action<IDictionary<string, object>, Func<IDictionary<string, object>, Task>>;
|
|
||||||
|
|
||||||
public class OpaqueUpgradeTests
|
public class OpaqueUpgradeTests
|
||||||
{
|
{
|
||||||
private const string Address = "http://localhost:8080/";
|
private const string Address = "http://localhost:8080/";
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task OpaqueUpgrade_SupportKeys_Present()
|
|
||||||
{
|
|
||||||
using (CreateServer(env =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
IDictionary<string, object> capabilities = env.Get<IDictionary<string, object>>("server.Capabilities");
|
|
||||||
Assert.NotNull(capabilities);
|
|
||||||
|
|
||||||
Assert.Equal("1.0", capabilities.Get<string>("opaque.Version"));
|
|
||||||
|
|
||||||
OpaqueUpgrade opaqueUpgrade = env.Get<OpaqueUpgrade>("opaque.Upgrade");
|
|
||||||
Assert.NotNull(opaqueUpgrade);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
byte[] body = Encoding.UTF8.GetBytes(ex.ToString());
|
|
||||||
env.Get<Stream>("owin.ResponseBody").Write(body, 0, body.Length);
|
|
||||||
}
|
|
||||||
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, response.Content.ReadAsStringAsync().Result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task OpaqueUpgrade_NullCallback_Throws()
|
|
||||||
{
|
|
||||||
using (CreateServer(env =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
OpaqueUpgrade opaqueUpgrade = env.Get<OpaqueUpgrade>("opaque.Upgrade");
|
|
||||||
opaqueUpgrade(new Dictionary<string, object>(), null);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
byte[] body = Encoding.UTF8.GetBytes(ex.ToString());
|
|
||||||
env.Get<Stream>("owin.ResponseBody").Write(body, 0, body.Length);
|
|
||||||
}
|
|
||||||
return Task.FromResult(0);
|
|
||||||
}))
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = await SendRequestAsync(Address);
|
|
||||||
Assert.Equal(200, (int)response.StatusCode);
|
|
||||||
Assert.True(response.Headers.TransferEncodingChunked.Value, "Chunked");
|
|
||||||
Assert.Contains("callback", response.Content.ReadAsStringAsync().Result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task OpaqueUpgrade_AfterHeadersSent_Throws()
|
public async Task OpaqueUpgrade_AfterHeadersSent_Throws()
|
||||||
{
|
{
|
||||||
bool? upgradeThrew = null;
|
using (var server = Utilities.CreateHttpServer())
|
||||||
using (CreateServer(env =>
|
|
||||||
{
|
{
|
||||||
|
Task<HttpResponseMessage> clientTask = SendRequestAsync(Address);
|
||||||
|
|
||||||
|
var context = await server.GetContextAsync();
|
||||||
byte[] body = Encoding.UTF8.GetBytes("Hello World");
|
byte[] body = Encoding.UTF8.GetBytes("Hello World");
|
||||||
env.Get<Stream>("owin.ResponseBody").Write(body, 0, body.Length);
|
context.Response.Body.Write(body, 0, body.Length);
|
||||||
OpaqueUpgrade opaqueUpgrade = env.Get<OpaqueUpgrade>("opaque.Upgrade");
|
|
||||||
try
|
context.Response.Headers["Upgrade"] = new[] { "WebSocket" }; // Win8.1 blocks anything but WebSocket
|
||||||
{
|
Assert.ThrowsAsync<InvalidOperationException>(async () => await context.UpgradeAsync());
|
||||||
opaqueUpgrade(null, _ => Task.FromResult(0));
|
context.Dispose();
|
||||||
upgradeThrew = false;
|
HttpResponseMessage response = await clientTask;
|
||||||
}
|
|
||||||
catch (InvalidOperationException)
|
|
||||||
{
|
|
||||||
upgradeThrew = true;
|
|
||||||
}
|
|
||||||
return Task.FromResult(0);
|
|
||||||
}))
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = await SendRequestAsync(Address);
|
|
||||||
Assert.Equal(200, (int)response.StatusCode);
|
Assert.Equal(200, (int)response.StatusCode);
|
||||||
Assert.True(response.Headers.TransferEncodingChunked.Value, "Chunked");
|
Assert.True(response.Headers.TransferEncodingChunked.Value, "Chunked");
|
||||||
Assert.True(upgradeThrew.Value);
|
Assert.Equal("Hello World", await response.Content.ReadAsStringAsync());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task OpaqueUpgrade_GetUpgrade_Success()
|
public async Task OpaqueUpgrade_GetUpgrade_Success()
|
||||||
{
|
{
|
||||||
ManualResetEvent waitHandle = new ManualResetEvent(false);
|
using (var server = Utilities.CreateHttpServer())
|
||||||
bool? callbackInvoked = null;
|
|
||||||
using (CreateServer(env =>
|
|
||||||
{
|
{
|
||||||
var responseHeaders = env.Get<IDictionary<string, string[]>>("owin.ResponseHeaders");
|
Task<Stream> clientTask = SendOpaqueRequestAsync("GET", Address);
|
||||||
responseHeaders["Upgrade"] = new string[] { "websocket" }; // Win8.1 blocks anything but WebSockets
|
|
||||||
OpaqueUpgrade opaqueUpgrade = env.Get<OpaqueUpgrade>("opaque.Upgrade");
|
var context = await server.GetContextAsync();
|
||||||
opaqueUpgrade(null, opqEnv =>
|
Assert.True(context.IsUpgradableRequest);
|
||||||
{
|
context.Response.Headers["Upgrade"] = new[] { "WebSocket" }; // Win8.1 blocks anything but WebSocket
|
||||||
callbackInvoked = true;
|
Stream serverStream = await context.UpgradeAsync();
|
||||||
waitHandle.Set();
|
Assert.True(serverStream.CanRead);
|
||||||
return Task.FromResult(0);
|
Assert.True(serverStream.CanWrite);
|
||||||
});
|
Stream clientStream = await clientTask;
|
||||||
return Task.FromResult(0);
|
serverStream.Dispose();
|
||||||
}))
|
context.Dispose();
|
||||||
{
|
clientStream.Dispose();
|
||||||
using (Stream stream = await SendOpaqueRequestAsync("GET", Address))
|
|
||||||
{
|
|
||||||
Assert.True(waitHandle.WaitOne(TimeSpan.FromSeconds(1)), "Timed out");
|
|
||||||
Assert.True(callbackInvoked.HasValue, "CallbackInvoked not set");
|
|
||||||
Assert.True(callbackInvoked.Value, "Callback not invoked");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -158,30 +80,32 @@ namespace Microsoft.Net.Server
|
||||||
[InlineData("PUT", "Content-Length: 0")]
|
[InlineData("PUT", "Content-Length: 0")]
|
||||||
public async Task OpaqueUpgrade_VariousMethodsUpgradeSendAndReceive_Success(string method, string extraHeader)
|
public async Task OpaqueUpgrade_VariousMethodsUpgradeSendAndReceive_Success(string method, string extraHeader)
|
||||||
{
|
{
|
||||||
using (CreateServer(env =>
|
using (var server = Utilities.CreateHttpServer())
|
||||||
{
|
{
|
||||||
var responseHeaders = env.Get<IDictionary<string, string[]>>("owin.ResponseHeaders");
|
Task<Stream> clientTask = SendOpaqueRequestAsync(method, Address, extraHeader);
|
||||||
responseHeaders["Upgrade"] = new string[] { "WebSocket" }; // Win8.1 blocks anything but WebSockets
|
|
||||||
OpaqueUpgrade opaqueUpgrade = env.Get<OpaqueUpgrade>("opaque.Upgrade");
|
|
||||||
opaqueUpgrade(null, async opqEnv =>
|
|
||||||
{
|
|
||||||
Stream opaqueStream = opqEnv.Get<Stream>("opaque.Stream");
|
|
||||||
|
|
||||||
byte[] buffer = new byte[100];
|
var context = await server.GetContextAsync();
|
||||||
int read = await opaqueStream.ReadAsync(buffer, 0, buffer.Length);
|
Assert.True(context.IsUpgradableRequest);
|
||||||
|
context.Response.Headers["Upgrade"] = new[] { "WebSocket" }; // Win8.1 blocks anything but WebSocket
|
||||||
|
Stream serverStream = await context.UpgradeAsync();
|
||||||
|
Stream clientStream = await clientTask;
|
||||||
|
|
||||||
await opaqueStream.WriteAsync(buffer, 0, read);
|
byte[] clientBuffer = new byte[] { 0x00, 0x01, 0xFF, 0x00, 0x00 };
|
||||||
});
|
await clientStream.WriteAsync(clientBuffer, 0, 3);
|
||||||
return Task.FromResult(0);
|
|
||||||
}))
|
byte[] serverBuffer = new byte[clientBuffer.Length];
|
||||||
{
|
int read = await serverStream.ReadAsync(serverBuffer, 0, serverBuffer.Length);
|
||||||
using (Stream stream = await SendOpaqueRequestAsync(method, Address, extraHeader))
|
Assert.Equal(clientBuffer, serverBuffer);
|
||||||
{
|
|
||||||
byte[] data = new byte[100];
|
await serverStream.WriteAsync(serverBuffer, 0, read);
|
||||||
stream.WriteAsync(data, 0, 49).Wait();
|
|
||||||
int read = stream.ReadAsync(data, 0, data.Length).Result;
|
byte[] clientEchoBuffer = new byte[clientBuffer.Length];
|
||||||
Assert.Equal(49, read);
|
read = await clientStream.ReadAsync(clientEchoBuffer, 0, clientEchoBuffer.Length);
|
||||||
}
|
Assert.Equal(clientBuffer, clientEchoBuffer);
|
||||||
|
|
||||||
|
serverStream.Dispose();
|
||||||
|
context.Dispose();
|
||||||
|
clientStream.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -193,54 +117,19 @@ namespace Microsoft.Net.Server
|
||||||
[InlineData("PUT", "Transfer-Encoding: chunked")]
|
[InlineData("PUT", "Transfer-Encoding: chunked")]
|
||||||
[InlineData("CUSTOMVERB", "Content-Length: 10")]
|
[InlineData("CUSTOMVERB", "Content-Length: 10")]
|
||||||
[InlineData("CUSTOMVERB", "Transfer-Encoding: chunked")]
|
[InlineData("CUSTOMVERB", "Transfer-Encoding: chunked")]
|
||||||
public void OpaqueUpgrade_InvalidMethodUpgrade_Disconnected(string method, string extraHeader)
|
public async Task OpaqueUpgrade_InvalidMethodUpgrade_Disconnected(string method, string extraHeader)
|
||||||
{
|
{
|
||||||
OpaqueUpgrade opaqueUpgrade = null;
|
using (var server = Utilities.CreateHttpServer())
|
||||||
using (CreateServer(env =>
|
|
||||||
{
|
{
|
||||||
opaqueUpgrade = env.Get<OpaqueUpgrade>("opaque.Upgrade");
|
var clientTask = SendOpaqueRequestAsync(method, Address, extraHeader);
|
||||||
if (opaqueUpgrade == null)
|
var context = await server.GetContextAsync();
|
||||||
{
|
Assert.False(context.IsUpgradableRequest);
|
||||||
throw new NotImplementedException();
|
context.Dispose();
|
||||||
}
|
|
||||||
opaqueUpgrade(null, opqEnv => Task.FromResult(0));
|
await Assert.ThrowsAsync<InvalidOperationException>(async () => await clientTask);
|
||||||
return Task.FromResult(0);
|
|
||||||
}))
|
|
||||||
{
|
|
||||||
Assert.Throws<InvalidOperationException>(() =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return SendOpaqueRequestAsync(method, Address, extraHeader).Result;
|
|
||||||
}
|
|
||||||
catch (AggregateException ag)
|
|
||||||
{
|
|
||||||
throw ag.GetBaseException();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Assert.Null(opaqueUpgrade);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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())
|
||||||
|
|
@ -318,5 +207,4 @@ namespace Microsoft.Net.Server
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
Loading…
Reference in New Issue