Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option -NoProxy to WebCmdlet #3447

Conversation

TheFlyingCorpse
Copy link
Contributor

This commit adds a -NoProxy parameter to the WebCmdlet, used by both Invoke-WebRequest and Invoke-RestMethod. The fix is intended to allow for bypassing a DefaultWebProxy, such as a system configured one for direct requests.

References #3418

I did not figure out where I can update the help files relevant to this, I'd appreciate being pointed in the right direction for this.

@msftclas
Copy link

@TheFlyingCorpse,
Thanks for having already signed the Contribution License Agreement. Your agreement was validated by Microsoft. We will now review your pull request.
Thanks,
Microsoft Pull Request Bot

@SteveL-MSFT
Copy link
Member

Can you add a test? Thanks!

Copy link
Member

@SteveL-MSFT SteveL-MSFT left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a test

/// gets or sets the NoProxy property
/// </summary>
[Parameter]
public virtual SwitchParameter NoProxy { get; set; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a good reason to make the property/parameter virtual?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest, I copied what was already used in that file for the other switches present.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should -noproxy and -proxy* parameters be in different parametersets?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds like a good idea, I'll add a few more tests and make that change.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that it is better not to do different parameter sets because we will not be able to do:

function Foo($NoProxy) {
   Invoke-WebRequest -NoProxy:$NoProxy -Proxy "http://proxy.server.com"
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency, it seems like these should be mutually exclusive (thus different parametersets). PowerShell doesn't work like Unix cmdlines where last one wins (in which case, the above example would be -Proxy overrides -NoProxy despite $true or $false). I've typically used splatting to construct parameters dynamically. I think if we want something more terse, we should introduce a more general approach as a language construct.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Point taken, updating now.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused about the switch, all the more so in a separate parameter set. I would prefer not to complicate and just make -Proxy $null

@TheFlyingCorpse TheFlyingCorpse force-pushed the feature/webcmdlet-add-noproxy-switch branch from 7bcc221 to af53884 Compare March 28, 2017 20:35
@TheFlyingCorpse
Copy link
Contributor Author

TheFlyingCorpse commented Mar 28, 2017

Tests added, if you want me to, I can add scenarios to verify it fails when proxy is defined to the made up proxy as a countermeasure to -NoProxy.
I did not add a test for the following two scenarios, I am not certain if they are in or out of scope:

  • Internet Explorer proxy defined, it is however how I developed the -NoProxy addition.
  • Proxy defined via "netsh winhttp", in the testing I did by hand this did not have any effect on Invoke-WebRequest or Invoke-RestMethod

@iSazonov
Copy link
Collaborator

Probably enough:

Invoke-WebRequest -Uri http://httpbin.org/headers -Proxy http://httpbin.org -NoProxy   - return expected result
Invoke-WebRequest -Uri http://httpbin.org/headers -Proxy http://httpbin.org -NoProxy:$false - return empty content

@TheFlyingCorpse TheFlyingCorpse force-pushed the feature/webcmdlet-add-noproxy-switch branch from af53884 to 1d9f2de Compare March 29, 2017 15:47
@TheFlyingCorpse
Copy link
Contributor Author

TheFlyingCorpse commented Mar 29, 2017

Updated tests quite a bit.

I did not split the parameters up to different parametersets as @iSazonov made a great case for why it ought not to be split up.

It "Validate Invoke-WebRequest error for -MaximumRedirection with Environment http_proxy set" {

# Store the current proxy.
$currentProxy = [System.Environment]::GetEnvironmentVariable("http_proxy")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it may be cleaner to put storing and restoring of http_proxy (if defined) in BeforeEach{} and AfterEach{} blocks rather than having repeated code.


# Store the current proxy.
$currentProxy = [System.Environment]::GetEnvironmentVariable("http_proxy")
[System.Environment]::SetEnvironmentVariable("http_proxy","http://localhost:8080")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be able to rely on:

$savedProxy = $env:http_proxy
...
$env:http_proxy = "http://localhost:8080"
...
$env:http_proxy = $savedProxy

@@ -247,7 +247,115 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" {

$result = ExecuteWebCommand -command $command
$result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
}

It "Validate Invoke-WebRequest returns User-Agent where -NoProxy with -Proxy set" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we agree that -NoProxy and -Proxy are mutually exclusive, then this test should validate you get an AmbiguousParameterSet,Microsoft.PowerShell.Commands.NewPSSessionCommand exception

$command = "Invoke-WebRequest -Uri 'http://httpbin.org/redirect/3' -MaximumRedirection 2 -TimeoutSec 5"

$result = ExecuteWebCommand -command $command
$result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not clear to me what this test is intended to validate. Since localhost:8080 is not a proxy, no redirection will actually happen and the error returned is that it can't contact the proxy.

[System.Environment]::SetEnvironmentVariable("http_proxy",$currentProxy)
}

It "Validate Invoke-WebRequest error for -MaximumRedirection with Environment https_proxy set" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, not clear to me why -MaximumRedirection is interesting here as a test with invalid proxy

@TheFlyingCorpse TheFlyingCorpse force-pushed the feature/webcmdlet-add-noproxy-switch branch from 1d9f2de to 4da3e63 Compare March 29, 2017 21:13
@TheFlyingCorpse
Copy link
Contributor Author

TheFlyingCorpse commented Mar 29, 2017

Updated, incorporated ParameterSetName's and updated the tests to reflect this change.

To be able to make the -NoProxy not use -Proxy, I had to modify a bit more than expected since there already was defined two ParameterSets: StandardMethod and CustomMethod, there are now two extra that redirects to the existing one. Without the change to this, the method would never get since the new names introduced would break this. The method would break on both use of -Proxy and -NoProxy since the switch using ParameterSetName would not match either existing Method.

Copy link
Contributor

@joeyaiello joeyaiello left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given all the discussion in #3418, I'm explicitly giving this one my 👍


It "Validate Invoke-WebRequest returns User-Agent where -NoProxy with Environment http_proxy Set" {

$env:http_proxy="http://localhost:8080"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the http and https tests are essentially the same, I think it may be better to use Pester's TestCase feature. See a sample here:

@TheFlyingCorpse
Copy link
Contributor Author

Note: I didn't find a good way with the mock to have a dynamic proxy when using $env to assign it inside the function when using parameters, if the workaround which uses "pure" PowerShell is not accepted, let me know what the alternative is :-)

@TheFlyingCorpse TheFlyingCorpse force-pushed the feature/webcmdlet-add-noproxy-switch branch from 4da3e63 to 1d31ab4 Compare March 31, 2017 19:05
@mirichmo mirichmo merged commit a770ecd into PowerShell:master Apr 1, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants