Skip to content

Commit 8e61e2c

Browse files
ggeurtskblok
authored andcommitted
WebSocketTransport initialization, shutdown and extension (#951)
1 parent 644c8e0 commit 8e61e2c

File tree

14 files changed

+267
-112
lines changed

14 files changed

+267
-112
lines changed

appveyor-fullframework.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ only_commits:
1616
- appveyor-fullframework.yml
1717
before_build:
1818
- ps: >-
19-
nuget.exe restore .\lib\PuppeteerSharp.AspNetFramework.sln
19+
dotnet restore .\lib\PuppeteerSharp.AspNetFramework.sln
2020
2121
New-SelfSignedCertificate -Subject "localhost" -FriendlyName "Puppeteer" -CertStoreLocation "cert:\CurrentUser\My"
2222
Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,54 @@
11
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Text;
2+
using System.Net.WebSockets;
3+
using System.Threading;
54
using System.Threading.Tasks;
65
using System.Web.Hosting;
7-
using Microsoft.Extensions.Logging;
86
using PuppeteerSharp.Transport;
97

108
namespace PuppeteerSharp.AspNetFramework
119
{
1210
public class AspNetWebSocketTransport : WebSocketTransport
1311
{
12+
#region Static fields
13+
14+
/// <summary>
15+
/// Gets a <see cref="TransportFactory"/> that creates <see cref="AspNetWebSocketTransport"/> instances.
16+
/// </summary>
17+
public static readonly TransportFactory AspNetTransportFactory = CreateAspNetTransport;
18+
1419
/// <summary>
15-
/// Initializes a new instance of the <see cref="PuppeteerSharp.AspNet.AspNetWebSocketTransport"/> class.
20+
/// Gets a <see cref="TransportTaskScheduler"/> that uses ASP.NET <see cref="HostingEnvironment.QueueBackgroundWorkItem(Func{CancellationToken,Task})"/>
21+
/// for scheduling of tasks.
1622
/// </summary>
17-
public AspNetWebSocketTransport() : base(false)
23+
public static readonly TransportTaskScheduler AspNetTransportScheduler = ScheduleBackgroundTask;
24+
25+
#endregion
26+
27+
#region Static methods
28+
29+
private static async Task<IConnectionTransport> CreateAspNetTransport(Uri url, IConnectionOptions connectionOptions, CancellationToken cancellationToken)
1830
{
31+
var webSocketFactory = connectionOptions.WebSocketFactory ?? DefaultWebSocketFactory;
32+
var webSocket = await webSocketFactory(url, connectionOptions, cancellationToken);
33+
return new AspNetWebSocketTransport(webSocket, connectionOptions.EnqueueTransportMessages);
1934
}
2035

21-
public override async Task InitializeAsync(string url, IConnectionOptions connectionOptions, ILoggerFactory loggerFactory = null)
36+
private static void ScheduleBackgroundTask(Func<CancellationToken, Task> taskFactory, CancellationToken cancellationToken)
2237
{
23-
await base.InitializeAsync(url, connectionOptions, loggerFactory).ConfigureAwait(false);
24-
HostingEnvironment.QueueBackgroundWorkItem((cts) => GetResponseAsync());
38+
Task ExecuteAsync(CancellationToken hostingCancellationToken)
39+
=> taskFactory(CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, hostingCancellationToken).Token);
40+
HostingEnvironment.QueueBackgroundWorkItem(ExecuteAsync);
2541
}
42+
43+
#endregion
44+
45+
#region Constructor(s)
46+
47+
/// <inheritdoc />
48+
public AspNetWebSocketTransport(WebSocket client, bool queueRequests)
49+
: base(client, AspNetTransportScheduler, queueRequests)
50+
{ }
51+
52+
#endregion
2653
}
2754
}

lib/PuppeteerSharp.Tests/PuppeteerSharp.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />
1010
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
1111
<PackageReference Include="MicrosoftExtensions.Logging.Xunit" Version="1.0.0" />
12-
<PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" />
12+
<PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" Condition="'$(TargetFramework).StartsWith(`net4`)' == True" />
1313
<PackageReference Include="xunit" Version="2.4.1" />
1414
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
1515
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.0-beta0005" />

lib/PuppeteerSharp.Tests/PuppeteerTests/PuppeteerConnectTests.cs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
using System.Linq;
1+
using System;
2+
using System.Linq;
23
using System.Threading.Tasks;
4+
using PuppeteerSharp.Transport;
35
using Xunit;
46
using Xunit.Abstractions;
57

@@ -87,7 +89,7 @@ public async Task ShouldSupportCustomWebSocket()
8789
WebSocketFactory = (uri, socketOptions, cancellationToken) =>
8890
{
8991
customSocketCreated = true;
90-
return Connection.DefaultWebSocketFactory(uri, socketOptions, cancellationToken);
92+
return WebSocketTransport.DefaultWebSocketFactory(uri, socketOptions, cancellationToken);
9193
}
9294
};
9395

