From 3775809f2145cc1498cdf5499483243c256e302a Mon Sep 17 00:00:00 2001 From: Bill Hiebert Date: Tue, 22 Jun 2021 16:28:56 -0700 Subject: [PATCH 1/3] Is building and tests pass --- build/dependencies.props | 2 +- build/sources.props | 8 ++--- .../BrowserLinkExtensions.cs | 2 +- .../BrowserLinkMiddleWare.cs | 4 +-- ...rosoft.VisualStudio.Web.BrowserLink.csproj | 9 ++--- .../SendFilesWrapper.cs | 33 +++++++++++++++---- test/Directory.Build.props | 4 +-- .../BrowserLinkMiddleWareUtilTest.cs | 8 ++--- ...t.VisualStudio.Web.BrowserLink.Test.csproj | 5 +-- 9 files changed, 46 insertions(+), 29 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index b91d1a7..cf3f544 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -8,7 +8,7 @@ 3.0.0-alpha1-10584 3.0.0-alpha1-10584 3.0.0-alpha1-10584 - 3.0.0-alpha1-10584 + 3.0.0-alpha1-10657 3.0.0-alpha1-10584 2.0.9 2.1.3 diff --git a/build/sources.props b/build/sources.props index 9215df9..af09707 100644 --- a/build/sources.props +++ b/build/sources.props @@ -5,13 +5,13 @@ $(DotNetRestoreSources) $(RestoreSources); - https://dotnet.myget.org/F/dotnet-core/api/v3/index.json; - https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; - https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; + https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json; + https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json; + https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public/nuget/v3/index.json; $(RestoreSources); https://api.nuget.org/v3/index.json; - + \ No newline at end of file diff --git a/src/Microsoft.VisualStudio.Web.BrowserLink/BrowserLinkExtensions.cs b/src/Microsoft.VisualStudio.Web.BrowserLink/BrowserLinkExtensions.cs index 2816439..77ed092 100644 --- a/src/Microsoft.VisualStudio.Web.BrowserLink/BrowserLinkExtensions.cs +++ b/src/Microsoft.VisualStudio.Web.BrowserLink/BrowserLinkExtensions.cs @@ -59,7 +59,7 @@ private static bool IsMicrosoftRuntime private static bool GetApplicationBasePath(IApplicationBuilder app, out string applicationBasePath) { - IHostingEnvironment hostingEnvironment = app.ApplicationServices.GetService(typeof(IHostingEnvironment)) as IHostingEnvironment; + IWebHostEnvironment hostingEnvironment = app.ApplicationServices.GetService(typeof(IWebHostEnvironment)) as IWebHostEnvironment; if (hostingEnvironment != null) { diff --git a/src/Microsoft.VisualStudio.Web.BrowserLink/BrowserLinkMiddleWare.cs b/src/Microsoft.VisualStudio.Web.BrowserLink/BrowserLinkMiddleWare.cs index 1ca29c8..b87e45e 100644 --- a/src/Microsoft.VisualStudio.Web.BrowserLink/BrowserLinkMiddleWare.cs +++ b/src/Microsoft.VisualStudio.Web.BrowserLink/BrowserLinkMiddleWare.cs @@ -109,8 +109,8 @@ private async Task ExecuteWithFilter(IHttpSocketAdapter injectScriptSocket, stri return StaticTaskResult.True; }); - IHttpSendFileFeature originalSendFile = httpContext.Features.Get(); - httpContext.Features.Set(new SendFilesWrapper(originalSendFile, httpContext.Response)); + IHttpResponseBodyFeature originalSendFile = httpContext.Features.Get(); + httpContext.Features.Set(new SendFilesWrapper(originalSendFile, httpContext.Response)); using (AddPageExecutionListenerFeatureTo(httpContext, requestId)) { diff --git a/src/Microsoft.VisualStudio.Web.BrowserLink/Microsoft.VisualStudio.Web.BrowserLink.csproj b/src/Microsoft.VisualStudio.Web.BrowserLink/Microsoft.VisualStudio.Web.BrowserLink.csproj index a85bf6a..5564378 100644 --- a/src/Microsoft.VisualStudio.Web.BrowserLink/Microsoft.VisualStudio.Web.BrowserLink.csproj +++ b/src/Microsoft.VisualStudio.Web.BrowserLink/Microsoft.VisualStudio.Web.BrowserLink.csproj @@ -2,16 +2,11 @@ A middleware that supports creating a communication channel between the development environment and one or more web browsers. - netstandard2.0 + netcoreapp3.1 true aspnetcore;browserlink - - - - - + - diff --git a/src/Microsoft.VisualStudio.Web.BrowserLink/SendFilesWrapper.cs b/src/Microsoft.VisualStudio.Web.BrowserLink/SendFilesWrapper.cs index 07fcd1d..aa8adb4 100644 --- a/src/Microsoft.VisualStudio.Web.BrowserLink/SendFilesWrapper.cs +++ b/src/Microsoft.VisualStudio.Web.BrowserLink/SendFilesWrapper.cs @@ -1,29 +1,45 @@ using System.IO; +using System.IO.Pipelines; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; + namespace Microsoft.VisualStudio.Web.BrowserLink { - internal class SendFilesWrapper : IHttpSendFileFeature + internal class SendFilesWrapper : IHttpResponseBodyFeature { private HttpResponse _response; - private IHttpSendFileFeature _wrapped; + private IHttpResponseBodyFeature _wrapped; - internal SendFilesWrapper(IHttpSendFileFeature wrapped, HttpResponse response) + internal SendFilesWrapper(IHttpResponseBodyFeature wrapped, HttpResponse response) { _wrapped = wrapped; _response = response; } - async Task IHttpSendFileFeature.SendFileAsync(string path, long offset, long? count, CancellationToken cancellation) + public Stream Stream => _wrapped.Stream; + + public PipeWriter Writer => _wrapped.Writer; + + public Task CompleteAsync() + { + return _wrapped.CompleteAsync(); + } + + public void DisableBuffering() + { + _wrapped.DisableBuffering(); + } + + public async Task SendFileAsync(string path, long offset, long? count, CancellationToken cancellationToken = default) { // TODO: Send mapping data to VS if (_wrapped != null) { - await _wrapped.SendFileAsync(path, offset, count, cancellation); + await _wrapped.SendFileAsync(path, offset, count, cancellationToken); return; } @@ -31,8 +47,13 @@ async Task IHttpSendFileFeature.SendFileAsync(string path, long offset, long? co { readStream.Seek(offset, SeekOrigin.Begin); - await readStream.CopyToAsync(_response.Body, 4096, cancellation); + await readStream.CopyToAsync(_response.Body, 4096, cancellationToken); } } + + public Task StartAsync(CancellationToken cancellationToken = default) + { + return _wrapped.StartAsync(cancellationToken); + } } } diff --git a/test/Directory.Build.props b/test/Directory.Build.props index f033eea..399be30 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -2,10 +2,10 @@ - netcoreapp2.2 + netcoreapp3.1 $(DeveloperBuildTestTfms) - $(StandardTestTfms);net461 + $(StandardTestTfms);net472 diff --git a/test/Microsoft.VisualStudio.Web.BrowserLink.Test/BrowserLinkMiddleWareUtilTest.cs b/test/Microsoft.VisualStudio.Web.BrowserLink.Test/BrowserLinkMiddleWareUtilTest.cs index 45f6692..95b7bfb 100644 --- a/test/Microsoft.VisualStudio.Web.BrowserLink.Test/BrowserLinkMiddleWareUtilTest.cs +++ b/test/Microsoft.VisualStudio.Web.BrowserLink.Test/BrowserLinkMiddleWareUtilTest.cs @@ -352,7 +352,7 @@ public void FilterRequestHeader_PortsNotMatch() BrowserLinkMiddleWareUtil.FilterRequestHeader(requestHeader, connectionString); // Assert - Assert.Null(requestHeader.IfNoneMatch); + Assert.Equal(0, requestHeader.IfNoneMatch.Count); Assert.Null(requestHeader.IfModifiedSince); } @@ -372,7 +372,7 @@ public void FilterRequestHeader_NoPortInConnectionString() BrowserLinkMiddleWareUtil.FilterRequestHeader(requestHeader, connectionString); // Assert - Assert.Null(requestHeader.IfNoneMatch); + Assert.Equal(0, requestHeader.IfNoneMatch.Count); Assert.Null(requestHeader.IfModifiedSince); } @@ -392,7 +392,7 @@ public void FilterRequestHeader_NoPortInETag() BrowserLinkMiddleWareUtil.FilterRequestHeader(requestHeader, connectionString); // Assert - Assert.Null(requestHeader.IfNoneMatch); + Assert.Equal(0, requestHeader.IfNoneMatch.Count); Assert.Null(requestHeader.IfModifiedSince); } @@ -412,7 +412,7 @@ public void FilterRequestHeader_NoPortInEtagAndConnectionString() BrowserLinkMiddleWareUtil.FilterRequestHeader(requestHeader, connectionString); // Assert - Assert.Null(requestHeader.IfNoneMatch); + Assert.Equal(0, requestHeader.IfNoneMatch.Count); Assert.Null(requestHeader.IfModifiedSince); } } diff --git a/test/Microsoft.VisualStudio.Web.BrowserLink.Test/Microsoft.VisualStudio.Web.BrowserLink.Test.csproj b/test/Microsoft.VisualStudio.Web.BrowserLink.Test/Microsoft.VisualStudio.Web.BrowserLink.Test.csproj index ea78cf1..935261c 100644 --- a/test/Microsoft.VisualStudio.Web.BrowserLink.Test/Microsoft.VisualStudio.Web.BrowserLink.Test.csproj +++ b/test/Microsoft.VisualStudio.Web.BrowserLink.Test/Microsoft.VisualStudio.Web.BrowserLink.Test.csproj @@ -1,7 +1,8 @@  - $(StandardTestTfms) + + netcoreapp3.1 @@ -9,7 +10,7 @@ - + From 574611df7bb130684b8dea4890569f1429bd6fc0 Mon Sep 17 00:00:00 2001 From: Bill Hiebert Date: Wed, 23 Jun 2021 16:08:32 -0700 Subject: [PATCH 2/3] Add startup hook and hosting startup classes --- .../HostingStartup.cs | 30 +++++++++++++++++++ .../StartupHook.cs | 10 +++++++ 2 files changed, 40 insertions(+) create mode 100644 src/Microsoft.VisualStudio.Web.BrowserLink/HostingStartup.cs create mode 100644 src/Microsoft.VisualStudio.Web.BrowserLink/StartupHook.cs diff --git a/src/Microsoft.VisualStudio.Web.BrowserLink/HostingStartup.cs b/src/Microsoft.VisualStudio.Web.BrowserLink/HostingStartup.cs new file mode 100644 index 0000000..cb22308 --- /dev/null +++ b/src/Microsoft.VisualStudio.Web.BrowserLink/HostingStartup.cs @@ -0,0 +1,30 @@ +// 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 Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +[assembly: HostingStartup(typeof(Microsoft.VisualStudio.Web.BrowserLink.HostingStartup))] + +namespace Microsoft.VisualStudio.Web.BrowserLink +{ + internal sealed class HostingStartup : IHostingStartup, IStartupFilter + { + public void Configure(IWebHostBuilder builder) + { + builder.ConfigureServices(services => services.TryAddEnumerable(ServiceDescriptor.Singleton(this))); + } + + public Action Configure(Action next) + { + return app => + { + app.UseBrowserLink(); + next(app); + }; + } + } +} diff --git a/src/Microsoft.VisualStudio.Web.BrowserLink/StartupHook.cs b/src/Microsoft.VisualStudio.Web.BrowserLink/StartupHook.cs new file mode 100644 index 0000000..b45c3e8 --- /dev/null +++ b/src/Microsoft.VisualStudio.Web.BrowserLink/StartupHook.cs @@ -0,0 +1,10 @@ +// 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. + +internal class StartupHook +{ + public static void Initialize() + { + // This method exists to make startup hook load successfully. We do not need to do anything interesting here. + } +} From 7c724a26af62026d8feec9208a328a1378d18462 Mon Sep 17 00:00:00 2001 From: Bill Hiebert Date: Thu, 24 Jun 2021 10:29:26 -0700 Subject: [PATCH 3/3] Address CR feedback --- .../SendFilesWrapper.cs | 25 +++++++++++-------- ...t.VisualStudio.Web.BrowserLink.Test.csproj | 1 - 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/Microsoft.VisualStudio.Web.BrowserLink/SendFilesWrapper.cs b/src/Microsoft.VisualStudio.Web.BrowserLink/SendFilesWrapper.cs index aa8adb4..93209b8 100644 --- a/src/Microsoft.VisualStudio.Web.BrowserLink/SendFilesWrapper.cs +++ b/src/Microsoft.VisualStudio.Web.BrowserLink/SendFilesWrapper.cs @@ -5,13 +5,12 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; - namespace Microsoft.VisualStudio.Web.BrowserLink { internal class SendFilesWrapper : IHttpResponseBodyFeature { - private HttpResponse _response; - private IHttpResponseBodyFeature _wrapped; + private readonly HttpResponse _response; + private readonly IHttpResponseBodyFeature _wrapped; internal SendFilesWrapper(IHttpResponseBodyFeature wrapped, HttpResponse response) { @@ -19,18 +18,21 @@ internal SendFilesWrapper(IHttpResponseBodyFeature wrapped, HttpResponse respons _response = response; } - public Stream Stream => _wrapped.Stream; + public Stream Stream => _wrapped?.Stream; - public PipeWriter Writer => _wrapped.Writer; + public PipeWriter Writer => _wrapped?.Writer; - public Task CompleteAsync() + public async Task CompleteAsync() { - return _wrapped.CompleteAsync(); + if (_wrapped != null) + { + await _wrapped.CompleteAsync(); + } } public void DisableBuffering() { - _wrapped.DisableBuffering(); + _wrapped?.DisableBuffering(); } public async Task SendFileAsync(string path, long offset, long? count, CancellationToken cancellationToken = default) @@ -51,9 +53,12 @@ public async Task SendFileAsync(string path, long offset, long? count, Cancellat } } - public Task StartAsync(CancellationToken cancellationToken = default) + public async Task StartAsync(CancellationToken cancellationToken = default) { - return _wrapped.StartAsync(cancellationToken); + if (_wrapped != null) + { + await _wrapped.StartAsync(cancellationToken); + } } } } diff --git a/test/Microsoft.VisualStudio.Web.BrowserLink.Test/Microsoft.VisualStudio.Web.BrowserLink.Test.csproj b/test/Microsoft.VisualStudio.Web.BrowserLink.Test/Microsoft.VisualStudio.Web.BrowserLink.Test.csproj index 935261c..1e51612 100644 --- a/test/Microsoft.VisualStudio.Web.BrowserLink.Test/Microsoft.VisualStudio.Web.BrowserLink.Test.csproj +++ b/test/Microsoft.VisualStudio.Web.BrowserLink.Test/Microsoft.VisualStudio.Web.BrowserLink.Test.csproj @@ -1,7 +1,6 @@  - netcoreapp3.1