Welcome to mirror list, hosted at ThFree Co, Russian Federation.

Startup.cs « BrowserDebugHost « wasm « sdks - github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: e18df90c39c7429ee9862feee9cea02a4bc552ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System.Net.Http;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;

namespace WebAssembly.Net.Debugging {
	internal class Startup {
		// This method gets called by the runtime. Use this method to add services to the container.
		// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
		public void ConfigureServices (IServiceCollection services) =>
			services.AddRouting ()
				.Configure<ProxyOptions> (Configuration);

		public Startup (IConfiguration configuration) =>
			Configuration = configuration;

		public IConfiguration Configuration { get; }

		// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
		public void Configure (IApplicationBuilder app, IOptionsMonitor<ProxyOptions> optionsAccessor, IWebHostEnvironment env)
		{
			var options  = 	optionsAccessor.CurrentValue;
			app.UseDeveloperExceptionPage ()
				.UseWebSockets ()
				.UseDebugProxy (options);
		}
	}

	static class DebugExtensions {
		public static Dictionary<string,string> MapValues (Dictionary<string,string> response, HttpContext context, Uri debuggerHost)
		{
			var filtered = new Dictionary<string, string> ();
			var request = context.Request;

			foreach (var key in response.Keys) {
				switch (key) {
				case "devtoolsFrontendUrl":
					var front = response [key];
					filtered[key] = $"{debuggerHost.Scheme}://{debuggerHost.Authority}{front.Replace ($"ws={debuggerHost.Authority}", $"ws={request.Host}")}";
					break;
				case "webSocketDebuggerUrl":
					var page = new Uri (response [key]);
					filtered [key] = $"{page.Scheme}://{request.Host}{page.PathAndQuery}";
					break;
				default:
					filtered [key] = response [key];
					break;
				}
			}
			return filtered;
		}

		public static IApplicationBuilder UseDebugProxy (this IApplicationBuilder app, ProxyOptions options) =>
			UseDebugProxy (app, options, MapValues);
		
		public static IApplicationBuilder UseDebugProxy (
			this IApplicationBuilder app,
			ProxyOptions options,
			Func<Dictionary<string,string>, HttpContext, Uri, Dictionary<string,string>> mapFunc)
		{
			var devToolsHost = options.DevToolsUrl;
			app.UseRouter (router => {
				router.MapGet ("/", Copy);
				router.MapGet ("/favicon.ico", Copy);
				router.MapGet ("json", RewriteArray);
				router.MapGet ("json/list", RewriteArray);
				router.MapGet ("json/version", RewriteSingle);
				router.MapGet ("json/new", RewriteSingle);
				router.MapGet ("devtools/page/{pageId}", ConnectProxy);
				router.MapGet ("devtools/browser/{pageId}", ConnectProxy);

				string GetEndpoint (HttpContext context)
				{
					var request = context.Request;
					var requestPath = request.Path;
					return $"{devToolsHost.Scheme}://{devToolsHost.Authority}{request.Path}{request.QueryString}";
				}

				async Task Copy (HttpContext context) {
					using (var httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds (5) }) {
						var response = await httpClient.GetAsync (GetEndpoint (context));
						context.Response.ContentType = response.Content.Headers.ContentType.ToString ();
						if ((response.Content.Headers.ContentLength ?? 0) > 0)
							context.Response.ContentLength = response.Content.Headers.ContentLength;
						var bytes = await response.Content.ReadAsByteArrayAsync ();
						await context.Response.Body.WriteAsync (bytes);

					}
				}

				async Task RewriteSingle (HttpContext context)
				{
					var version = await ProxyGetJsonAsync<Dictionary<string, string>> (GetEndpoint (context));
					context.Response.ContentType = "application/json";
					await context.Response.WriteAsync (
						JsonSerializer.Serialize (mapFunc (version, context, devToolsHost)));
				}

				async Task RewriteArray (HttpContext context)
				{
					var tabs = await ProxyGetJsonAsync<Dictionary<string, string> []> (GetEndpoint (context));
					var alteredTabs = tabs.Select (t => mapFunc (t, context, devToolsHost)).ToArray ();
					context.Response.ContentType = "application/json";
					await context.Response.WriteAsync (JsonSerializer.Serialize (alteredTabs));
				}

				async Task ConnectProxy (HttpContext context)
				{
					if (!context.WebSockets.IsWebSocketRequest) {
						context.Response.StatusCode = 400;
						return;
					}

					var endpoint = new Uri ($"ws://{devToolsHost.Authority}{context.Request.Path.ToString ()}");
					try {
						using var loggerFactory = LoggerFactory.Create(
							builder => builder.AddConsole().AddFilter(null, LogLevel.Information));
						var proxy = new DebuggerProxy (loggerFactory);
						var ideSocket = await context.WebSockets.AcceptWebSocketAsync ();

						await proxy.Run (endpoint, ideSocket);
					} catch (Exception e) {
						Console.WriteLine ("got exception {0}", e);
					}
				}
			});
			return app;
		}

		static async Task<T> ProxyGetJsonAsync<T> (string url)
		{
			using (var httpClient = new HttpClient ()) {
				var response = await httpClient.GetAsync (url);
				return await JsonSerializer.DeserializeAsync<T> (await response.Content.ReadAsStreamAsync ());
			}
		}
	}
}