@@ -96,5 +98,25 @@ public async Task ShouldSupportCustomWebSocket()
9698
Assert.True(customSocketCreated);
9799
}
98100
}
101+
102+
[Fact]
103+
public async Task ShouldSupportCustomTransport()
104+
{
105+
var customTransportCreated = false;
106+
var options = new ConnectOptions()
107+
{
108+
BrowserWSEndpoint = Browser.WebSocketEndpoint,
109+
TransportFactory = (url, opt, cancellationToken) =>
110+
{
111+
customTransportCreated = true;
112+
return WebSocketTransport.DefaultTransportFactory(url, opt, cancellationToken);
113+
}
114+
};
115+
116+
using (await Puppeteer.ConnectAsync(options, TestConstants.LoggerFactory))
117+
{
118+
Assert.True(customTransportCreated);
119+
}
120+
}
99121
}
100122
}

lib/PuppeteerSharp.Tests/PuppeteerTests/PuppeteerLaunchTests.cs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
using System;
2-
using System.Collections.Generic;
32
using System.Diagnostics;
43
using System.IO;
54
using System.Linq;
65
using System.Net;
76
using System.Runtime.InteropServices;
8-
using System.Text.RegularExpressions;
97
using System.Threading.Tasks;
108
using PuppeteerSharp.Helpers;
9+
using PuppeteerSharp.Transport;
1110
using Xunit;
1211
using Xunit.Abstractions;
1312

@@ -410,7 +409,7 @@ public async Task ShouldSupportCustomWebSocket()
410409
options.WebSocketFactory = (uri, socketOptions, cancellationToken) =>
411410
{
412411
customSocketCreated = true;
413-
return Connection.DefaultWebSocketFactory(uri, socketOptions, cancellationToken);
412+
return WebSocketTransport.DefaultWebSocketFactory(uri, socketOptions, cancellationToken);
414413
};
415414

416415
using (await Puppeteer.LaunchAsync(options, TestConstants.LoggerFactory))
@@ -419,6 +418,23 @@ public async Task ShouldSupportCustomWebSocket()
419418
}
420419
}
421420

