MegaBites-AI/Windows-powershell
0308
1# Copyright (c) Microsoft Corporation.2# Licensed under the MIT License.3 4# This is a Pester test suite which validate the Web cmdlets.5#6# Note: These tests use data from WebListener7#8 9# Invokes the given command via script block invocation.10#11function ExecuteWebCommand {12 param (13 [ValidateNotNullOrEmpty()]14 [string]15 $command16 )17 18 $result = [PSObject]@{Output = $null; Error = $null}19 20 try {21 $scriptBlock = [scriptblock]::Create($command)22 $result.Output = & $scriptBlock23 } catch {24 $result.Error = $_25 }26 27 return $result28}29 30# This function calls either Invoke-WebRequest or Invoke-RestMethod using the OutFile parameter31# Then, the file content is read and return in a $result object.32#33function ExecuteRequestWithOutFile {34 param (35 [ValidateSet("Invoke-RestMethod", "Invoke-WebRequest" )]36 [string]37 $cmdletName,38 39 [string]40 $uri = (Get-WebListenerUrl -Test 'Get')41 )42 43 $result = [PSObject]@{Output = $null; Error = $null}44 # We use '[outfile1]' in the file name to check that OutFile parameter is literal path45 $filePath = Join-Path $TestDrive ((Get-Random).ToString() + "[outfile1].txt")46 try {47 if ($cmdletName -eq "Invoke-WebRequest") {48 Invoke-WebRequest -Uri $uri -OutFile $filePath49 } else {50 Invoke-RestMethod -Uri $uri -OutFile $filePath51 }52 $result.Output = Get-Content -LiteralPath $filePath -Raw -ErrorAction SilentlyContinue53 } catch {54 $result.Error = $_55 } finally {56 if (Test-Path $filePath) {57 Remove-Item $filePath -Force -ErrorAction SilentlyContinue58 }59 }60 return $result61}62 63# This function calls either Invoke-WebRequest or Invoke-RestMethod with the given uri64# using the Headers parameter to disable keep-alive.65#66function ExecuteRequestWithHeaders {67 param (68 [ValidateSet("Invoke-RestMethod", "Invoke-WebRequest" )]69 [string]70 $cmdletName,71 72 [string]73 $uri = (Get-WebListenerUrl -Test 'Get')74 )75 76 $result = [PSObject]@{Output = $null; Error = $null}77 try {78 $headers = @{ Connection = 'close'}79 if ($cmdletName -eq "Invoke-WebRequest") {80 $result.Output = Invoke-WebRequest -Uri $uri -Headers $headers81 } else {82 $result.Output = Invoke-RestMethod -Uri $uri -Headers $headers83 }84 } catch {85 $result.Error = $_86 }87 return $result88}89 90# Returns test data for the given content type.91#92function GetTestData {93 param (94 [ValidateSet("text/plain", "application/xml", "application/json")]95 [String]96 $contentType97 )98 99 $testData = @{ItemID = 987123; Name = 'TestData'}100 101 if ($contentType -eq "text/plain") {102 $body = $testData | Out-String103 } elseif ($contentType -eq "application/xml") {104 $body = '105<?xml version="1.0" encoding="utf-8"?>106<Objects>107<Object>108<ItemID>987123</ItemID>109<Name>TestData</Name>110</Object>111</Objects>112'113 } else {114 # "application/json"115 $body = $testData | ConvertTo-Json -Compress116 }117 118 return $body119}120 121function ExecuteRedirectRequest {122 param (123 [Parameter(Mandatory)]124 [string]125 $uri,126 127 [ValidateSet('Invoke-WebRequest', 'Invoke-RestMethod')]128 [string]129 $Cmdlet = 'Invoke-WebRequest',130 131 [ValidateSet('POST', 'GET')]132 [string]133 $Method = 'GET',134 135 [ValidateSet('POST')]136 [string]137 $CustomMethod,138 139 [switch]140 $PreserveAuthorizationOnRedirect,141 142 [switch]143 $PreserveHttpMethodOnRedirect,144 145 [ValidateRange(0, [int]::MaxValue)]146 [int]147 $MaximumRedirection148 )149 $result = [PSObject]@{Output = $null; Error = $null; Content = $null}150 151 try {152 $headers = @{"Authorization" = "test"}153 if ($Cmdlet -eq 'Invoke-WebRequest') {154 if ($MaximumRedirection -gt 0) {155 $result.Output = Invoke-WebRequest -Uri $uri -Headers $headers -PreserveAuthorizationOnRedirect:$PreserveAuthorizationOnRedirect.IsPresent -Method $Method -MaximumRedirection:$MaximumRedirection156 } elseif ($CustomMethod) {157 $result.Output = Invoke-WebRequest -Uri $uri -Headers $headers -PreserveAuthorizationOnRedirect:$PreserveAuthorizationOnRedirect.IsPresent -CustomMethod $CustomMethod158 } else {159 $result.Output = Invoke-WebRequest -Uri $uri -Headers $headers -PreserveAuthorizationOnRedirect:$PreserveAuthorizationOnRedirect.IsPresent -PreserveHttpMethodOnRedirect:$PreserveHttpMethodOnRedirect.IsPresent -Method $Method160 }161 $result.Content = $result.Output.Content | ConvertFrom-Json162 } else {163 if ($MaximumRedirection -gt 0) {164 $result.Output = Invoke-RestMethod -Uri $uri -Headers $headers -PreserveAuthorizationOnRedirect:$PreserveAuthorizationOnRedirect.IsPresent -Method $Method -MaximumRedirection:$MaximumRedirection165 } elseif ($CustomMethod) {166 $result.Output = Invoke-RestMethod -Uri $uri -Headers $headers -PreserveAuthorizationOnRedirect:$PreserveAuthorizationOnRedirect.IsPresent -CustomMethod $CustomMethod167 } else {168 $result.Output = Invoke-RestMethod -Uri $uri -Headers $headers -PreserveAuthorizationOnRedirect:$PreserveAuthorizationOnRedirect.IsPresent -PreserveHttpMethodOnRedirect:$PreserveHttpMethodOnRedirect.IsPresent -Method $Method169 }170 # NOTE: $result.Output should already be a PSObject (Invoke-RestMethod converts the returned json automatically)171 # so simply reference $result.Output172 $result.Content = $result.Output173 }174 } catch {175 $result.Error = $_176 }177 178 return $result179}180 181# This function calls either Invoke-WebRequest or Invoke-RestMethod with the given uri182# using the custum headers and the optional SkipHeaderValidation switch.183function ExecuteRequestWithCustomHeaders {184 param (185 [Parameter(Mandatory)]186 [string]187 $Uri,188 189 [ValidateSet('Invoke-WebRequest', 'Invoke-RestMethod')]190 [string]191 $Cmdlet = 'Invoke-WebRequest',192 193 [Parameter(Mandatory)]194 [ValidateNotNull()]195 [Hashtable]196 $Headers,197 198 [switch]199 $SkipHeaderValidation200 )201 $result = [PSObject]@{Output = $null; Error = $null; Content = $null}202 203 try {204 if ($Cmdlet -eq 'Invoke-WebRequest') {205 $result.Output = Invoke-WebRequest -Uri $Uri -Headers $Headers -SkipHeaderValidation:$SkipHeaderValidation.IsPresent206 $result.Content = $result.Output.Content | ConvertFrom-Json207 } else {208 $result.Output = Invoke-RestMethod -Uri $Uri -Headers $Headers -SkipHeaderValidation:$SkipHeaderValidation.IsPresent209 # NOTE: $result.Output should already be a PSObject (Invoke-RestMethod converts the returned json automatically)210 # so simply reference $result.Output211 $result.Content = $result.Output212 }213 } catch {214 $result.Error = $_215 }216 217 return $result218}219 220# This function calls either Invoke-WebRequest or Invoke-RestMethod with the given uri221# using the custom UserAgent and the optional SkipHeaderValidation switch.222function ExecuteRequestWithCustomUserAgent {223 param (224 [Parameter(Mandatory)]225 [string]226 $Uri,227 228 [ValidateSet('Invoke-WebRequest', 'Invoke-RestMethod')]229 [string]230 $Cmdlet = 'Invoke-WebRequest',231 232 [Parameter(Mandatory)]233 [ValidateNotNull()]234 [string]235 $UserAgent,236 237 [switch]238 $SkipHeaderValidation239 )240 $result = [PSObject]@{Output = $null; Error = $null; Content = $null}241 242 try {243 $Params = @{244 Uri = $Uri245 ConnectionTimeoutSeconds = 5246 UserAgent = $UserAgent247 SkipHeaderValidation = $SkipHeaderValidation.IsPresent248 }249 if ($Cmdlet -eq 'Invoke-WebRequest') {250 $result.Output = Invoke-WebRequest @Params251 $result.Content = $result.Output.Content | ConvertFrom-Json252 } else {253 $result.Output = Invoke-RestMethod @Params254 # NOTE: $result.Output should already be a PSObject (Invoke-RestMethod converts the returned json automatically)255 # so simply reference $result.Output256 $result.Content = $result.Output257 }258 } catch {259 $result.Error = $_260 }261 262 return $result263}264 265# This function calls Invoke-WebRequest with the given uri266function ExecuteWebRequest {267 param (268 [Parameter(Mandatory)]269 [string]270 $Uri,271 272 [switch]273 $UseBasicParsing274 )275 $result = [PSObject]@{Output = $null; Error = $null; Content = $null}276 277 try {278 $result.Output = Invoke-WebRequest -Uri $Uri -UseBasicParsing:$UseBasicParsing.IsPresent279 $result.Content = $result.Output.Content280 } catch {281 $result.Error = $_282 }283 284 return $result285}286 287[string] $debugEncodingPrefix = 'WebResponse content encoding: '288# This function calls Invoke-WebRequest with the given uri and289# parses the verbose output to determine the encoding used for the content.290function ExecuteRestMethod {291 param (292 [Parameter(Mandatory)]293 [string]294 $Uri,295 296 [switch]297 $UseBasicParsing298 )299 $result = @{Output = $null; Error = $null; Encoding = $null; Content = $null}300 $debugPreferenceSave = $DebugPreference301 $DebugPreference = 'Continue'302 try {303 $debugFile = Join-Path $TestDrive -ChildPath ExecuteRestMethod.debug.txt304 $result.Output = Invoke-RestMethod -Uri $Uri -UseBasicParsing:$UseBasicParsing.IsPresent 5>$debugFile305 $result.Content = $result.Output306 307 # Invoke-RestMethod does not return encoding as part of an object, only in debug output, so we parse the debug output for the purposes of verifying the test.308 # This debug output is defined in InvokeRestMethodCommand.Common.cs ProcessResponse()309 if (Test-Path -Path $debugFile) {310 $result.Debug = Get-Content -Path $debugFile311 foreach ($item in $result.Debug) {312 $line = $item.Trim()313 if ($line.StartsWith($debugEncodingPrefix)) {314 $encodingName = [int]::Parse($item.SubString($EncodingPrefix.Length).Split('CodePage: ')[1].Trim())315 $result.Encoding = [System.Text.Encoding]::GetEncoding($encodingName)316 break317 }318 }319 if ($null -eq $result.Encoding) {320 throw "Encoding not found in debug output. Lines: $($result.Debug.Count) Content:$($result.Debug)"321 }322 }323 324 if ($null -eq $result.Debug) {325 throw "No debug output was found"326 }327 } catch {328 $result.Error = $_ | Select-Object * | Out-String329 } finally {330 $DebugPreference = $debugPreferenceSave331 if (Test-Path -Path $debugFile) {332 Remove-Item -Path $debugFile -ErrorAction SilentlyContinue333 }334 }335 336 return $result337}338 339function GetMultipartBody {340 param (341 [Switch]342 $String,343 344 [Switch]345 $File346 )347 $multipartContent = [System.Net.Http.MultipartFormDataContent]::new()348 if ($String.IsPresent) {349 $stringHeader = [System.Net.Http.Headers.ContentDispositionHeaderValue]::new("form-data")350 $stringHeader.Name = "TestString"351 $StringContent = [System.Net.Http.StringContent]::new("TestValue")352 $StringContent.Headers.ContentDisposition = $stringHeader353 $multipartContent.Add($stringContent)354 }355 if ($File.IsPresent) {356 $multipartFile = Join-Path $TestDrive 'multipart.txt'357 "TestContent" | Set-Content $multipartFile358 $FileStream = [System.IO.FileStream]::new($multipartFile, [System.IO.FileMode]::Open)359 $fileHeader = [System.Net.Http.Headers.ContentDispositionHeaderValue]::new("form-data")360 $fileHeader.Name = "TestFile"361 $fileHeader.FileName = 'multipart.txt'362 $fileContent = [System.Net.Http.StreamContent]::new($FileStream)363 $fileContent.Headers.ContentDisposition = $fileHeader364 $fileContent.Headers.ContentType = [System.Net.Http.Headers.MediaTypeHeaderValue]::Parse("text/plain")365 $multipartContent.Add($fileContent)366 }367 # unary comma required to prevent $multipartContent from being unwrapped/enumerated368 return , $multipartContent369}370 371<#372 Defines the list of redirect codes to test as well as the373 expected Method when the redirection is handled.374 See https://learn.microsoft.com/dotnet/api/system.net.httpstatuscode375 for additonal details.376#>377$redirectTests = @(378 @{redirectType = 'MultipleChoices'; redirectedMethod = 'GET'}379 @{redirectType = 'Ambiguous'; redirectedMethod = 'GET'} # Synonym for MultipleChoices380 381 @{redirectType = 'Moved'; redirectedMethod = 'GET'}382 @{redirectType = 'MovedPermanently'; redirectedMethod = 'GET'} # Synonym for Moved383 384 @{redirectType = 'Found'; redirectedMethod = 'GET'}385 @{redirectType = 'Redirect'; redirectedMethod = 'GET'} # Synonym for Found386 387 @{redirectType = 'redirectMethod'; redirectedMethod = 'GET'}388 @{redirectType = 'SeeOther'; redirectedMethod = 'GET'} # Synonym for RedirectMethod389 390 @{redirectType = 'TemporaryRedirect'; redirectedMethod = 'POST'}391 @{redirectType = 'RedirectKeepVerb'; redirectedMethod = 'POST'} # Synonym for TemporaryRedirect392 393 @{redirectType = 'relative'; redirectedMethod = 'GET'}394)395 396Describe "Invoke-WebRequest tests" -Tags "Feature", "RequireAdminOnWindows" {397 BeforeAll {398 $oldProgress = $ProgressPreference399 $ProgressPreference = 'SilentlyContinue'400 $WebListener = Start-WebListener401 $NotFoundQuery = @{402 statuscode = 404403 responsephrase = 'Not Found'404 contenttype = 'text/plain'405 body = 'oops'406 headers = "{}"407 }408 }409 410 AfterAll {411 $ProgressPreference = $oldProgress412 }413 414 # Validate the output of Invoke-WebRequest415 #416 function ValidateResponse {417 param ($response)418 419 $response.Error | Should -Be $null420 421 # A successful call returns: Status = 200, and StatusDescription = "OK"422 $response.Output.StatusDescription | Should -Match "OK"423 $response.Output.StatusCode | Should -Be 200424 425 # Make sure the response contains the following properties:426 $response.Output.RawContent | Should -Not -Be $null427 $response.Output.Headers | Should -Not -Be $null428 $response.Output.RawContent | Should -Not -Be $null429 $response.Output.RawContentLength | Should -Not -Be $null430 $response.Output.Content | Should -Not -Be $null431 }432 433 #User-Agent changes on different platforms, so tests should only be run if on the correct platform434 It "Invoke-WebRequest returns Correct User-Agent on MacOSX" -Skip:(!$IsMacOS) {435 $uri = Get-WebListenerUrl -Test 'Get'436 $command = "Invoke-WebRequest -Uri '$uri'"437 438 $result = ExecuteWebCommand -command $command439 ValidateResponse -response $result440 441 # Validate response content442 $jsonContent = $result.Output.Content | ConvertFrom-Json443 $jsonContent.headers.'User-Agent' | Should -MatchExactly '.*\(Macintosh;.*\) PowerShell\/\d+\.\d+\.\d+.*'444 }445 446 It "Invoke-WebRequest returns Correct User-Agent on Linux" -Skip:(!$IsLinux) {447 $uri = Get-WebListenerUrl -Test 'Get'448 $command = "Invoke-WebRequest -Uri '$uri'"449 450 $result = ExecuteWebCommand -command $command451 ValidateResponse -response $result452 453 # Validate response content454 $jsonContent = $result.Output.Content | ConvertFrom-Json455 $jsonContent.headers.'User-Agent' | Should -MatchExactly '.*\(Linux;.*\) PowerShell\/\d+\.\d+\.\d+.*'456 }457 458 It "Invoke-WebRequest returns Correct User-Agent on Windows" -Skip:(!$IsWindows) {459 $uri = Get-WebListenerUrl -Test 'Get'460 $command = "Invoke-WebRequest -Uri '$uri'"461 462 $result = ExecuteWebCommand -command $command463 ValidateResponse -response $result464 465 # Validate response content466 $jsonContent = $result.Output.Content | ConvertFrom-Json467 $jsonContent.headers.'User-Agent' | Should -MatchExactly '.*\(Windows NT \d+\.\d*;.*\) PowerShell\/\d+\.\d+\.\d+.*'468 }469 470 It "Invoke-WebRequest returns headers dictionary" {471 $uri = Get-WebListenerUrl -Test 'Get'472 $command = "Invoke-WebRequest -Uri '$uri'"473 474 $result = ExecuteWebCommand -command $command475 ValidateResponse -response $result476 477 # Validate response content478 $jsonContent = $result.Output.Content | ConvertFrom-Json479 $jsonContent.headers.Host | Should -Be $Uri.Authority480 }481 482 It "Invoke-WebRequest with blank ContentType succeeds" {483 $uri = Get-WebListenerUrl -Test 'Get'484 $command = "Invoke-WebRequest -Uri '$uri' -ContentType ''"485 486 $result = ExecuteWebCommand -command $command487 488 # Validate response489 ValidateResponse -response $result490 491 $result.Output.Headers.'Content-Length' | Should -BeNullOrEmpty492 }493 494 It "Validate Invoke-WebRequest -DisableKeepAlive" {495 # Operation options496 $uri = Get-WebListenerUrl -Test 'Get'497 $command = "Invoke-WebRequest -Uri $uri -DisableKeepAlive"498 499 $result = ExecuteWebCommand -command $command500 ValidateResponse -response $result501 502 $result.Output.Headers.Connection | Should -Be "Close"503 }504 505 It "Validate Invoke-WebRequest -HttpVersion '<httpVersion>'" -Skip:(!$IsWindows) -TestCases @(506 @{ httpVersion = '1.1'},507 @{ httpVersion = '2'}508 ) {509 param($httpVersion)510 511 if(Test-IsWinServer2012R2 -and $httpVersion -eq '2') {512 Set-ItResult -Skipped -Because "HTTP/2 is not supported on Windows Server 2012R2"513 return514 }515 516 # Operation options517 $uri = Get-WebListenerUrl -Test 'Get' -Https518 $command = "Invoke-WebRequest -Uri $uri -HttpVersion $httpVersion -SkipCertificateCheck"519 520 $result = ExecuteWebCommand -command $command521 ValidateResponse -response $result522 523 # Validate response content524 $jsonContent = $result.Output.Content | ConvertFrom-Json525 $jsonContent.protocol | Should -Be "HTTP/$httpVersion"526 }527 528 It "Validate Invoke-WebRequest -MaximumRedirection" {529 $uri = Get-WebListenerUrl -Test 'Redirect' -TestValue '3'530 $command = "Invoke-WebRequest -Uri '$uri' -MaximumRedirection 4"531 532 $result = ExecuteWebCommand -command $command533 ValidateResponse -response $result534 535 # Validate response content536 $jsonContent = $result.Output.Content | ConvertFrom-Json537 $jsonContent.headers.Host | Should -Match $uri.Authority538 }539 540 It "Validate Invoke-WebRequest error for -MaximumRedirection" {541 $uri = Get-WebListenerUrl -Test 'Redirect' -TestValue '3'542 $command = "Invoke-WebRequest -Uri '$uri' -MaximumRedirection 2"543 544 $result = ExecuteWebCommand -command $command545 $result.Error.FullyQualifiedErrorId | Should -Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"546 }547 548 It "Validate Invoke-WebRequest redirect with -Query destination Http" {549 $httpUri = Get-WebListenerUrl -Test 'Get'550 $uri = Get-WebListenerUrl -Test 'Redirect' -Query @{destination = $httpUri}551 $command = "Invoke-WebRequest -Uri '$uri'"552 553 $result = ExecuteWebCommand -command $command554 $jsonContent = $result.Output.Content | ConvertFrom-Json555 $jsonContent.headers.Host | Should -Match $httpUri.Authority556 }557 558 It "Validate Invoke-WebRequest redirect with -Query destination Https" {559 $httpsUri = Get-WebListenerUrl -Test 'Get' -Https560 $uri = Get-WebListenerUrl -Test 'Redirect' -Https -Query @{destination = $httpsUri}561 $command = "Invoke-WebRequest -Uri '$uri' -SkipCertificateCheck"562 563 $result = ExecuteWebCommand -command $command564 $jsonContent = $result.Output.Content | ConvertFrom-Json565 $jsonContent.headers.Host | Should -Match $httpsUri.Authority566 }567 568 It "Invoke-WebRequest supports request that returns page containing UTF-8 data." {569 $uri = Get-WebListenerUrl -Test 'Encoding' -TestValue 'Utf8'570 $command = "Invoke-WebRequest -Uri '$uri'"571 572 $result = ExecuteWebCommand -command $command573 ValidateResponse -response $result574 575 $Result.Output.Encoding.BodyName | Should -Be 'utf-8'576 $Result.Output.Content | Should -Match 'โกโ โ งโ โ ผโ โ โกโ โ โ โ นโ ฐโ โกฃโ โ '577 }578 579 It "Invoke-WebRequest -ContentType overwrites Content-Type from -Headers." {580 $uri = Get-WebListenerUrl -Test 'POST'581 $command = "Invoke-WebRequest -Uri '$uri' -ContentType 'application/json' -Headers @{'Content-Type'='plain/text'} -Method 'POST'"582 $result = ExecuteWebCommand -command $command583 $result.Output.BaseResponse.RequestMessage.Content.Headers.ContentType.MediaType | Should -BeExactly 'application/json'584 }585 586 It "Invoke-WebRequest supports sending request as UTF-8." {587 $uri = Get-WebListenerUrl -Test 'POST'588 # Body must contain non-ASCII characters589 $command = "Invoke-WebRequest -Uri '$uri' -Body 'ะฟัะพะฒะตัะบะฐ' -ContentType 'application/json; charset=utf-8' -Method 'POST'"590 591 $result = ExecuteWebCommand -command $command592 ValidateResponse -response $result593 594 $result.Output.Encoding.BodyName | Should -BeExactly 'utf-8'595 $object = $Result.Output.Content | ConvertFrom-Json596 $object.Data | Should -BeExactly 'ะฟัะพะฒะตัะบะฐ'597 }598 599 It "Invoke-WebRequest supports sending XML requests without encoding" {600 $uri = Get-WebListenerUrl -Test POST601 $body = '<?xml version="1.0"?><foo />'602 $result = Invoke-WebRequest -Uri $uri -body ([xml]$body) -ContentType 'text/xml' -method 'POST'603 604 $object = $result.Content | ConvertFrom-Json605 $object.Data | Should -BeExactly $body606 }607 608 It "Invoke-WebRequest supports request that returns page containing CodPage 936 data." {609 $uri = Get-WebListenerUrl -Test 'Encoding' -TestValue 'CP936'610 $command = "Invoke-WebRequest -Uri '$uri'"611 612 $result = ExecuteWebCommand -command $command613 ValidateResponse -response $result614 615 $Result.Output.Encoding.CodePage | Should -Be 936616 $Result.Output.Content | Should -Match 'ๆต่ฏ123'617 }618 619 It "Invoke-WebRequest validate ConnectionTimeoutSeconds option" {620 $uri = Get-WebListenerUrl -Test 'Delay' -TestValue '5'621 $command = "Invoke-WebRequest -Uri '$uri' -ConnectionTimeoutSeconds 2"622 623 $result = ExecuteWebCommand -command $command624 $result.Error.FullyQualifiedErrorId | Should -Be "ConnectionTimeoutReached,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"625 }626 627 It "Invoke-WebRequest validate TimeoutSec alias" {628 $uri = Get-WebListenerUrl -Test 'Delay' -TestValue '5'629 $command = "Invoke-WebRequest -Uri '$uri' -TimeoutSec 2"630 631 $result = ExecuteWebCommand -command $command632 $result.Error.FullyQualifiedErrorId | Should -Be "ConnectionTimeoutReached,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"633 }634 635 It "Validate Invoke-WebRequest error with -Proxy and -NoProxy option" {636 $uri = Get-WebListenerUrl -Test 'Delay' -TestValue '10'637 $command = "Invoke-WebRequest -Uri '$uri' -Proxy 'http://127.0.0.1:8080' -NoProxy -TimeoutSec 2"638 639 $result = ExecuteWebCommand -command $command640 $result.Error.FullyQualifiedErrorId | Should -Be "AmbiguousParameterSet,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"641 }642 643 $testCase = @(644 @{ proxy_address = (Get-WebListenerUrl).Authority; name = 'HTTP proxy'; protocol = 'http' }645 @{ proxy_address = (Get-WebListenerUrl -https).Authority; name = 'HTTPS proxy'; protocol = 'https' }646 )647 648 It "Validate Invoke-WebRequest with -Proxy option set - '<name>'" -TestCases $testCase {649 param($proxy_address, $name, $protocol)650 651 # use external url, but with proxy the external url should not actually be called652 $command = "Invoke-WebRequest -Uri ${protocol}://httpbin.org -Proxy '${protocol}://${proxy_address}'"653 $result = ExecuteWebCommand -command $command654 $command = "Invoke-WebRequest -Uri '${protocol}://${proxy_address}' -NoProxy"655 $expectedResult = ExecuteWebCommand -command $command656 $result.Output.Content | Should -BeExactly $expectedResult.Output.Content657 }658 659 # Perform the following operation for Invoke-WebRequest660 # gzip Returns gzip-encoded data.661 # deflate Returns deflate-encoded data.662 # brotli Returns brotli-encoded data.663 # $dataEncodings = @("Chunked", "Compress", "Deflate", "GZip", "Identity")664 # Note: These are the supported options, but we do not have a web service to test them all.665 It "Invoke-WebRequest supports request that returns <DataEncoding>-encoded data." -TestCases @(666 @{ DataEncoding = "gzip" }667 @{ DataEncoding = "deflate" }668 @{ DataEncoding = "brotli" }669 ) {670 param($dataEncoding)671 $uri = Get-WebListenerUrl -Test 'Compression' -TestValue $dataEncoding672 $command = "Invoke-WebRequest -Uri '$uri'"673 674 $result = ExecuteWebCommand -command $command675 ValidateResponse -response $result676 677 # Validate response content678 # The content should be de-compressed, and otherwise converting from JSON will fail.679 $jsonContent = $result.Output.Content | ConvertFrom-Json680 $jsonContent.Headers.Host | Should -BeExactly $uri.Authority681 }682 683 # Perform the following operation for Invoke-WebRequest using the following content types: "text/plain", "application/xml", "application/xml"684 # post Returns POST data.685 # patch Returns PATCH data.686 # put Returns PUT data.687 # delete Returns DELETE data688 $testMethods = @("POST", "PATCH", "PUT", "DELETE")689 $contentTypes = @("text/plain", "application/xml", "application/json")690 691 foreach ($contentType in $contentTypes) {692 foreach ($method in $testMethods) {693 # Operation options694 $uri = Get-WebListenerUrl -Test $method695 $body = GetTestData -contentType $contentType696 $command = "Invoke-WebRequest -Uri $uri -Body '$body' -Method $method -ContentType $contentType"697 $commandNoContentType = "Invoke-WebRequest -Uri $uri -Body '$body' -Method $method"698 699 It "Invoke-WebRequest -Uri $uri -Method $method -ContentType $contentType -Body [body data]" {700 701 $result = ExecuteWebCommand -command $command702 ValidateResponse -response $result703 704 # Validate response content705 $jsonContent = $result.Output.Content | ConvertFrom-Json706 $jsonContent.url | Should -Match $uri707 $jsonContent.headers.'Content-Type' | Should -Match $contentType708 # Validate that the response Content.data field is the same as what we sent.709 $jsonContent.data | Should -Be $body710 }711 712 It "Invoke-WebRequest -Uri $uri -Method $method -Body [body data]" {713 714 $result = ExecuteWebCommand -command $commandNoContentType715 ValidateResponse -response $result716 717 # Validate response content718 $jsonContent = $result.Output.Content | ConvertFrom-Json719 $jsonContent.url | Should -Match $uri720 if ($method -eq "POST")721 {722 $jsonContent.headers.'Content-Type' | Should -Match "application/x-www-form-urlencoded"723 # Validate that the response Content.form field is the same as what we sent.724 [string]$jsonContent.form | Should -Be ([string][PSCustomObject]@{$body.Split("=")[0] = [System.Object[]]})725 $jsonContent.data | Should -BeNullOrEmpty726 }727 else728 {729 # Validate that the response Content.data field is the same as what we sent.730 $jsonContent.data | Should -Be $body731 }732 733 }734 }735 }736 737 It "Validate Invoke-WebRequest -Headers --> Set KeepAlive to false via headers" {738 $uri = Get-WebListenerUrl -Test 'Get'739 $result = ExecuteRequestWithHeaders -cmdletName Invoke-WebRequest -uri $uri740 ValidateResponse -response $result741 $result.Output.Headers.Connection | Should -Be "Close"742 }743 744 # Validate all available user agents for Invoke-WebRequest745 $agents = @{746 InternetExplorer = "MSIE 9.0"747 Chrome = "Chrome"748 Opera = "Opera"749 Safari = "Safari"750 FireFox = "Firefox"751 }752 753 foreach ($agentName in $agents.Keys) {754 $expectedAgent = $agents[$agentName]755 $uri = Get-WebListenerUrl -Test 'Get'756 $userAgent = "[Microsoft.PowerShell.Commands.PSUserAgent]::$agentName"757 $command = "Invoke-WebRequest -Uri $uri -UserAgent ($userAgent) "758 759 It "Validate Invoke-WebRequest UserAgent. Execute--> $command" {760 761 $result = ExecuteWebCommand -command $command762 ValidateResponse -response $result763 764 # Validate response content765 $jsonContent = $result.Output.Content | ConvertFrom-Json766 $jsonContent.headers.Host | Should -Be $uri.Authority767 $jsonContent.headers.'User-Agent' | Should -Match $expectedAgent768 }769 }770 771 It "Validate Invoke-WebRequest -OutFile" {772 $uri = Get-WebListenerUrl -Test 'Get'773 $result = ExecuteRequestWithOutFile -cmdletName "Invoke-WebRequest" -uri $uri774 $jsonContent = $result.Output | ConvertFrom-Json775 $jsonContent.headers.Host | Should -Be $uri.Authority776 }777 778 It "Invoke-WebRequest -OutFile folder Downloads the file and names it" {779 $uri = Get-WebListenerUrl -Test 'Get'780 $content = Invoke-WebRequest -Uri $uri781 $outFile = Join-Path $TestDrive $content.BaseResponse.RequestMessage.RequestUri.Segments[-1]782 783 # ensure the file does not exist784 Remove-Item -Force -ErrorAction Ignore -Path $outFile785 Invoke-WebRequest -Uri $uri -OutFile $TestDrive786 787 Test-Path $outFile | Should -Be $true788 Get-Item $outFile | Select-Object -ExpandProperty Length | Should -Be $content.Content.Length789 }790 791 It "Invoke-WebRequest -PassThru -OutFile <directory> saves the downloaded file path as a property in WebResponseObject"{792 $uri = Get-WebListenerUrl -Test 'Get'793 $content = Invoke-WebRequest -Uri $uri -PassThru -OutFile $TestDrive794 $content.OutFile | Should -exist795 $content.OutFile | Should -Be (Join-Path $TestDrive 'Get')796 }797 798 It "Invoke-WebRequest -PassThru -OutFile <file> saves the downloaded file path as a property in WebResponseObject"{799 $uri = Get-WebListenerUrl -Test 'Get'800 $filePath = Join-Path $TestDrive "pestertest-outfile"801 $content = Invoke-WebRequest -Uri $uri -PassThru -OutFile $filePath802 $content.OutFile | Should -exist803 $content.OutFile | Should -Be $filePath804 }805 806 It "Invoke-WebRequest -PassThru -OutFile -Verbose File Name reflects the downloaded file name" {807 $uri = Get-WebListenerUrl -Test 'Get'808 $filePath = Join-Path $TestDrive "pestertest-outfile"809 $content = Invoke-WebRequest -Verbose -Uri $uri -PassThru -OutFile $filePath 4>variable:verbo810 $verbo[-1].Message | Should -Match "pestertest-outfile"811 }812 813 It "Invoke-WebRequest should fail if -OutFile is <Name>." -TestCases @(814 @{ Name = "empty"; Value = [string]::Empty }815 @{ Name = "null"; Value = $null }816 ) {817 param ($value)818 $uri = Get-WebListenerUrl -Test 'Get'819 $errorId = "ParameterArgumentValidationError,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"820 { Invoke-WebRequest -Uri $uri -OutFile $value} | Should -Throw -ErrorId $errorId821 }822 823 It "Validate Invoke-WebRequest handles missing Content-Type in response header" {824 #Validate that exception is not thrown when response headers are missing Content-Type.825 $uri = Get-WebListenerUrl -Test 'ResponseHeaders' -Query @{'Content-Type' = ''}826 $command = "Invoke-WebRequest -Uri '$uri'"827 $result = ExecuteWebCommand -command $command828 $result.Error | Should -BeNullOrEmpty829 }830 831 It "Validate Invoke-WebRequest StandardMethod and CustomMethod parameter sets" {832 $uri = Get-WebListenerUrl -Test 'Get'833 #Validate that parameter sets are functioning correctly834 $errorId = "AmbiguousParameterSet,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"835 { Invoke-WebRequest -Uri $uri -Method GET -CustomMethod TEST } | Should -Throw -ErrorId $errorId836 }837 838 It "Validate Invoke-WebRequest CustomMethod method is used" {839 $uri = Get-WebListenerUrl -Test 'Get'840 $command = "Invoke-WebRequest -Uri '$uri' -CustomMethod TEST"841 $result = ExecuteWebCommand -command $command842 $result.Error | Should -BeNullOrEmpty843 ($result.Output.Content | ConvertFrom-Json).method | Should -Be "TEST"844 }845 846 It "Validate Invoke-WebRequest default ContentType for CustomMethod POST" {847 $uri = Get-WebListenerUrl -Test 'Post'848 $command = "Invoke-WebRequest -Uri '$uri' -CustomMethod POST -Body 'testparam=testvalue'"849 $result = ExecuteWebCommand -command $command850 $jsonResult = $result.Output.Content | ConvertFrom-Json851 $jsonResult.form.testparam | Should -Be "testvalue"852 $jsonResult.Headers.'Content-Type' | Should -Be "application/x-www-form-urlencoded"853 }854 855 It "Validate Invoke-WebRequest body is converted to query params for CustomMethod GET" {856 $uri = Get-WebListenerUrl -Test 'Get'857 $command = "Invoke-WebRequest -Uri '$uri' -CustomMethod GET -Body @{'testparam'='testvalue'}"858 $result = ExecuteWebCommand -command $command859 ($result.Output.Content | ConvertFrom-Json).args.testparam | Should -Be "testvalue"860 }861 862 It 'Validate Invoke-WebRequest empty body CustomMethod GET' {863 $uri = Get-WebListenerUrl -Test 'Get'864 $command = "Invoke-WebRequest -Uri '$uri' -CustomMethod GET"865 $result = ExecuteWebCommand -command $command866 $result.Output.Headers.'Content-Length' | Should -BeNullOrEmpty867 }868 869 It "Validate Invoke-WebRequest body is converted to query params for CustomMethod GET and -NoProxy" {870 $uri = Get-WebListenerUrl -Test 'Get'871 $command = "Invoke-WebRequest -Uri '$uri' -CustomMethod GET -Body @{'testparam'='testvalue'} -NoProxy"872 $result = ExecuteWebCommand -command $command873 ($result.Output.Content | ConvertFrom-Json).query | Should -Be "?testparam=testvalue"874 }875 876 It "Validate Invoke-WebRequest returns HTTP errors in exception" {877 $query = @{878 body = "I am a teapot!!!"879 statuscode = 418880 responsephrase = "I am a teapot"881 }882 $uri = Get-WebListenerUrl -Test 'Response' -Query $query883 $command = "Invoke-WebRequest -Uri '$uri'"884 $result = ExecuteWebCommand -command $command885 886 $result.Error.ErrorDetails.Message | Should -Be $query.body887 $result.Error.Exception | Should -BeOfType Microsoft.PowerShell.Commands.HttpResponseException888 $result.Error.Exception.Response.StatusCode | Should -Be 418889 $result.Error.Exception.Response.ReasonPhrase | Should -Be $query.responsephrase890 $result.Error.Exception.Message | Should -Match ": 418 \($($query.responsephrase)\)\."891 $result.Error.FullyQualifiedErrorId | Should -Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"892 }893 894 It "Validate Invoke-WebRequest returns <type> errors in exception" -TestCases @(895 @{ type = "XML"896 query = @{897 contenttype = 'application/xml'898 body = '<?xml version="1.0" encoding="UTF-8"?><Error><Code>418</Code><Message>I am a teapot!!!</Message></Error>'899 statuscode = 418900 responsephrase = "I am a teapot"901 }902 expectederror = $IsWindows ? "`r`n<Error>`r`n <Code>418</Code>`r`n <Message>I am a teapot!!!</Message>`r`n</Error>" : "`n<Error>`n <Code>418</Code>`n <Message>I am a teapot!!!</Message>`n</Error>"903 }904 905 @{ type = "Json"906 query = @{907 contenttype = 'application/json'908 body = '{"error":{"code":"418", "message":"I am a teapot!!!"}}'909 statuscode = 418910 responsephrase = "I am a teapot"911 }912 expectederror = $IsWindows ? "`r`n{`r`n `"error`": {`r`n `"code`": `"418`",`r`n `"message`": `"I am a teapot!!!`"`r`n }`r`n}" : "`n{`n `"error`": {`n `"code`": `"418`",`n `"message`": `"I am a teapot!!!`"`n }`n}"913 }914 ) {915 param($query, $expectederror)916 $uri = Get-WebListenerUrl -Test 'Response' -Query $query917 $command = "Invoke-WebRequest -Uri '$uri'"918 $result = ExecuteWebCommand -command $command919 920 $result.Error.ErrorDetails.Message | Should -Be $expectederror921 }922 923 It "Validate Invoke-WebRequest returns empty RelationLink property if there is no Link Header" {924 $uri = $uri = Get-WebListenerUrl -Test 'Get'925 $command = "Invoke-WebRequest -Uri '$uri'"926 $result = ExecuteWebCommand -command $command927 928 $result.Output.RelationLink.Count | Should -Be 0929 }930 931 It "Validate Invoke-WebRequest returns valid RelationLink property with absolute uris if Link Header is present <name>" -TestCases @(932 $originalUri = Get-WebListenerUrl -Test 'Link' -Query @{maxlinks = 5; linknumber = 2}933 @{name = '(URI with scheme)'; uri = $originalUri}934 @{name = '(URI without scheme)'; uri = $originalUri.OriginalString.Split("//")[1]}935 ) {936 param($uri)937 $command = "Invoke-WebRequest -Uri '$uri'"938 $result = ExecuteWebCommand -command $command939 940 $result.Output.RelationLink.Count | Should -BeExactly 5941 $baseUri = Get-WebListenerUrl -Test 'Link'942 $result.Output.RelationLink["next"] | Should -BeExactly "${baseUri}?maxlinks=5&linknumber=3&type=default"943 $result.Output.RelationLink["last"] | Should -BeExactly "${baseUri}?maxlinks=5&linknumber=5&type=default"944 $result.Output.RelationLink["prev"] | Should -BeExactly "${baseUri}?maxlinks=5&linknumber=1&type=default"945 $result.Output.RelationLink["first"] | Should -BeExactly "${baseUri}?maxlinks=5&linknumber=1&type=default"946 $result.Output.RelationLink["self"] | Should -BeExactly "${baseUri}?maxlinks=5&linknumber=2&type=default"947 }948 949 It "Validate Invoke-WebRequest returns valid RelationLink property with absolute uris if Multiple Link Headers are present" {950 $uri = Get-WebListenerUrl -Test 'Link' -Query @{maxlinks = 5; linknumber = 2; type = 'multiple'}951 $command = "Invoke-WebRequest -Uri '$uri'"952 $result = ExecuteWebCommand -command $command953 954 $result.Output.RelationLink.Count | Should -BeExactly 5955 $baseUri = Get-WebListenerUrl -Test 'Link'956 $result.Output.RelationLink["next"] | Should -BeExactly "${baseUri}?maxlinks=5&linknumber=3&type=multiple"957 $result.Output.RelationLink["last"] | Should -BeExactly "${baseUri}?maxlinks=5&linknumber=5&type=multiple"958 $result.Output.RelationLink["prev"] | Should -BeExactly "${baseUri}?maxlinks=5&linknumber=1&type=multiple"959 $result.Output.RelationLink["first"] | Should -BeExactly "${baseUri}?maxlinks=5&linknumber=1&type=multiple"960 $result.Output.RelationLink["self"] | Should -BeExactly "${baseUri}?maxlinks=5&linknumber=2&type=multiple"961 }962 963 964 It "Validate Invoke-WebRequest RelationLink keys are treated case-insensitively" {965 $uri = Get-WebListenerUrl -Test 'Link' -Query @{maxlinks = 5; linknumber = 2; type = 'multiple'}966 $command = "Invoke-WebRequest -Uri '$uri'"967 $result = ExecuteWebCommand -command $command968 969 $result.Output.RelationLink["next"] | Should -Not -BeNullOrEmpty970 $result.Output.RelationLink["next"] | Should -BeExactly $result.Output.RelationLink["Next"]971 972 $result.Output.RelationLink["last"] | Should -Not -BeNullOrEmpty973 $result.Output.RelationLink["last"] | Should -BeExactly $result.Output.RelationLink["LAST"]974 975 $result.Output.RelationLink["prev"] | Should -Not -BeNullOrEmpty976 $result.Output.RelationLink["prev"] | Should -BeExactly $result.Output.RelationLink["preV"]977 978 $result.Output.RelationLink["first"] | Should -Not -BeNullOrEmpty979 $result.Output.RelationLink["first"] | Should -BeExactly $result.Output.RelationLink["FiRsT"]980 981 $result.Output.RelationLink["self"] | Should -Not -BeNullOrEmpty982 $result.Output.RelationLink["self"] | Should -BeExactly $result.Output.RelationLink["self"]983 }984 985 It "Validate Invoke-WebRequest quietly ignores invalid Link Headers in RelationLink property: <type>" -TestCases @(986 @{ type = "noUrl" }987 @{ type = "malformed" }988 @{ type = "noRel" }989 ) {990 param($type)991 $uri = Get-WebListenerUrl -Test 'Link' -Query @{type = $type}992 $command = "Invoke-WebRequest -Uri '$uri'"993 $result = ExecuteWebCommand -command $command994 995 $result.Output.RelationLink.Count | Should -BeExactly 3996 $baseUri = Get-WebListenerUrl -Test 'Link'997 $result.Output.RelationLink["last"] | Should -BeExactly "${baseUri}?maxlinks=3&linknumber=3&type=${type}"998 $result.Output.RelationLink["first"] | Should -BeExactly "${baseUri}?maxlinks=3&linknumber=1&type=${type}"999 $result.Output.RelationLink["self"] | Should -BeExactly "${baseUri}?maxlinks=3&linknumber=1&type=${type}"1000 }1001 1002 It "Validate Invoke-WebRequest handles different whitespace for Link Headers: <type>" -TestCases @(1003 @{ type = "noWhitespace" }1004 @{ type = "extraWhitespace" }1005 ) {1006 param($type)1007 $uri = Get-WebListenerUrl -Test 'Link' -Query @{type = $type}1008 $command = "Invoke-WebRequest -Uri '$uri'"1009 $result = ExecuteWebCommand -command $command1010 1011 $result.Output.RelationLink.Count | Should -BeExactly 41012 $baseUri = Get-WebListenerUrl -Test 'Link'1013 $result.Output.RelationLink["last"] | Should -BeExactly "${baseUri}?maxlinks=3&linknumber=3&type=${type}"1014 $result.Output.RelationLink["first"] | Should -BeExactly "${baseUri}?maxlinks=3&linknumber=1&type=${type}"1015 $result.Output.RelationLink["self"] | Should -BeExactly "${baseUri}?maxlinks=3&linknumber=1&type=${type}"1016 $result.Output.RelationLink["next"] | Should -BeExactly "${baseUri}?maxlinks=3&linknumber=2&type=${type}"1017 }1018 1019 It "Verify Invoke-WebRequest supresses terminating errors with -SkipHttpErrorCheck" {1020 $uri = Get-WebListenerUrl -Test 'Response' -Query $NotFoundQuery1021 $command = "Invoke-WebRequest -SkipHttpErrorCheck -Uri '$uri'"1022 $result = ExecuteWebCommand -Command $command1023 $result.output.StatusCode | Should -Be 4041024 $result.output.Content | Should -BeExactly "oops"1025 $result.error | Should -BeNullOrEmpty1026 }1027 1028 It "Verify Invoke-WebRequest terminates without -SkipHttpErrorCheck" {1029 $uri = Get-WebListenerUrl -Test 'Response' -Query $NotFoundQuery1030 $command = "Invoke-WebRequest -Uri '$uri'"1031 $result = ExecuteWebCommand -Command $command1032 $result.output | Should -BeNullOrEmpty1033 $result.error | Should -Not -BeNullOrEmpty1034 }1035 1036 Context "Redirect" {1037 It "Validates Invoke-WebRequest with -PreserveAuthorizationOnRedirect preserves the authorization header on redirect: <redirectType> <redirectedMethod>" -TestCases $redirectTests {1038 param($redirectType, $redirectedMethod)1039 $uri = Get-WebListenerUrl -Test 'Redirect' -Query @{type = $redirectType}1040 $response = ExecuteRedirectRequest -Uri $uri -PreserveAuthorizationOnRedirect1041 1042 $response.Error | Should -BeNullOrEmpty1043 $response.Content.Headers."Authorization" | Should -BeExactly "test"1044 }1045 1046 It "Validates Invoke-WebRequest with -PreserveAuthorizationOnRedirect respects -MaximumRedirection on redirect: <redirectType> <redirectedMethod>" -TestCases $redirectTests {1047 param($redirectType, $redirectedMethod)1048 $uri = Get-WebListenerUrl -Test 'Redirect' -TestValue '3' -Query @{type = $redirectType}1049 $response = ExecuteRedirectRequest -Uri $uri -PreserveAuthorizationOnRedirect -MaximumRedirection 21050 1051 $response.Error.FullyQualifiedErrorId | Should -Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"1052 }1053 1054 It "Validates Invoke-WebRequest preserves the authorization header on multiple redirects: <redirectType>" -TestCases $redirectTests {1055 param($redirectType)1056 $uri = Get-WebListenerUrl -Test 'Redirect' -TestValue 3 -Query @{type = $redirectType}1057 $response = ExecuteRedirectRequest -Uri $uri -PreserveAuthorizationOnRedirect1058 1059 $response.Error | Should -BeNullOrEmpty1060 $response.Content.Headers."Authorization" | Should -BeExactly "test"1061 }1062 1063 It "Validates Invoke-WebRequest with -WebSession and -PreserveAuthorizationOnRedirect doesn't change session variable on multiple redirects: <redirectType>" -TestCases $redirectTests {1064 param($redirectType)1065 1066 #[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Demo/doc/test secret.")]1067 $token = "testpassword" | ConvertTo-SecureString -AsPlainText -Force1068 $credential = [pscredential]::new("testuser", $token)1069 $certificate = Get-WebListenerClientCertificate1070 $headers = @{"Authorization" = "test"}1071 $proxy = (Get-WebListenerUrl).Authority1072 $uri = Get-WebListenerUrl -Test 'Redirect' -TestValue 2 -Query @{type = $redirectType}1073 1074 $session = [Microsoft.PowerShell.Commands.WebRequestSession]::new()1075 $session.MaximumRedirection = 21076 $session.MaximumRetryCount = 21077 $session.RetryIntervalInSeconds = 21078 $session.UseDefaultCredentials = $true1079 $null = Invoke-WebRequest -Uri $uri -PreserveAuthorizationOnRedirect -WebSession $session -AllowUnencryptedAuthentication -Headers $headers1080 $session.MaximumRedirection | Should -BeExactly 21081 $session.MaximumRetryCount | Should -BeExactly 21082 $session.RetryIntervalInSeconds | Should -BeExactly 21083 $session.UseDefaultCredentials | Should -BeExactly $true1084 1085 $session = [Microsoft.PowerShell.Commands.WebRequestSession]::new()1086 $session.Credentials = $credential1087 $session.Certificates = [System.Security.Cryptography.X509Certificates.X509CertificateCollection]::new([X509Certificate]$certificate)1088 $null = Invoke-WebRequest -Uri $uri -PreserveAuthorizationOnRedirect -WebSession $session -SkipCertificateCheck -Headers $headers1089 $session.Credentials.UserName | Should -BeExactly $credential.UserName1090 $session.Credentials.Password | Should -BeExactly $credential.GetNetworkCredential().Password1091 $session.Certificates.Thumbprint | Should -BeExactly $certificate.Thumbprint1092 1093 $session = [Microsoft.PowerShell.Commands.WebRequestSession]::new()1094 $session.Proxy = [System.Net.WebProxy]::new($proxy)1095 $null = Invoke-WebRequest -Uri $uri -PreserveAuthorizationOnRedirect -WebSession $session -Headers $headers1096 $session.Proxy.GetProxy($uri).Authority | Should -BeExactly $proxy1097 }1098 1099 It "Validates Invoke-WebRequest strips the authorization header on various redirects: <redirectType>" -TestCases $redirectTests {1100 param($redirectType)1101 $uri = Get-WebListenerUrl -Test 'Redirect' -Query @{type = $redirectType}1102 $response = ExecuteRedirectRequest -Uri $uri1103 1104 $response.Error | Should -BeNullOrEmpty1105 # ensure user-agent is present (i.e., no false positives )1106 $response.Content.Headers."User-Agent" | Should -Not -BeNullOrEmpty1107 # ensure Authorization header has been removed.1108 $response.Content.Headers."Authorization" | Should -BeNullOrEmpty1109 }1110 1111 # NOTE: Only testing redirection of POST -> GET for unique underlying values of HttpStatusCode.1112 # Some names overlap in underlying value.1113 It "Validates Invoke-WebRequest strips the authorization header redirects and switches from POST to GET when it handles the redirect: <redirectType> <redirectedMethod>" -TestCases $redirectTests {1114 param($redirectType, $redirectedMethod)1115 $uri = Get-WebListenerUrl -Test 'Redirect' -Query @{type = $redirectType}1116 $response = ExecuteRedirectRequest -Uri $uri -Method 'POST'1117 1118 $response.Error | Should -BeNullOrEmpty1119 # ensure user-agent is present (i.e., no false positives )1120 $response.Content.Headers."User-Agent" | Should -Not -BeNullOrEmpty1121 # ensure Authorization header has been removed.1122 $response.Content.Headers."Authorization" | Should -BeNullOrEmpty1123 # ensure POST was changed to GET for selected redirections and remains as POST for others.1124 $response.Content.Method | Should -Be $redirectedMethod1125 }1126 1127 It "Validates Invoke-WebRequest -PreserveAuthorizationOnRedirect keeps the authorization header redirects and switches from POST to GET when it handles the redirect: <redirectType> <redirectedMethod>" -TestCases $redirectTests {1128 param($redirectType, $redirectedMethod)1129 $uri = Get-WebListenerUrl -Test 'Redirect' -Query @{type = $redirectType}1130 $response = ExecuteRedirectRequest -PreserveAuthorizationOnRedirect -Uri $uri -Method 'POST'1131 1132 $response.Error | Should -BeNullOrEmpty1133 # ensure user-agent is present (i.e., no false positives )1134 $response.Content.Headers."User-Agent" | Should -Not -BeNullOrEmpty1135 # ensure Authorization header has been preserved.1136 $response.Content.Headers."Authorization" | Should -BeExactly 'test'1137 # ensure POST was changed to GET for selected redirections and remains as POST for others.1138 $response.Content.Method | Should -Be $redirectedMethod1139 }1140 1141 It "Validates Invoke-WebRequest -PreserveAuthorizationOnRedirect -CustomMethod POST keeps the authorization header redirects and switches from POST to GET when it handles the redirect: <redirectType> <redirectedMethod>" -TestCases $redirectTests {1142 param($redirectType, $redirectedMethod)1143 $uri = Get-WebListenerUrl -Test 'Redirect' -Query @{type = $redirectType}1144 1145 $response = ExecuteRedirectRequest -PreserveAuthorizationOnRedirect -Uri $uri -CustomMethod 'POST'1146 1147 $response.Error | Should -BeNullOrEmpty1148 # ensure user-agent is present (i.e., no false positives )1149 $response.Content.Headers."User-Agent" | Should -Not -BeNullOrEmpty1150 # ensure Authorization header has been preserved.1151 $response.Content.Headers."Authorization" | Should -BeExactly 'test'1152 # ensure POST was changed to GET for selected redirections and remains as POST for others.1153 $response.Content.Method | Should -Be $redirectedMethod1154 }1155 1156 It "Validates Invoke-WebRequest -PreserveHttpMethodOnRedirect keeps the authorization header redirects and do remains POST when it handles the redirect: <redirectType>" -TestCases $redirectTests {1157 param($redirectType)1158 $uri = Get-WebListenerUrl -Test 'Redirect' -Query @{type = $redirectType}1159 $response = ExecuteRedirectRequest -PreserveHttpMethodOnRedirect -Uri $uri -Method 'POST'1160 1161 $response.Error | Should -BeNullOrEmpty1162 # ensure user-agent is present (i.e., no false positives )1163 $response.Content.Headers."User-Agent" | Should -Not -BeNullOrEmpty1164 # ensure Authorization header has been kept.1165 $response.Content.Headers."Authorization" | Should -BeExactly 'test'1166 # ensure POST doesn't change.1167 $response.Content.Method | Should -Be 'POST'1168 }1169 1170 It "Validates Invoke-WebRequest handles responses without Location header for requests with Authorization header and redirect: <redirectType>" -TestCases $redirectTests {1171 param($redirectType, $redirectedMethod)1172 # Skip relative test as it is not a valid response type.1173 if ($redirectType -eq 'relative') { return }1174 1175 # When an Authorization request header is present,1176 # and -PreserveAuthorizationOnRedirect is not present,1177 # PowerShell should throw an HTTP Response Exception1178 # for a redirect response which does not contain a Location response header.1179 # The correct redirect status code should be included in the exception.1180 1181 $StatusCode = [int][System.Net.HttpStatusCode]$redirectType1182 $uri = Get-WebListenerUrl -Test Response -Query @{statuscode = $StatusCode}1183 $command = "Invoke-WebRequest -Uri '$uri' -Headers @{Authorization = 'foo'}"1184 $response = ExecuteWebCommand -command $command1185 1186 $response.Error.Exception | Should -BeOfType Microsoft.PowerShell.Commands.HttpResponseException1187 $response.Error.Exception.Response.StatusCode | Should -Be $StatusCode1188 $response.Error.Exception.Response.Headers.Location | Should -BeNullOrEmpty1189 }1190 1191 It "Validate Invoke-WebRequest Https to Http redirect with -AllowInsecureRedirect" {1192 $httpUri = Get-WebListenerUrl -Test 'Get'1193 $uri = Get-WebListenerUrl -Test 'Redirect' -Https -Query @{destination = $httpUri}1194 $command = "Invoke-WebRequest -Uri '$uri' -SkipCertificateCheck -AllowInsecureRedirect"1195 1196 $result = ExecuteWebCommand -command $command1197 $jsonContent = $result.Output.Content | ConvertFrom-Json1198 $jsonContent.headers.Host | Should -Match $httpUri.Authority1199 }1200 