diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index 86e239cfdfe..ddf9afd0c2d 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -592,29 +592,22 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" { # gzip Returns gzip-encoded data. # deflate Returns deflate-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. - # $dataEncodings = @("gzip", "deflate") --> Currently there is a bug for deflate encoding. Please see '7976639:Invoke-WebRequest does not support -TransferEncoding deflate' for more info. - $dataEncodings = @("gzip") - foreach ($data in $dataEncodings) - { - It "Invoke-WebRequest supports request that returns $data-encoded data." { - - $command = "Invoke-WebRequest -Uri http://httpbin.org/$data -TimeoutSec 5" + # 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"} + ) { + param($dataEncoding) + $uri = Get-WebListenerUrl -Test 'Compression' -TestValue $dataEncoding + $command = "Invoke-WebRequest -Uri '$uri'" - $result = ExecuteWebCommand -command $command - ValidateResponse -response $result + $result = ExecuteWebCommand -command $command + ValidateResponse -response $result - # Validate response content - $jsonContent = $result.Output.Content | ConvertFrom-Json - if ($data -eq "gzip") - { - $jsonContent.gzipped | Should Match $true - } - else - { - $jsonContent.deflated | Should Match $true - } - } + # Validate response content + $result.Output.Headers.'Content-Encoding'[0] | Should BeExactly $dataEncoding + $jsonContent = $result.Output.Content | ConvertFrom-Json + $jsonContent.Headers.Host | Should BeExactly $uri.Authority } # Perform the following operation for Invoke-WebRequest using the following content types: "text/plain", "application/xml", "application/xml" @@ -1433,27 +1426,18 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" { # gzip Returns gzip-encoded data. # deflate Returns deflate-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. - # $dataEncodings = @("gzip", "deflate") --> Currently there is a bug for deflate encoding. Please see '7976639:Invoke-RestMethod does not support -TransferEncoding deflate' for more info. - $dataEncodings = @("gzip") - foreach ($data in $dataEncodings) - { - It "Invoke-RestMethod supports request that returns $data-encoded data." { - - $command = "Invoke-RestMethod -Uri http://httpbin.org/$data -TimeoutSec 5" - - $result = ExecuteWebCommand -command $command + # 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"} + ) { + param($dataEncoding) + $uri = Get-WebListenerUrl -Test 'Compression' -TestValue $dataEncoding + $result = Invoke-RestMethod -Uri $uri -ResponseHeadersVariable 'headers' - # Validate response - if ($data -eq "gzip") - { - $result.Output.gzipped | Should Match $true - } - else - { - $result.Output.deflated | Should Match $true - } - } + # Validate response content + $headers.'Content-Encoding'[0] | Should BeExactly $dataEncoding + $result.Headers.Host | Should BeExactly $uri.Authority } # Perform the following operation for Invoke-RestMethod using the following content types: "text/plain", "application/xml", "application/xml" diff --git a/test/tools/Modules/WebListener/WebListener.psm1 b/test/tools/Modules/WebListener/WebListener.psm1 index 87a5899d300..7e8b4eea999 100644 --- a/test/tools/Modules/WebListener/WebListener.psm1 +++ b/test/tools/Modules/WebListener/WebListener.psm1 @@ -114,6 +114,7 @@ function Get-WebListenerUrl { [switch]$Https, [ValidateSet( 'Cert', + 'Compression', 'Delay', 'Encoding', 'Get', diff --git a/test/tools/WebListener/Controllers/CompressionController.cs b/test/tools/WebListener/Controllers/CompressionController.cs new file mode 100644 index 00000000000..b715f5db6c4 --- /dev/null +++ b/test/tools/WebListener/Controllers/CompressionController.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using mvc.Models; + +namespace mvc.Controllers +{ + public class CompressionController : Controller + { + public ActionResult Index() + { + string url = "/Compression/Gzip"; + ViewData["Url"] = url; + Response.Redirect(url, false); + return View("~/Views/Redirect/Index.cshtml"); + } + + [GzipFilter] + public JsonResult Gzip() + { + var getController = new GetController(); + getController.ControllerContext = this.ControllerContext; + return getController.Index(); + } + + [DeflateFilter] + public JsonResult Deflate() + { + 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/DeflateFilter.cs b/test/tools/WebListener/DeflateFilter.cs new file mode 100644 index 00000000000..beab309b007 --- /dev/null +++ b/test/tools/WebListener/DeflateFilter.cs @@ -0,0 +1,30 @@ +using System; +using System.IO; +using System.IO.Compression; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Filters; + +namespace mvc.Controllers +{ + internal sealed class DeflateFilter : 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 DeflateStream(responseStream, CompressionLevel.Fastest)) + { + httpContext.Response.Headers.Add("Content-Encoding", new [] { "deflate" }); + memoryStream.Seek(0, SeekOrigin.Begin); + await memoryStream.CopyToAsync(compressedStream); + } + } + } + } +} diff --git a/test/tools/WebListener/GzipFilter.cs b/test/tools/WebListener/GzipFilter.cs new file mode 100644 index 00000000000..c15976beb7f --- /dev/null +++ b/test/tools/WebListener/GzipFilter.cs @@ -0,0 +1,30 @@ +using System; +using System.IO; +using System.IO.Compression; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Filters; + +namespace mvc.Controllers +{ + internal sealed class GzipFilter : 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 GZipStream(responseStream, CompressionLevel.Fastest)) + { + httpContext.Response.Headers.Add("Content-Encoding", new [] { "gzip" }); + memoryStream.Seek(0, SeekOrigin.Begin); + await memoryStream.CopyToAsync(compressedStream); + } + } + } + } +} diff --git a/test/tools/WebListener/README.md b/test/tools/WebListener/README.md index 802b4cc4fc9..6892000d954 100644 --- a/test/tools/WebListener/README.md +++ b/test/tools/WebListener/README.md @@ -59,6 +59,46 @@ Response when certificate is not provided in request: } ``` +## /Compression/Deflate/ +Returns the same results as the Get test with deflate compression. + +```powershell +$uri = Get-WebListenerUrl -Test 'Compression' -TestValue 'Deflate' +Invoke-RestMethod -Uri $uri -Headers $headers +``` + +```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/Deflate" +} +``` + +## /Compression/Gzip/ +Returns the same results as the Get test with gzip compression. + +```powershell +$uri = Get-WebListenerUrl -Test 'Compression' -TestValue 'Gzip' +Invoke-RestMethod -Uri $uri -Headers $headers +``` + +```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/Gzip" +} +``` + ## /Delay/ Returns the same results as the Get test. If a number is supplied, the server will wait that many seconds before returning a response. This can be used to test timeouts. diff --git a/test/tools/WebListener/Views/Home/Index.cshtml b/test/tools/WebListener/Views/Home/Index.cshtml index 7b4669ce334..8b914686652 100644 --- a/test/tools/WebListener/Views/Home/Index.cshtml +++ b/test/tools/WebListener/Views/Home/Index.cshtml @@ -2,6 +2,8 @@