From 1d59bc8de82c0e05e4b6c9c27ef5a34b97f149c1 Mon Sep 17 00:00:00 2001 From: markekraus Date: Wed, 2 Aug 2017 20:00:00 -0500 Subject: [PATCH 1/2] Add UserAgent to SkipHeaderValidation --- .../CoreCLR/WebRequestPSCmdlet.CoreClr.cs | 10 ++- .../WebCmdlets.Tests.ps1 | 88 +++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/WebRequestPSCmdlet.CoreClr.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/WebRequestPSCmdlet.CoreClr.cs index bbe96fa6641..b8445dad74f 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/WebRequestPSCmdlet.CoreClr.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/WebRequestPSCmdlet.CoreClr.cs @@ -283,7 +283,15 @@ internal virtual HttpRequestMessage GetRequest(Uri uri, bool stripAuthorization) } else { - request.Headers.Add(HttpKnownHeaderNames.UserAgent, WebSession.UserAgent); + if (SkipHeaderValidation) + { + request.Headers.TryAddWithoutValidation(HttpKnownHeaderNames.UserAgent, WebSession.UserAgent); + } + else + { + request.Headers.Add(HttpKnownHeaderNames.UserAgent, WebSession.UserAgent); + } + } // Set 'Keep-Alive' to false. This means set the Connection to 'Close'. diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index f1d2097807d..fb756cbd206 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -227,6 +227,44 @@ function ExecuteRequestWithCustomHeaders return $result } +# This function calls either Invoke-WebRequest or Invoke-RestMethod with the given uri +# using the custom UserAgent and the optional SkipHeaderValidation switch. +function ExecuteRequestWithCustomUserAgent { + param ( + [Parameter(Mandatory)] + [string] + $Uri, + + [ValidateSet('Invoke-WebRequest', 'Invoke-RestMethod')] + [string] $Cmdlet = 'Invoke-WebRequest', + + [Parameter(Mandatory)] + [ValidateNotNull()] + [string] $UserAgent, + + [switch] $SkipHeaderValidation + ) + $result = [PSObject]@{Output = $null; Error = $null; Content = $null} + + try { + if ($Cmdlet -eq 'Invoke-WebRequest') { + $result.Output = Invoke-WebRequest -Uri $Uri -TimeoutSec 5 -UserAgent $UserAgent -SkipHeaderValidation:$SkipHeaderValidation.IsPresent + $result.Content = $result.Output.Content | ConvertFrom-Json + } + else { + $result.Output = Invoke-RestMethod -Uri $Uri -TimeoutSec 5 -UserAgent $UserAgent -SkipHeaderValidation:$SkipHeaderValidation.IsPresent + # NOTE: $result.Output should already be a PSObject (Invoke-RestMethod converts the returned json automatically) + # so simply reference $result.Output + $result.Content = $result.Output + } + } + catch { + $result.Error = $_ + } + + return $result +} + <# Defines the list of redirect codes to test as well as the expected Method when the redirection is handled. @@ -732,6 +770,31 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" { $response.Content.Headers -contains "If-Match" | Should Be $true } + It "Verifies Invoke-WebRequest default UserAgent handling with no errors" { + $UserAgent = [Microsoft.PowerShell.Commands.PSUserAgent]::InternetExplorer + $response = ExecuteRequestWithCustomUserAgent -Uri "http://localhost:8081/PowerShell?test=echo" -UserAgent $UserAgent -Cmdlet "Invoke-WebRequest" + + $response.Error | Should BeNullOrEmpty + $response.Content.Headers.'User-Agent' | Should Match $UserAgent + } + + It "Verifies Invoke-WebRequest default UserAgent handling reports an error is returned for an invalid UserAgent value" { + $UserAgent = 'Invalid:Agent' + $response = ExecuteRequestWithCustomUserAgent -Uri "http://localhost:8081/PowerShell?test=echo" -UserAgent $UserAgent -Cmdlet "Invoke-WebRequest" + + $response.Error | Should Not BeNullOrEmpty + $response.Error.FullyQualifiedErrorId | Should Be "System.FormatException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand" + $response.Error.Exception.Message | Should Be "The format of value 'Invalid:Agent' is invalid." + } + + It "Verifies Invoke-WebRequest UserAgent handling does not report an error when using -SkipHeaderValidation" { + $UserAgent = 'Invalid:Agent' + $response = ExecuteRequestWithCustomUserAgent -Uri "http://localhost:8081/PowerShell?test=echo" -UserAgent $UserAgent -SkipHeaderValidation -Cmdlet "Invoke-WebRequest" + + $response.Error | Should BeNullOrEmpty + $response.Content.Headers.'User-Agent' | Should Match $UserAgent + } + #endregion SkipHeaderVerification Tests BeforeEach { @@ -1223,6 +1286,31 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" { $response.Content.Headers -contains "If-Match" | Should Be $true } + It "Verifies Invoke-RestMethod default UserAgent handling with no errors" { + $UserAgent = [Microsoft.PowerShell.Commands.PSUserAgent]::InternetExplorer + $response = ExecuteRequestWithCustomUserAgent -Uri "http://localhost:8081/PowerShell?test=echo" -UserAgent $UserAgent -Cmdlet "Invoke-RestMethod" + + $response.Error | Should BeNullOrEmpty + $response.Content.Headers.'User-Agent' | Should Match $UserAgent + } + + It "Verifies Invoke-RestMethod default UserAgent handling reports an error is returned for an invalid UserAgent value" { + $UserAgent = 'Invalid:Agent' + $response = ExecuteRequestWithCustomUserAgent -Uri "http://localhost:8081/PowerShell?test=echo" -UserAgent $UserAgent -Cmdlet "Invoke-RestMethod" + + $response.Error | Should Not BeNullOrEmpty + $response.Error.FullyQualifiedErrorId | Should Be "System.FormatException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand" + $response.Error.Exception.Message | Should Be "The format of value 'Invalid:Agent' is invalid." + } + + It "Verifies Invoke-RestMethod UserAgent handling does not report an error when using -SkipHeaderValidation" { + $UserAgent = 'Invalid:Agent' + $response = ExecuteRequestWithCustomUserAgent -Uri "http://localhost:8081/PowerShell?test=echo" -UserAgent $UserAgent -SkipHeaderValidation -Cmdlet "Invoke-RestMethod" + + $response.Error | Should BeNullOrEmpty + $response.Content.Headers.'User-Agent' | Should Match $UserAgent + } + #endregion SkipHeaderVerification tests BeforeEach { From 97c3f440aa91672f6df01de8b3aadc6ed1de85e7 Mon Sep 17 00:00:00 2001 From: markekraus Date: Fri, 4 Aug 2017 04:05:29 -0500 Subject: [PATCH 2/2] Add Splatting to ExecuteRequestWithCustomUserAgent --- .../Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index fb756cbd206..ba5fbd9277b 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -247,12 +247,18 @@ function ExecuteRequestWithCustomUserAgent { $result = [PSObject]@{Output = $null; Error = $null; Content = $null} try { + $Params = @{ + Uri = $Uri + TimeoutSec = 5 + UserAgent = $UserAgent + SkipHeaderValidation = $SkipHeaderValidation.IsPresent + } if ($Cmdlet -eq 'Invoke-WebRequest') { - $result.Output = Invoke-WebRequest -Uri $Uri -TimeoutSec 5 -UserAgent $UserAgent -SkipHeaderValidation:$SkipHeaderValidation.IsPresent + $result.Output = Invoke-WebRequest @Params $result.Content = $result.Output.Content | ConvertFrom-Json } else { - $result.Output = Invoke-RestMethod -Uri $Uri -TimeoutSec 5 -UserAgent $UserAgent -SkipHeaderValidation:$SkipHeaderValidation.IsPresent + $result.Output = Invoke-RestMethod @Params # NOTE: $result.Output should already be a PSObject (Invoke-RestMethod converts the returned json automatically) # so simply reference $result.Output $result.Content = $result.Output