From 1d31ab4fff8254777d475fbb30b3dfe09543a07e Mon Sep 17 00:00:00 2001 From: Rune Darrud Date: Tue, 28 Mar 2017 21:25:13 +0200 Subject: [PATCH] Add option -NoProxy to WebCmdlet --- .../Common/InvokeRestMethodCommand.Common.cs | 4 +- .../Common/WebRequestPSCmdlet.Common.cs | 24 ++- .../CoreCLR/WebRequestPSCmdlet.CoreClr.cs | 12 +- .../FullClr/WebRequestPSCmdlet.FullClr.cs | 10 +- .../WebCmdlets.Tests.ps1 | 161 +++++++++++++++++- 5 files changed, 201 insertions(+), 10 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs index 0614147443a..da58abfc054 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs @@ -17,6 +17,7 @@ public partial class InvokeRestMethodCommand /// gets or sets the parameter Method /// [Parameter(ParameterSetName = "StandardMethod")] + [Parameter(ParameterSetName = "StandardMethodNoProxy")] public override WebRequestMethod Method { get { return base.Method; } @@ -26,7 +27,8 @@ public override WebRequestMethod Method /// /// gets or sets the parameter CustomMethod /// - [Parameter(ParameterSetName = "CustomMethod")] + [Parameter(Mandatory=true,ParameterSetName = "CustomMethod")] + [Parameter(Mandatory=true,ParameterSetName = "CustomMethodNoProxy")] [Alias("CM")] [ValidateNotNullOrEmpty] public override string CustomMethod diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs index 560aa57a1e5..e9eb8f77e56 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs @@ -148,6 +148,7 @@ public virtual int MaximumRedirection /// gets or sets the Method property /// [Parameter(ParameterSetName = "StandardMethod")] + [Parameter(ParameterSetName = "StandardMethodNoProxy")] public virtual WebRequestMethod Method { get { return _method; } @@ -158,7 +159,8 @@ public virtual WebRequestMethod Method /// /// gets or sets the CustomMethod property /// - [Parameter(ParameterSetName = "CustomMethod")] + [Parameter(Mandatory=true,ParameterSetName = "CustomMethod")] + [Parameter(Mandatory=true,ParameterSetName = "CustomMethodNoProxy")] [Alias("CM")] [ValidateNotNullOrEmpty] public virtual string CustomMethod @@ -170,25 +172,39 @@ public virtual string CustomMethod #endregion + #region NoProxy + + /// + /// gets or sets the NoProxy property + /// + [Parameter(Mandatory=true,ParameterSetName = "CustomMethodNoProxy")] + [Parameter(Mandatory=true,ParameterSetName = "StandardMethodNoProxy")] + public virtual SwitchParameter NoProxy { get; set; } + + #endregion + #region Proxy /// /// gets or sets the Proxy property /// - [Parameter] + [Parameter(ParameterSetName = "StandardMethod")] + [Parameter(ParameterSetName = "CustomMethod")] public virtual Uri Proxy { get; set; } /// /// gets or sets the ProxyCredential property /// - [Parameter] + [Parameter(ParameterSetName = "StandardMethod")] + [Parameter(ParameterSetName = "CustomMethod")] [Credential] public virtual PSCredential ProxyCredential { get; set; } /// /// gets or sets the ProxyUseDefaultCredentials property /// - [Parameter] + [Parameter(ParameterSetName = "StandardMethod")] + [Parameter(ParameterSetName = "CustomMethod")] public virtual SwitchParameter ProxyUseDefaultCredentials { get; set; } #endregion 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 3699a991c2f..47e83f69775 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 @@ -105,7 +105,11 @@ internal virtual HttpClient GetHttpClient() handler.Credentials = WebSession.Credentials; } - if (WebSession.Proxy != null) + if (NoProxy) + { + handler.UseProxy = false; + } + else if (WebSession.Proxy != null) { handler.Proxy = WebSession.Proxy; } @@ -155,13 +159,17 @@ internal virtual HttpRequestMessage GetRequest(Uri uri) { Uri requestUri = PrepareUri(uri); HttpMethod httpMethod = null; - + switch (ParameterSetName) { + case "StandardMethodNoProxy": + goto case "StandardMethod"; case "StandardMethod": // set the method if the parameter was provided httpMethod = GetHttpMethod(Method); break; + case "CustomMethodNoProxy": + goto case "CustomMethod"; case "CustomMethod": if (!string.IsNullOrEmpty(CustomMethod)) { diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/FullClr/WebRequestPSCmdlet.FullClr.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/FullClr/WebRequestPSCmdlet.FullClr.cs index 8922b9dd40a..c1b65ba3ee3 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/FullClr/WebRequestPSCmdlet.FullClr.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/FullClr/WebRequestPSCmdlet.FullClr.cs @@ -79,13 +79,19 @@ internal virtual WebRequest GetRequest(Uri uri) request.Credentials = WebSession.Credentials; } - if (null != WebSession.Proxy) + if (NoProxy) + { + handler.UseProxy = false; + } + else if (WebSession.Proxy != null) { request.Proxy = WebSession.Proxy; } switch (ParameterSetName) { + case "StandardMethodNoProxy": + goto case "StandardMethod"; case "StandardMethod": if (WebRequestMethod.Default != Method) { @@ -93,6 +99,8 @@ internal virtual WebRequest GetRequest(Uri uri) request.Method = Method.ToString().ToUpperInvariant(); } break; + case "CustomMethodNoProxy": + goto case "CustomMethod"; case "CustomMethod": // set the method if the parameter was provided request.Method = CustomMethod.ToUpperInvariant(); diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index d2d562ae234..041953be9c5 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -247,7 +247,66 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" { $result = ExecuteWebCommand -command $command $result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand" + } + + It "Validate Invoke-WebRequest error with -Proxy and -NoProxy option" { + + $command = "Invoke-WebRequest -Uri http://httpbin.org/delay/:10 -Proxy 'http://localhost:8080' -NoProxy -TimeoutSec 2" + + $result = ExecuteWebCommand -command $command + $result.Error.FullyQualifiedErrorId | Should Be "AmbiguousParameterSet,Microsoft.PowerShell.Commands.InvokeWebRequestCommand" + } + + $testCase = @( + @{ proxy_address = "http://localhost:8080"; name = 'http_proxy'; protocol = 'http' } + @{ proxy_address = "http://localhost:8080"; name = 'https_proxy'; protocol = 'https' } + ) + + It "Validate Invoke-WebRequest error with -Proxy option set - ''" -TestCases $testCase { + param($proxy_address, $name, $protocol) + + $command = "Invoke-WebRequest -Uri '${protocol}://httpbin.org/delay/:5' -TimeoutSec 5 -Proxy '${proxy_address}'" + + $result = ExecuteWebCommand -command $command + $result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand" + } + + It "Validate Invoke-WebRequest error with environment proxy set - ''" -TestCases $testCase { + param($proxy_address, $name, $protocol) + + # Configure the environment variable. + New-Item -Name ${name} -Value ${proxy_address} -ItemType Variable -Path Env: -Force + + $command = "Invoke-WebRequest -Uri '${protocol}://httpbin.org/delay/:5' -TimeoutSec 5" + + $result = ExecuteWebCommand -command $command + $result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand" + } + + It "Validate Invoke-WebRequest returns User-Agent where -NoProxy with envirionment proxy set - ''" -TestCases $testCase { + param($proxy_address, $name, $protocol) + # Configure the environment variable. + New-Item -Name ${name} -Value ${proxy_address} -ItemType Variable -Path Env: -Force + + $command = "Invoke-WebRequest -Uri '${protocol}://httpbin.org/headers' -TimeoutSec 5 -NoProxy" + + $result = ExecuteWebCommand -command $command + ValidateResponse -response $result + + # Validate response content + $jsonContent = $result.Output.Content | ConvertFrom-Json + $jsonContent.headers.'Accept-Encoding' | Should Match "gzip, ?deflate" + $jsonContent.headers.Host | Should Match "httpbin.org" + $jsonContent.headers.'User-Agent' | Should Match "WindowsPowerShell" + } + + It "Invoke-WebRequest validate timeout option" { + + $command = "Invoke-WebRequest -Uri http://httpbin.org/delay/:5 -TimeoutSec 10" + + $result = ExecuteWebCommand -command $command + $result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand" } # Perform the following operation for Invoke-WebRequest @@ -451,6 +510,32 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" { $result.Error.ErrorDetails.Message | Should Match $result.Error.Exception.InnerException.Message $result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand" } + + BeforeEach { + if ($env:http_proxy) { + $savedHttpProxy = $env:http_proxy + $copiedHttpProxy = $true + } + + if ($env:https_proxy) { + $savedHttpsProxy = $env:https_proxy + $copiedHttpsProxy = $true + } + } + + AfterEach { + if ($copiedHttpProxy) { + $env:http_proxy = $savedHttpProxy + } else { + $env:http_proxy = $null + } + + if ($copiedHttpsProxy) { + $env:https_proxy = $savedHttpsProxy + } else { + $env:https_proxy = $null + } + } } Describe "Invoke-RestMethod tests" -Tags "Feature" { @@ -524,7 +609,6 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" { $result.headers.'Accept-Encoding' | Should Match "gzip, deflate" $result.headers.Host | Should Match "httpbin.org" $result.headers.'User-Agent' | Should Match "WindowsPowerShell" - } #> @@ -534,7 +618,54 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" { $result = ExecuteWebCommand -command $command $result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand" + } + + It "Validate Invoke-RestMethod error with -Proxy and -NoProxy option" { + + $command = "Invoke-RestMethod -Uri http://httpbin.org/delay/:10 -Proxy 'http://localhost:8080' -NoProxy -TimeoutSec 2" + + $result = ExecuteWebCommand -command $command + $result.Error.FullyQualifiedErrorId | Should Be "AmbiguousParameterSet,Microsoft.PowerShell.Commands.InvokeRestMethodCommand" + } + + $testCase = @( + @{ proxy_address = "http://localhost:8080"; name = 'http_proxy'; protocol = 'http' } + @{ proxy_address = "http://localhost:8080"; name = 'https_proxy'; protocol = 'https' } + ) + + It "Validate Invoke-RestMethod error with -Proxy option - ''" -TestCases $testCase { + param($proxy_address, $name, $protocol) + + $command = "Invoke-RestMethod -Uri '${protocol}://httpbin.org/' -Proxy '${proxy_address}' -TimeoutSec 2" + + $result = ExecuteWebCommand -command $command + $result.Error.FullyQualifiedErrorId | Should Be "System.Threading.Tasks.TaskCanceledException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand" + } + + It "Validate Invoke-RestMethod error with environment proxy set - ''" -TestCases $testCase { + param($proxy_address, $name, $protocol) + + # Configure the environment variable. + New-Item -Name ${name} -Value ${proxy_address} -ItemType Variable -Path Env: -Force + + $command = "Invoke-RestMethod -Uri '${protocol}://httpbin.org/delay/:5' -TimeoutSec 5" + + $result = ExecuteWebCommand -command $command + $result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand" + } + + It "Validate Invoke-RestMethod returns User-Agent with option -NoProxy when environment proxy set - ''" -TestCases $testCase { + param($proxy_address, $name, $protocol) + + # Configure the environment variable. + New-Item -Name ${name} -Value ${proxy_address} -ItemType Variable -Path Env: -Force + $command = "Invoke-RestMethod -Uri '${protocol}://httpbin.org/user-agent' -TimeoutSec 5 -NoProxy" + + $result = ExecuteWebCommand -command $command + + # Validate response + $result.Output.'User-Agent' | Should Match "WindowsPowerShell" } # Perform the following operation for Invoke-RestMethod @@ -744,7 +875,33 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" { # need to check against inner exception since Linux and Windows uses different HTTP client libraries so errors aren't the same $result.Error.ErrorDetails.Message | Should Match $result.Error.Exception.InnerException.Message $result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand" - } + } + + BeforeEach { + if ($env:http_proxy) { + $savedHttpProxy = $env:http_proxy + $copiedHttpProxy = $true + } + + if ($env:https_proxy) { + $savedHttpsProxy = $env:https_proxy + $copiedHttpsProxy = $true + } + } + + AfterEach { + if ($copiedHttpProxy) { + $env:http_proxy = $savedHttpProxy + } else { + $env:http_proxy = $null + } + + if ($copiedHttpsProxy) { + $env:https_proxy = $savedHttpsProxy + } else { + $env:https_proxy = $null + } + } } Describe "Validate Invoke-WebRequest and Invoke-RestMethod -InFile" -Tags "Feature" {