421+
[Fact]
422+
public async Task ShouldSupportCustomTransport()
423+
{
424+
var customTransportCreated = false;
425+
var options = TestConstants.DefaultBrowserOptions();
426+
options.TransportFactory = (url, opt, cancellationToken) =>
427+
{
428+
customTransportCreated = true;
429+
return WebSocketTransport.DefaultTransportFactory(url, opt, cancellationToken);
430+
};
431+
432+
using (await Puppeteer.LaunchAsync(options, TestConstants.LoggerFactory))
433+
{
434+
Assert.True(customTransportCreated);
435+
}
436+
}
437+
422438
private Process GetTestAppProcess(string appName, string arguments)
423439
{
424440
var process = new Process();

lib/PuppeteerSharp/ConnectOptions.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
using System;
22
using System.Net.WebSockets;
3+
using PuppeteerSharp.Transport;
34

45
namespace PuppeteerSharp
56
{
6-
using System.Threading;
7-
using System.Threading.Tasks;
8-
using PuppeteerSharp.Transport;
9-
107
/// <summary>
118
/// Options for connecting to an existing browser.
129
/// </summary>
@@ -48,7 +45,7 @@ public class ConnectOptions : IBrowserOptions, IConnectionOptions
4845
/// Optional factory for <see cref="WebSocket"/> implementations.
4946
/// If <see cref="Transport"/> is set this property will be ignored.
5047
/// </summary>
51-
public Func<Uri, IConnectionOptions, CancellationToken, Task<WebSocket>> WebSocketFactory { get; set; }
48+
public WebSocketFactory WebSocketFactory { get; set; }
5249

5350
/// <summary>
5451
/// Gets or sets the default Viewport.
@@ -59,7 +56,14 @@ public class ConnectOptions : IBrowserOptions, IConnectionOptions
5956
/// <summary>
6057
/// Optional connection transport.
6158
/// </summary>
59+
[Obsolete("Use " + nameof(TransportFactory) + " instead")]
6260
public IConnectionTransport Transport { get; set; }
61+
62+
/// <summary>
63+
/// Optional factory for <see cref="IConnectionTransport"/> implementations.
64+
/// </summary>
65+
public TransportFactory TransportFactory { get; set; }
66+
6367
/// <summary>
6468
/// If not <see cref="Transport"/> is set this will be use to determine is the default <see cref="WebSocketTransport"/> will enqueue messages.
6569
/// </summary>

lib/PuppeteerSharp/Connection.cs

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Collections.Concurrent;
33
using System.Linq;
4-
using System.Net.WebSockets;
54
using System.Threading;
65
using System.Threading.Tasks;
76
using Microsoft.Extensions.Logging;
@@ -270,21 +269,19 @@ private void ProcessIncomingMessage(ConnectionResponse obj)
270269
/// <summary>
271270
/// Gets default web socket factory implementation.
272271
/// </summary>
273-
public static readonly Func<Uri, IConnectionOptions, CancellationToken, Task<WebSocket>> DefaultWebSocketFactory = async (uri, options, cancellationToken) =>
274-
{
275-
var result = new ClientWebSocket();
276-
result.Options.KeepAliveInterval = TimeSpan.Zero;
277-
await result.ConnectAsync(uri, cancellationToken).ConfigureAwait(false);
278-
return result;
279-
};
272+
[Obsolete("Use " + nameof(WebSocketTransport) + "." + nameof(WebSocketTransport.DefaultWebSocketFactory) + " instead")]
273+
public static readonly WebSocketFactory DefaultWebSocketFactory = WebSocketTransport.DefaultWebSocketFactory;
280274

281-
internal static async Task<Connection> Create(string url, IConnectionOptions connectionOptions, ILoggerFactory loggerFactory = null)
275+
internal static async Task<Connection> Create(string url, IConnectionOptions connectionOptions, ILoggerFactory loggerFactory = null, CancellationToken cancellationToken = default)
282276
{
283-
var transport = connectionOptions.Transport ?? new WebSocketTransport();
284-
connectionOptions.WebSocketFactory = connectionOptions.WebSocketFactory ?? DefaultWebSocketFactory;
285-
286-
await transport.InitializeAsync(url, connectionOptions).ConfigureAwait(false);
287-
277+
#pragma warning disable 618
278+
var transport = connectionOptions.Transport;
279+
#pragma warning restore 618
280+
if (transport == null)
281+
{
282+
var transportFactory = connectionOptions.TransportFactory ?? WebSocketTransport.DefaultTransportFactory;
283+
transport = await transportFactory(new Uri(url), connectionOptions, cancellationToken);
284+
}
288285
return new Connection(url, connectionOptions.SlowMo, transport, loggerFactory);
289286
}
290287

lib/PuppeteerSharp/IConnectionOptions.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
using System;
22
using System.Net.WebSockets;
3-
using System.Threading;
4-
using System.Threading.Tasks;
53
using PuppeteerSharp.Transport;
64

75
namespace PuppeteerSharp
@@ -26,13 +24,19 @@ public interface IConnectionOptions
2624
/// Optional factory for <see cref="WebSocket"/> implementations.
2725
/// If <see cref="Transport"/> is set this property will be ignored.
2826
/// </summary>
29-
Func<Uri, IConnectionOptions, CancellationToken, Task<WebSocket>> WebSocketFactory { get; set; }
27+
WebSocketFactory WebSocketFactory { get; set; }
3028

3129
/// <summary>
32-
/// Optional connection transport.
30+
/// Optional connection transport factory.
3331
/// </summary>
32+
[Obsolete("Use " + nameof(TransportFactory) + " instead")]
3433
IConnectionTransport Transport { get; set; }
3534

35+
/// <summary>
36+
/// Optional factory for <see cref="IConnectionTransport"/> implementations.
37+
/// </summary>
38+
TransportFactory TransportFactory { get; set; }
39+
3640
/// <summary>
3741
/// If not <see cref="Transport"/> is set this will be use to determine is the default <see cref="WebSocketTransport"/> will enqueue messages.
3842
/// </summary>

lib/PuppeteerSharp/LaunchOptions.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Net.WebSockets;
4-
using System.Threading;
5-
using System.Threading.Tasks;
64
using PuppeteerSharp.Transport;
75

86
namespace PuppeteerSharp
@@ -110,13 +108,19 @@ public string[] IgnoredDefaultArgs
110108
/// Optional factory for <see cref="WebSocket"/> implementations.
111109
/// If <see cref="Transport"/> is set this property will be ignored.
112110
/// </summary>
113-
public Func<Uri, IConnectionOptions, CancellationToken, Task<WebSocket>> WebSocketFactory { get; set; }
111+
public WebSocketFactory WebSocketFactory { get; set; }
114112

115113
/// <summary>
116114
/// Optional connection transport.
117115
/// </summary>
116+
[Obsolete("Use " + nameof(TransportFactory) + " instead")]
118117
public IConnectionTransport Transport { get; set; }
119118

119+
/// <summary>
120+
/// Optional factory for <see cref="IConnectionTransport"/> implementations.
121+
/// </summary>
122+
public TransportFactory TransportFactory { get; set; }
123+
120124
/// <summary>
121125
/// Gets or sets the default Viewport.
122126
/// </summary>

lib/PuppeteerSharp/Transport/IConnectionTransport.cs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
using System;
2-
using System.Threading;
32
using System.Threading.Tasks;
4-
using Microsoft.Extensions.Logging;
53

64
namespace PuppeteerSharp.Transport
75
{
@@ -10,14 +8,6 @@ namespace PuppeteerSharp.Transport
108
/// </summary>
119
public interface IConnectionTransport : IDisposable
1210
{
13-
/// <summary>
14-
/// Initialize the Transport
15-
/// </summary>
16-
/// <param name="url">Chromium URL</param>
17-
/// <param name="connectionOptions">Connection options</param>
18-
/// <param name="loggerFactory">Logger factory</param>
19-
Task InitializeAsync(string url, IConnectionOptions connectionOptions, ILoggerFactory loggerFactory = null);
20-
2111
/// <summary>
2212
/// Gets a value indicating whether this <see cref="PuppeteerSharp.Transport.IConnectionTransport"/> is closed.
2313
/// </summary>

0 commit comments

Comments
 (0)