mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Add -SkipHeaderValidation switch to Invoke-WebRequest and Invoke-RestMethod to support adding headers without validating the header value. (#4085)
* Add -SkipHeaderValidation switch to Invoke-WebRequest and Invoke-RestMethod to support adding headers without validating the header value. * Fix whitespace
This commit is contained in:
committed by
Travis Plunk
parent
7442e77073
commit
ea758a53af
+21
-4
@@ -58,12 +58,21 @@ namespace Microsoft.PowerShell.Commands
|
||||
/// CoreCLR (HTTPClient) does not have this behavior so web requests that work on
|
||||
/// PowerShell/FullCLR can fail with PowerShell/CoreCLR. To provide compatibility,
|
||||
/// we'll detect requests with an Authorization header and automatically strip
|
||||
/// the header when the first redirect occurs. This switch turns off this logic for
|
||||
/// the header when the first redirect occurs. This switch turns off this logic for
|
||||
/// edge cases where the authorization header needs to be preserved across redirects.
|
||||
/// </remarks>
|
||||
[Parameter]
|
||||
public virtual SwitchParameter PreserveAuthorizationOnRedirect { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// gets or sets the SkipHeaderValidation property
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This property adds headers to the request's header collection without validation.
|
||||
/// </remarks>
|
||||
[Parameter]
|
||||
public virtual SwitchParameter SkipHeaderValidation { get; set; }
|
||||
|
||||
#region Abstract Methods
|
||||
|
||||
/// <summary>
|
||||
@@ -240,14 +249,22 @@ namespace Microsoft.PowerShell.Commands
|
||||
}
|
||||
else
|
||||
{
|
||||
if (stripAuthorization
|
||||
&&
|
||||
if (stripAuthorization
|
||||
&&
|
||||
String.Equals(entry.Key, HttpKnownHeaderNames.Authorization.ToString(), StringComparison.OrdinalIgnoreCase)
|
||||
)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
request.Headers.Add(entry.Key, entry.Value);
|
||||
|
||||
if (SkipHeaderValidation)
|
||||
{
|
||||
request.Headers.TryAddWithoutValidation(entry.Key, entry.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
request.Headers.Add(entry.Key, entry.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,6 +184,49 @@ function ExecuteRedirectRequest
|
||||
return $result
|
||||
}
|
||||
|
||||
# This function calls either Invoke-WebRequest or Invoke-RestMethod with the given uri
|
||||
# using the custum headers and the optional SkipHeaderValidation switch.
|
||||
function ExecuteRequestWithCustomHeaders
|
||||
{
|
||||
param (
|
||||
[Parameter(Mandatory)]
|
||||
[string]
|
||||
$Uri,
|
||||
|
||||
[ValidateSet('Invoke-WebRequest', 'Invoke-RestMethod')]
|
||||
[string] $Cmdlet = 'Invoke-WebRequest',
|
||||
|
||||
[Parameter(Mandatory)]
|
||||
[ValidateNotNull()]
|
||||
[Hashtable] $Headers,
|
||||
|
||||
[switch] $SkipHeaderValidation
|
||||
)
|
||||
$result = [PSObject]@{Output = $null; Error = $null; Content = $null}
|
||||
|
||||
try
|
||||
{
|
||||
if ($Cmdlet -eq 'Invoke-WebRequest')
|
||||
{
|
||||
$result.Output = Invoke-WebRequest -Uri $Uri -TimeoutSec 5 -Headers $Headers -SkipHeaderValidation:$SkipHeaderValidation.IsPresent
|
||||
$result.Content = $result.Output.Content | ConvertFrom-Json
|
||||
}
|
||||
else
|
||||
{
|
||||
$result.Output = Invoke-RestMethod -Uri $Uri -TimeoutSec 5 -Headers $Headers -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.
|
||||
@@ -662,6 +705,35 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" {
|
||||
|
||||
#endregion Redirect tests
|
||||
|
||||
#region SkipHeaderVerification Tests
|
||||
|
||||
It "Verifies Invoke-WebRequest default header handling with no errors" {
|
||||
$headers = @{"If-Match" = "*"}
|
||||
$response = ExecuteRequestWithCustomHeaders -Uri "http://localhost:8080/PowerShell?test=echo" -headers $headers
|
||||
|
||||
$response.Error | Should BeNullOrEmpty
|
||||
$response.Content.Headers -contains "If-Match" | Should Be $true
|
||||
}
|
||||
|
||||
It "Verifies Invoke-WebRequest default header handling reports an error is returned for an invalid If-Match header value" {
|
||||
$headers = @{"If-Match" = "12345"}
|
||||
$response = ExecuteRequestWithCustomHeaders -Uri "http://localhost:8080/PowerShell?test=echo" -headers $headers
|
||||
|
||||
$response.Error | Should Not BeNullOrEmpty
|
||||
$response.Error.FullyQualifiedErrorId | Should Be "System.FormatException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
|
||||
$response.Error.Exception.Message | Should Be "The format of value '12345' is invalid."
|
||||
}
|
||||
|
||||
It "Verifies Invoke-WebRequest header handling does not report an error when using -SkipHeaderValidation" {
|
||||
$headers = @{"If-Match" = "12345"}
|
||||
$response = ExecuteRequestWithCustomHeaders -Uri "http://localhost:8080/PowerShell?test=echo" -headers $headers -SkipHeaderValidation
|
||||
|
||||
$response.Error | Should BeNullOrEmpty
|
||||
$response.Content.Headers -contains "If-Match" | Should Be $true
|
||||
}
|
||||
|
||||
#endregion SkipHeaderVerification Tests
|
||||
|
||||
BeforeEach {
|
||||
if ($env:http_proxy) {
|
||||
$savedHttpProxy = $env:http_proxy
|
||||
@@ -1124,6 +1196,35 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" {
|
||||
|
||||
#endregion Redirect tests
|
||||
|
||||
#region SkipHeaderVerification tests
|
||||
|
||||
It "Verifies Invoke-RestMethod default header handling with no errors" {
|
||||
$headers = @{"If-Match" = "*"}
|
||||
$response = ExecuteRequestWithCustomHeaders -Uri "http://localhost:8081/PowerShell?test=echo" -headers $headers -Cmdlet "Invoke-RestMethod"
|
||||
|
||||
$response.Error | Should BeNullOrEmpty
|
||||
$response.Content.Headers -contains "If-Match" | Should Be $true
|
||||
}
|
||||
|
||||
It "Verifies Invoke-RestMethod default header handling reports an error is returned for an invalid If-Match header value" {
|
||||
$headers = @{"If-Match" = "12345"}
|
||||
$response = ExecuteRequestWithCustomHeaders -Uri "http://localhost:8081/PowerShell?test=echo" -headers $headers -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 '12345' is invalid."
|
||||
}
|
||||
|
||||
It "Verifies Invoke-RestMethod header handling does not report an error when using -SkipHeaderValidation" {
|
||||
$headers = @{"If-Match" = "12345"}
|
||||
$response = ExecuteRequestWithCustomHeaders -Uri "http://localhost:8081/PowerShell?test=echo" -headers $headers -SkipHeaderValidation -Cmdlet "Invoke-RestMethod"
|
||||
|
||||
$response.Error | Should BeNullOrEmpty
|
||||
$response.Content.Headers -contains "If-Match" | Should Be $true
|
||||
}
|
||||
|
||||
#endregion SkipHeaderVerification tests
|
||||
|
||||
BeforeEach {
|
||||
if ($env:http_proxy) {
|
||||
$savedHttpProxy = $env:http_proxy
|
||||
|
||||
@@ -134,6 +134,13 @@ Function Start-HTTPListener {
|
||||
$contentType = $queryItems["contenttype"]
|
||||
$output = $queryItems["output"]
|
||||
}
|
||||
|
||||
# Echo the request as the output.
|
||||
"echo"
|
||||
{
|
||||
Write-Verbose -Message "Echo request"
|
||||
$output = $request | ConvertTo-Json -Depth 6
|
||||
}
|
||||
|
||||
<#
|
||||
This test provides support for multiple redirection types as well as a custom
|
||||
|
||||
Reference in New Issue
Block a user