Skip to content

Commit 2e9bb2f

Browse files
Debug proxy as external tool (#19767)
1 parent 147c392 commit 2e9bb2f

File tree

17 files changed

+757
-376
lines changed

17 files changed

+757
-376
lines changed

src/Components/Blazor.sln

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Authentication.Msal", "Auth
103103
EndProject
104104
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Authentication.WebAssembly.Msal", "WebAssembly\Authentication.Msal\src\Microsoft.Authentication.WebAssembly.Msal.csproj", "{2F105FA7-74DA-4855-9D8E-818DEE1F8D43}"
105105
EndProject
106+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DebugProxy", "DebugProxy", "{96DE9B14-D81F-422E-A33A-728BFB9C153A}"
107+
EndProject
108+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.WebAssembly.DebugProxy", "WebAssembly\DebugProxy\src\Microsoft.AspNetCore.Components.WebAssembly.DebugProxy.csproj", "{8BB1A8BE-F002-40A2-9B8E-439284B21C1C}"
109+
EndProject
106110
Global
107111
GlobalSection(SolutionConfigurationPlatforms) = preSolution
108112
Debug|Any CPU = Debug|Any CPU
@@ -521,6 +525,18 @@ Global
521525
{2F105FA7-74DA-4855-9D8E-818DEE1F8D43}.Release|x64.Build.0 = Release|Any CPU
522526
{2F105FA7-74DA-4855-9D8E-818DEE1F8D43}.Release|x86.ActiveCfg = Release|Any CPU
523527
{2F105FA7-74DA-4855-9D8E-818DEE1F8D43}.Release|x86.Build.0 = Release|Any CPU
528+
{8BB1A8BE-F002-40A2-9B8E-439284B21C1C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
529+
{8BB1A8BE-F002-40A2-9B8E-439284B21C1C}.Debug|Any CPU.Build.0 = Debug|Any CPU
530+
{8BB1A8BE-F002-40A2-9B8E-439284B21C1C}.Debug|x64.ActiveCfg = Debug|Any CPU
531+
{8BB1A8BE-F002-40A2-9B8E-439284B21C1C}.Debug|x64.Build.0 = Debug|Any CPU
532+
{8BB1A8BE-F002-40A2-9B8E-439284B21C1C}.Debug|x86.ActiveCfg = Debug|Any CPU
533+
{8BB1A8BE-F002-40A2-9B8E-439284B21C1C}.Debug|x86.Build.0 = Debug|Any CPU
534+
{8BB1A8BE-F002-40A2-9B8E-439284B21C1C}.Release|Any CPU.ActiveCfg = Release|Any CPU
535+
{8BB1A8BE-F002-40A2-9B8E-439284B21C1C}.Release|Any CPU.Build.0 = Release|Any CPU
536+
{8BB1A8BE-F002-40A2-9B8E-439284B21C1C}.Release|x64.ActiveCfg = Release|Any CPU
537+
{8BB1A8BE-F002-40A2-9B8E-439284B21C1C}.Release|x64.Build.0 = Release|Any CPU
538+
{8BB1A8BE-F002-40A2-9B8E-439284B21C1C}.Release|x86.ActiveCfg = Release|Any CPU
539+
{8BB1A8BE-F002-40A2-9B8E-439284B21C1C}.Release|x86.Build.0 = Release|Any CPU
524540
EndGlobalSection
525541
GlobalSection(SolutionProperties) = preSolution
526542
HideSolutionNode = FALSE
@@ -573,6 +589,8 @@ Global
573589
{EAF50654-98ED-44BB-A120-0436EC0CD3E0} = {CBD2BB24-3EC3-4950-ABE4-8C521D258DCD}
574590
{E4D756A7-A934-4D7F-BC6E-7B95FE4098AB} = {B29FB58D-FAE5-405E-9695-BCF93582BE9A}
575591
{2F105FA7-74DA-4855-9D8E-818DEE1F8D43} = {E4D756A7-A934-4D7F-BC6E-7B95FE4098AB}
592+
{96DE9B14-D81F-422E-A33A-728BFB9C153A} = {B29FB58D-FAE5-405E-9695-BCF93582BE9A}
593+
{8BB1A8BE-F002-40A2-9B8E-439284B21C1C} = {96DE9B14-D81F-422E-A33A-728BFB9C153A}
576594
EndGlobalSection
577595
GlobalSection(ExtensibilityGlobals) = postSolution
578596
SolutionGuid = {27A36094-AA50-4FFD-ADE6-C055E391F741}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
namespace Microsoft.AspNetCore.Components.WebAssembly.DebugProxy
5+
{
6+
public class DebugProxyOptions
7+
{
8+
public string BrowserHost { get; set; }
9+
}
10+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
5+
<OutputType>Exe</OutputType>
6+
<PackageId>Microsoft.AspNetCore.Components.WebAssembly.DebugProxy</PackageId>
7+
<IsShippingPackage>true</IsShippingPackage>
8+
<HasReferenceAssembly>false</HasReferenceAssembly>
9+
<Description>Debug proxy for use when building Blazor applications.</Description>
10+
<!-- Set this to false because assemblies should not reference this assembly directly, (except for tests, of course). -->
11+
<IsProjectReferenceProvider>false</IsProjectReferenceProvider>
12+
13+
<!-- This is so that we add the FrameworkReference to Microsoft.AspNetCore.App -->
14+
<UseLatestAspNetCoreReference>true</UseLatestAspNetCoreReference>
15+
<MicrosoftAspNetCoreAppVersion>3.1.0</MicrosoftAspNetCoreAppVersion>
16+
</PropertyGroup>
17+
18+
<ItemGroup>
19+
<Reference Include="Microsoft.Extensions.CommandLineUtils.Sources" />
20+
21+
<!-- Dependencies of ws-proxy sources -->
22+
<Reference Include="Newtonsoft.Json" />
23+
<Reference Include="Mono.Cecil" />
24+
</ItemGroup>
25+
26+
</Project>

src/Components/WebAssembly/Server/src/MonoDebugProxy/ws-proxy/DevToolsProxy.cs renamed to src/Components/WebAssembly/DebugProxy/src/MonoDebugProxy/ws-proxy/DevToolsProxy.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Linq;
33
using System.Threading.Tasks;
44
using Newtonsoft.Json.Linq;
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Diagnostics;
6+
using Microsoft.AspNetCore.Hosting;
7+
using Microsoft.Extensions.CommandLineUtils;
8+
using Microsoft.Extensions.Configuration;
9+
using Microsoft.Extensions.DependencyInjection;
10+
using Microsoft.Extensions.Hosting;
11+
12+
namespace Microsoft.AspNetCore.Components.WebAssembly.DebugProxy
13+
{
14+
public class Program
15+
{
16+
static int Main(string[] args)
17+
{
18+
var app = new CommandLineApplication(throwOnUnexpectedArg: false)
19+
{
20+
Name = "webassembly-debugproxy"
21+
};
22+
app.HelpOption("-?|-h|--help");
23+
24+
var browserHostOption = new CommandOption("-b|--browser-host", CommandOptionType.SingleValue)
25+
{
26+
Description = "Host on which the browser is listening for debug connections. Example: http://localhost:9300"
27+
};
28+
29+
var ownerPidOption = new CommandOption("-op|--owner-pid", CommandOptionType.SingleValue)
30+
{
31+
Description = "ID of the owner process. The debug proxy will shut down if this process exits."
32+
};
33+
34+
app.Options.Add(browserHostOption);
35+
app.Options.Add(ownerPidOption);
36+
37+
app.OnExecute(() =>
38+
{
39+
var host = Host.CreateDefaultBuilder(args)
40+
.ConfigureAppConfiguration((hostingContext, config) =>
41+
{
42+
config.AddCommandLine(args);
43+
})
44+
.ConfigureWebHostDefaults(webBuilder =>
45+
{
46+
webBuilder.UseStartup<Startup>();
47+
48+
// By default we bind to a dyamic port
49+
// This can be overridden using an option like "--urls http://localhost:9500"
50+
webBuilder.UseUrls("http://127.0.0.1:0");
51+
})
52+
.ConfigureServices(serviceCollection =>
53+
{
54+
serviceCollection.AddSingleton(new DebugProxyOptions
55+
{
56+
BrowserHost = browserHostOption.HasValue()
57+
? browserHostOption.Value()
58+
: "http://127.0.0.1:9222",
59+
});
60+
})
61+
.Build();
62+
63+
if (ownerPidOption.HasValue())
64+
{
65+
var ownerProcess = Process.GetProcessById(int.Parse(ownerPidOption.Value()));
66+
ownerProcess.EnableRaisingEvents = true;
67+
ownerProcess.Exited += async (sender, eventArgs) =>
68+
{
69+
Console.WriteLine("Exiting because parent process has exited");
70+
await host.StopAsync();
71+
};
72+
}
73+
74+
host.Run();
75+
76+
return 0;
77+
});
78+
79+
try
80+
{
81+
return app.Execute(args);
82+
}
83+
catch (CommandParsingException cex)
84+
{
85+
app.Error.WriteLine(cex.Message);
86+
app.ShowHelp();
87+
return 1;
88+
}
89+
}
90+
}
91+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Net;
6+
using Microsoft.AspNetCore.Builder;
7+
using Microsoft.Extensions.DependencyInjection;
8+
using Microsoft.Extensions.Logging;
9+
using WebAssembly.Net.Debugging;
10+
11+
namespace Microsoft.AspNetCore.Components.WebAssembly.DebugProxy
12+
{
13+
public class Startup
14+
{
15+
public void Configure(IApplicationBuilder app, DebugProxyOptions debugProxyOptions)
16+
{
17+
app.UseDeveloperExceptionPage();
18+
app.UseWebSockets();
19+
app.UseRouting();
20+
21+
app.UseEndpoints(endpoints =>
22+
{
23+
// At the homepage, we check whether we can uniquely identify the target tab
24+
// - If yes, we redirect directly to the debug tools, proxying to that tab
25+
// - If no, we present a list of available tabs for the user to pick from
26+
endpoints.MapGet("/", new TargetPickerUi(debugProxyOptions).Display);
27+
28+
// At this URL, we wire up the actual WebAssembly proxy
29+
endpoints.MapGet("/ws-proxy", async (context) =>
30+
{
31+
if (!context.WebSockets.IsWebSocketRequest)
32+
{
33+
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
34+
return;
35+
}
36+
37+
var loggerFactory = context.RequestServices.GetRequiredService<ILoggerFactory>();
38+
var browserUri = new Uri(context.Request.Query["browser"]);
39+
var ideSocket = await context.WebSockets.AcceptWebSocketAsync();
40+
await new MonoProxy(loggerFactory).Run(browserUri, ideSocket);
41+
});
42+
});
43+
}
44+
}
45+
}

0 commit comments

Comments
 (0)