diff --git a/src/Tools/dotnet-watch/BrowserRefresh/src/BrowserScriptMiddleware.cs b/src/Tools/dotnet-watch/BrowserRefresh/src/BrowserScriptMiddleware.cs
new file mode 100644
index 0000000000..b90ae7591d
--- /dev/null
+++ b/src/Tools/dotnet-watch/BrowserRefresh/src/BrowserScriptMiddleware.cs
@@ -0,0 +1,51 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Globalization;
+using System.IO;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
+
+namespace Microsoft.AspNetCore.Watch.BrowserRefresh
+{
+ ///
+ /// Responds with the contennts of WebSocketScriptInjection.js with the stub WebSocket url replaced by the
+ /// one specified by the launching app.
+ ///
+ public sealed class BrowserScriptMiddleware
+ {
+ private readonly byte[] _scriptBytes;
+ private readonly string _contentLength;
+
+ public BrowserScriptMiddleware(RequestDelegate next)
+ : this(Environment.GetEnvironmentVariable("ASPNETCORE_AUTO_RELOAD_WS_ENDPOINT")!)
+ {
+ }
+
+ internal BrowserScriptMiddleware(string webSocketUrl)
+ {
+ _scriptBytes = GetWebSocketClientJavaScript(webSocketUrl);
+ _contentLength = _scriptBytes.Length.ToString(CultureInfo.InvariantCulture);
+ }
+
+ public async Task InvokeAsync(HttpContext context)
+ {
+ context.Response.Headers["Cache-Control"] = "no-store";
+ context.Response.Headers["Content-Length"] = _contentLength;
+ context.Response.Headers["Content-Type"] = "application/javascript; charset=utf-8";
+
+ await context.Response.Body.WriteAsync(_scriptBytes.AsMemory(), context.RequestAborted);
+ }
+
+ internal static byte[] GetWebSocketClientJavaScript(string hostString)
+ {
+ var jsFileName = "Microsoft.AspNetCore.Watch.BrowserRefresh.WebSocketScriptInjection.js";
+ using var reader = new StreamReader(typeof(WebSocketScriptInjection).Assembly.GetManifestResourceStream(jsFileName)!);
+ var script = reader.ReadToEnd().Replace("{{hostString}}", hostString);
+
+ return Encoding.UTF8.GetBytes(script);
+ }
+ }
+}
diff --git a/src/Tools/dotnet-watch/BrowserRefresh/src/HostingFilter.cs b/src/Tools/dotnet-watch/BrowserRefresh/src/HostingFilter.cs
index 02135dca0d..68f32444b7 100644
--- a/src/Tools/dotnet-watch/BrowserRefresh/src/HostingFilter.cs
+++ b/src/Tools/dotnet-watch/BrowserRefresh/src/HostingFilter.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
+using System.Globalization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
@@ -22,6 +23,7 @@ namespace Microsoft.AspNetCore.Watch.BrowserRefresh
{
return app =>
{
+ app.Map(WebSocketScriptInjection.WebSocketScriptUrl, app1 => app1.UseMiddleware());
app.UseMiddleware();
next(app);
};
diff --git a/src/Tools/dotnet-watch/BrowserRefresh/src/ResponseStreamWrapper.cs b/src/Tools/dotnet-watch/BrowserRefresh/src/ResponseStreamWrapper.cs
index dfc5d46503..ae5fcc6f2c 100644
--- a/src/Tools/dotnet-watch/BrowserRefresh/src/ResponseStreamWrapper.cs
+++ b/src/Tools/dotnet-watch/BrowserRefresh/src/ResponseStreamWrapper.cs
@@ -58,7 +58,7 @@ namespace Microsoft.AspNetCore.Watch.BrowserRefresh
OnWrite();
if (IsHtmlResponse && !ScriptInjectionPerformed)
{
- ScriptInjectionPerformed = WebSocketScriptInjection.Instance.TryInjectLiveReloadScript(_baseStream, buffer);
+ ScriptInjectionPerformed = WebSocketScriptInjection.TryInjectLiveReloadScript(_baseStream, buffer);
}
else
{
@@ -78,7 +78,7 @@ namespace Microsoft.AspNetCore.Watch.BrowserRefresh
if (IsHtmlResponse && !ScriptInjectionPerformed)
{
- ScriptInjectionPerformed = WebSocketScriptInjection.Instance.TryInjectLiveReloadScript(_baseStream, buffer.AsSpan(offset, count));
+ ScriptInjectionPerformed = WebSocketScriptInjection.TryInjectLiveReloadScript(_baseStream, buffer.AsSpan(offset, count));
}
else
{
@@ -92,7 +92,7 @@ namespace Microsoft.AspNetCore.Watch.BrowserRefresh
if (IsHtmlResponse && !ScriptInjectionPerformed)
{
- ScriptInjectionPerformed = await WebSocketScriptInjection.Instance.TryInjectLiveReloadScriptAsync(_baseStream, buffer.AsMemory(offset, count), cancellationToken);
+ ScriptInjectionPerformed = await WebSocketScriptInjection.TryInjectLiveReloadScriptAsync(_baseStream, buffer.AsMemory(offset, count), cancellationToken);
}
else
{
@@ -106,7 +106,7 @@ namespace Microsoft.AspNetCore.Watch.BrowserRefresh
if (IsHtmlResponse && !ScriptInjectionPerformed)
{
- ScriptInjectionPerformed = await WebSocketScriptInjection.Instance.TryInjectLiveReloadScriptAsync(_baseStream, buffer, cancellationToken);
+ ScriptInjectionPerformed = await WebSocketScriptInjection.TryInjectLiveReloadScriptAsync(_baseStream, buffer, cancellationToken);
}
else
{
diff --git a/src/Tools/dotnet-watch/BrowserRefresh/src/WebSocketScriptInjection.cs b/src/Tools/dotnet-watch/BrowserRefresh/src/WebSocketScriptInjection.cs
index f0e85e2fa8..43cb43c50e 100644
--- a/src/Tools/dotnet-watch/BrowserRefresh/src/WebSocketScriptInjection.cs
+++ b/src/Tools/dotnet-watch/BrowserRefresh/src/WebSocketScriptInjection.cs
@@ -13,22 +13,18 @@ namespace Microsoft.AspNetCore.Watch.BrowserRefresh
/// Helper class that handles the HTML injection into
/// a string or byte array.
///
- public class WebSocketScriptInjection
+ public static class WebSocketScriptInjection
{
private const string BodyMarker = "