From 75b6f542e01b56958288dfedc9072b2dc9606808 Mon Sep 17 00:00:00 2001 From: markekraus Date: Mon, 7 Aug 2017 18:17:31 -0500 Subject: [PATCH 1/4] [Feature] Add Support for Content Headers --- .../CoreCLR/ContentHelper.CoreClr.cs | 26 ++++++++++++++++--- .../CoreCLR/WebResponseObject.CoreClr.cs | 6 +++++ .../WebCmdlets.Tests.ps1 | 18 +++++++++++++ 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/ContentHelper.CoreClr.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/ContentHelper.CoreClr.cs index 261b4c98b7e..7d32b12d1e7 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/ContentHelper.CoreClr.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/ContentHelper.CoreClr.cs @@ -7,6 +7,7 @@ using System.Text; using System.Linq; using System.Net.Http; +using System.Net.Http.Headers; namespace Microsoft.PowerShell.Commands { @@ -37,11 +38,30 @@ internal static StringBuilder GetRawContentHeader(HttpResponseMessage response) raw.AppendFormat("{0} {1} {2}", protocol, statusCode, statusDescription); raw.AppendLine(); } + + HttpHeaders[] headerCollections = + { + response.Headers, + response.Content == null ? null : response.Content.Headers + }; - foreach (var entry in response.Headers) + foreach(var headerCollection in headerCollections) { - raw.AppendFormat("{0}: {1}", entry.Key, entry.Value.FirstOrDefault()); - raw.AppendLine(); + if(headerCollection == null) + { + continue; + } + foreach (var header in headerCollection) + { + // Headers may have multiple entries with different values + foreach (var headerValue in header.Value) + { + raw.Append(header.Key); + raw.Append(": "); + raw.Append(headerValue); + raw.AppendLine(); + } + } } raw.AppendLine(); diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/WebResponseObject.CoreClr.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/WebResponseObject.CoreClr.cs index 79fc400af7f..2637dd09b10 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/WebResponseObject.CoreClr.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/WebResponseObject.CoreClr.cs @@ -36,6 +36,12 @@ public Dictionary> Headers { headers[entry.Key] = entry.Value; } + if(BaseResponse.Content != null){ + foreach (var entry in BaseResponse.Content.Headers) + { + headers[entry.Key] = entry.Value; + } + } return headers; } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index 638f94f1dd0..1e44a6559e0 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -1070,6 +1070,24 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" { #endregion charset encoding tests + It "Verifies Invoke-WebRequest includes Content headers in Headers property" { + $command = "Invoke-WebRequest -Uri 'http://httpbin.org/get'" + $result = ExecuteWebCommand -command $command + ValidateResponse $result + + $result.Output.Headers.'Content-Type' | Should Not BeNullOrEmpty + $result.Output.Headers.'Content-Length' | Should Not BeNullOrEmpty + } + + It "Verifies Invoke-WebRequest includes Content headers in RawContent property" { + $command = "Invoke-WebRequest -Uri 'http://httpbin.org/get'" + $result = ExecuteWebCommand -command $command + ValidateResponse $result + + $result.Output.RawContent | Should Match 'Content-Type:' + $result.Output.RawContent | Should Match 'Content-Length:' + } + BeforeEach { if ($env:http_proxy) { $savedHttpProxy = $env:http_proxy From 5e3854af95d5b148b9116477aca8221b04b064e6 Mon Sep 17 00:00:00 2001 From: Mark Kraus Date: Thu, 17 Aug 2017 13:35:00 -0500 Subject: [PATCH 2/4] Format changes --- .../utility/WebCmdlet/CoreCLR/ContentHelper.CoreClr.cs | 4 ++-- .../utility/WebCmdlet/CoreCLR/WebResponseObject.CoreClr.cs | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/ContentHelper.CoreClr.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/ContentHelper.CoreClr.cs index 7d32b12d1e7..4268bc63a98 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/ContentHelper.CoreClr.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/ContentHelper.CoreClr.cs @@ -45,9 +45,9 @@ internal static StringBuilder GetRawContentHeader(HttpResponseMessage response) response.Content == null ? null : response.Content.Headers }; - foreach(var headerCollection in headerCollections) + foreach (var headerCollection in headerCollections) { - if(headerCollection == null) + if (headerCollection == null) { continue; } diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/WebResponseObject.CoreClr.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/WebResponseObject.CoreClr.cs index 2637dd09b10..9e4b52bfd0f 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/WebResponseObject.CoreClr.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/WebResponseObject.CoreClr.cs @@ -36,7 +36,8 @@ public Dictionary> Headers { headers[entry.Key] = entry.Value; } - if(BaseResponse.Content != null){ + if (BaseResponse.Content != null) + { foreach (var entry in BaseResponse.Content.Headers) { headers[entry.Key] = entry.Value; From dfef828fe9389a2198d06e609fda7f6fef623ecd Mon Sep 17 00:00:00 2001 From: markekraus Date: Fri, 18 Aug 2017 05:35:34 -0500 Subject: [PATCH 3/4] [feature] httplistener multiheader support & native contet header tests --- .../WebCmdlets.Tests.ps1 | 33 +++++++++++++++---- .../Modules/HttpListener/HttpListener.psm1 | 13 +++++++- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index 1e44a6559e0..fc65586af6e 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -1070,24 +1070,45 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" { #endregion charset encoding tests + #region Content Header Inclusion It "Verifies Invoke-WebRequest includes Content headers in Headers property" { - $command = "Invoke-WebRequest -Uri 'http://httpbin.org/get'" + $uri = "http://localhost:8080/PowerShell?test=response&contenttype=text/plain&output=OK" + $command = "Invoke-WebRequest -Uri '$uri'" $result = ExecuteWebCommand -command $command ValidateResponse $result - $result.Output.Headers.'Content-Type' | Should Not BeNullOrEmpty - $result.Output.Headers.'Content-Length' | Should Not BeNullOrEmpty + $result.Output.Headers.'Content-Type' | Should Be 'text/plain' + $result.Output.Headers.'Content-Length' | Should Be 2 } It "Verifies Invoke-WebRequest includes Content headers in RawContent property" { - $command = "Invoke-WebRequest -Uri 'http://httpbin.org/get'" + $uri = "http://localhost:8080/PowerShell?test=response&contenttype=text/plain&output=OK" + $command = "Invoke-WebRequest -Uri '$uri'" $result = ExecuteWebCommand -command $command ValidateResponse $result - $result.Output.RawContent | Should Match 'Content-Type:' - $result.Output.RawContent | Should Match 'Content-Length:' + $result.Output.RawContent | Should Match ([regex]::Escape('Content-Type: text/plain')) + $result.Output.RawContent | Should Match ([regex]::Escape('Content-Length: 2')) } + It "Verifies Invoke-WebRequest Supports Multiple response headers with same name" { + $headers = @{ + 'X-Fake-Header' = 'testvalue01','testvalue02' + } | ConvertTo-Json -Compress + $uri = "http://localhost:8080/PowerShell?test=response&contenttype=text/plain&output=OK&headers=$headers" + $command = "Invoke-WebRequest -Uri '$uri'" + $result = ExecuteWebCommand -command $command + ValidateResponse $result + + $result.Output.Headers.'X-Fake-Header'.Count | Should Be 2 + $result.Output.Headers.'X-Fake-Header'.Contains('testvalue01') | Should Be $True + $result.Output.Headers.'X-Fake-Header'.Contains('testvalue02') | Should Be $True + $result.Output.RawContent | Should Match ([regex]::Escape('X-Fake-Header: testvalue01')) + $result.Output.RawContent | Should Match ([regex]::Escape('X-Fake-Header: testvalue02')) + } + + #endregion Content Header Inclusion + BeforeEach { if ($env:http_proxy) { $savedHttpProxy = $env:http_proxy diff --git a/test/tools/Modules/HttpListener/HttpListener.psm1 b/test/tools/Modules/HttpListener/HttpListener.psm1 index 8fc048c8cc7..e1218d36ccb 100644 --- a/test/tools/Modules/HttpListener/HttpListener.psm1 +++ b/test/tools/Modules/HttpListener/HttpListener.psm1 @@ -133,6 +133,14 @@ Function Start-HTTPListener { $statusCode = $queryItems["statuscode"] $contentType = $queryItems["contenttype"] $output = $queryItems["output"] + if ($queryItems['headers']) + { + $headerCollection = $queryItems['headers'] | ConvertFrom-Json + foreach ($header in $headerCollection.psobject.Properties.name) + { + $outputHeader.add($header,$headerCollection.$header) + } + } } # Echo the request as the output. @@ -284,7 +292,10 @@ Function Start-HTTPListener { $response.Headers.Clear() foreach ($header in $outputHeader.Keys) { - $response.Headers.Add($header, $outputHeader[$header]) + foreach ($headerValue in $outputHeader.$header) + { + $response.Headers.Add($header, $headerValue) + } } if ($null -ne $output) From 07d7b3d4234ec3ae03a85083efa5b1c750b00623 Mon Sep 17 00:00:00 2001 From: markekraus Date: Fri, 18 Aug 2017 13:21:13 -0500 Subject: [PATCH 4/4] [Feature] add comments --- test/tools/Modules/HttpListener/HttpListener.psm1 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/tools/Modules/HttpListener/HttpListener.psm1 b/test/tools/Modules/HttpListener/HttpListener.psm1 index e1218d36ccb..b682235617a 100644 --- a/test/tools/Modules/HttpListener/HttpListener.psm1 +++ b/test/tools/Modules/HttpListener/HttpListener.psm1 @@ -133,6 +133,12 @@ Function Start-HTTPListener { $statusCode = $queryItems["statuscode"] $contentType = $queryItems["contenttype"] $output = $queryItems["output"] + + # Pass a JSON collection to the 'headers' field + # /PowerShell?test=response&headers={"Pragma":"no-cache","X-Fake-Header":["testvalue01","testvalue02"]} + # In PowerShell: + # $headers = @{Pragma='no-cache';'X-Fake-Header'='testvalue01','testvalue02'} | ConvertTo-Json -Compress + # $uri = "http://localhost:8080/PowerShell?test=response&headers=$headers" if ($queryItems['headers']) { $headerCollection = $queryItems['headers'] | ConvertFrom-Json