diff --git a/.spelling b/.spelling index 3afd5ed7ada..eee58d26366 100644 --- a/.spelling +++ b/.spelling @@ -106,6 +106,7 @@ brcrista breakpoint brianbunke britishben +brotli brucepay bugfix build.json diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index 0a84f60cd76..ef2d32746ed 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -584,11 +584,13 @@ Describe "Invoke-WebRequest tests" -Tags "Feature", "RequireAdminOnWindows" { # Perform the following operation for Invoke-WebRequest # gzip Returns gzip-encoded data. # deflate Returns deflate-encoded data. + # brotli Returns brotli-encoded data. # $dataEncodings = @("Chunked", "Compress", "Deflate", "GZip", "Identity") # Note: These are the supported options, but we do not have a web service to test them all. It "Invoke-WebRequest supports request that returns -encoded data." -TestCases @( @{ DataEncoding = "gzip" } @{ DataEncoding = "deflate" } + @{ DataEncoding = "brotli" } ) { param($dataEncoding) $uri = Get-WebListenerUrl -Test 'Compression' -TestValue $dataEncoding @@ -2228,11 +2230,13 @@ Describe "Invoke-RestMethod tests" -Tags "Feature", "RequireAdminOnWindows" { # Perform the following operation for Invoke-RestMethod # gzip Returns gzip-encoded data. # deflate Returns deflate-encoded data. + # brotli Returns brotli-encoded data. # $dataEncodings = @("Chunked", "Compress", "Deflate", "GZip", "Identity") # Note: These are the supported options, but we do not have a web service to test them all. It "Invoke-RestMethod supports request that returns -encoded data." -TestCases @( @{ DataEncoding = "gzip" } @{ DataEncoding = "deflate" } + @{ DataEncoding = "brotli" } ) { param($dataEncoding) $uri = Get-WebListenerUrl -Test 'Compression' -TestValue $dataEncoding diff --git a/test/tools/WebListener/BrotliFilter.cs b/test/tools/WebListener/BrotliFilter.cs new file mode 100644 index 00000000000..510bd1da2e3 --- /dev/null +++ b/test/tools/WebListener/BrotliFilter.cs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.IO; +using System.IO.Compression; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Filters; + +namespace mvc.Controllers +{ + internal sealed class BrotliFilter : ResultFilterAttribute + { + public override async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next) + { + var httpContext = context.HttpContext; + using (var memoryStream = new MemoryStream()) + { + var responseStream = httpContext.Response.Body; + httpContext.Response.Body = memoryStream; + + await next(); + + using (var compressedStream = new BrotliStream(responseStream, CompressionLevel.Fastest)) + { + httpContext.Response.Headers.Add("Content-Encoding", new[] { "br" }); + memoryStream.Seek(0, SeekOrigin.Begin); + await memoryStream.CopyToAsync(compressedStream); + } + } + } + } +} diff --git a/test/tools/WebListener/Controllers/CompressionController.cs b/test/tools/WebListener/Controllers/CompressionController.cs index f8fcd0c4d80..4043c774b79 100644 --- a/test/tools/WebListener/Controllers/CompressionController.cs +++ b/test/tools/WebListener/Controllers/CompressionController.cs @@ -37,6 +37,14 @@ public JsonResult Deflate() return getController.Index(); } + [BrotliFilter] + public JsonResult Brotli() + { + var getController = new GetController(); + getController.ControllerContext = this.ControllerContext; + return getController.Index(); + } + public IActionResult Error() { return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); diff --git a/test/tools/WebListener/README.md b/test/tools/WebListener/README.md index f4d84c3bb18..111a3b86240 100644 --- a/test/tools/WebListener/README.md +++ b/test/tools/WebListener/README.md @@ -143,6 +143,27 @@ Response when certificate is not provided in request: } ``` +### /Compression/Brotli/ + +Returns the same results as the Get test with brotli compression. + +```powershell +$uri = Get-WebListenerUrl -Test 'Compression' -TestValue 'Brotli' +Invoke-RestMethod -Uri $uri +``` + +```json +{ + "args": {}, + "origin": "127.0.0.1", + "headers": { + "User-Agent": "Mozilla/5.0 (Windows NT; Microsoft Windows 10.0.15063 ; en-US) PowerShell/6.0.0", + "Host": "localhost:8083" + }, + "url": "http://localhost:8083/Compression/Brotli" +} +``` + ### /Compression/Deflate/ Returns the same results as the Get test with deflate compression. diff --git a/test/tools/WebListener/Views/Home/Index.cshtml b/test/tools/WebListener/Views/Home/Index.cshtml index 78155781884..fb7e6746161 100644 --- a/test/tools/WebListener/Views/Home/Index.cshtml +++ b/test/tools/WebListener/Views/Home/Index.cshtml @@ -5,6 +5,7 @@
  • /Auth/Negotiate/ - Negotiate Authentication
  • /Auth/NTLM/ - NTLM Authentication
  • /Cert/ - Client Certificate Details
  • +
  • /Compression/Brotli/ - Returns brotli compressed response
  • /Compression/Deflate/ - Returns deflate compressed response
  • /Compression/Gzip/ - Returns gzip compressed response
  • /Delay/{seconds} - Delays response for seconds seconds.