2020-03-24 11:08:37 -07:00
# Copyright (c) Microsoft Corporation.
2018-02-13 09:23:53 -08:00
# Licensed under the MIT License.
2016-07-22 15:09:03 -07:00
# This is a Pester test suite which validate the Web cmdlets.
#
2017-12-13 09:28:05 -06:00
# Note: These tests use data from WebListener
2016-07-22 15:09:03 -07:00
#
# Invokes the given command via script block invocation.
#
2018-01-09 15:43:25 -06:00
function ExecuteWebCommand {
2016-07-22 15:09:03 -07:00
param (
[ ValidateNotNullOrEmpty ()]
[ string ]
$command
)
2017-01-16 13:31:14 -08:00
2016-07-22 15:09:03 -07:00
$result = [ PSObject ] @ { Output = $null ; Error = $null }
2018-01-09 15:43:25 -06:00
try {
2016-07-22 15:09:03 -07:00
$scriptBlock = [ scriptblock ]:: Create ( $command )
2018-01-09 15:43:25 -06:00
$result . Output = & $scriptBlock
} catch {
2016-07-22 15:09:03 -07:00
$result . Error = $_
}
return $result
}
# This function calls either Invoke-WebRequest or Invoke-RestMethod using the OutFile parameter
# Then, the file content is read and return in a $result object.
#
2018-01-09 15:43:25 -06:00
function ExecuteRequestWithOutFile {
2016-07-22 15:09:03 -07:00
param (
2017-01-16 13:31:14 -08:00
[ ValidateSet ( "Invoke-RestMethod" , "Invoke-WebRequest" )]
2016-07-22 15:09:03 -07:00
[ string ]
$cmdletName ,
2018-01-09 15:43:25 -06:00
2016-07-22 15:09:03 -07:00
[ string ]
2017-09-07 22:53:04 -05:00
$uri = ( Get-WebListenerUrl -Test 'Get' )
2016-07-22 15:09:03 -07:00
)
2017-01-16 13:31:14 -08:00
2016-07-22 15:09:03 -07:00
$result = [ PSObject ] @ { Output = $null ; Error = $null }
2020-05-21 03:17:02 +05:00
# We use '[outfile1]' in the file name to check that OutFile parameter is literal path
$filePath = Join-Path $TestDrive (( Get-Random ). ToString () + "[outfile1].txt" )
2018-01-09 15:43:25 -06:00
try {
if ( $cmdletName -eq "Invoke-WebRequest" ) {
2016-07-22 15:09:03 -07:00
Invoke-WebRequest -Uri $uri -OutFile $filePath
2018-01-09 15:43:25 -06:00
} else {
2016-07-22 15:09:03 -07:00
Invoke-RestMethod -Uri $uri -OutFile $filePath
}
2020-05-21 03:17:02 +05:00
$result . Output = Get-Content -LiteralPath $filePath -Raw -ErrorAction SilentlyContinue
2018-01-09 15:43:25 -06:00
} catch {
2016-07-22 15:09:03 -07:00
$result . Error = $_
2018-01-09 15:43:25 -06:00
} finally {
if ( Test-Path $filePath ) {
2018-05-17 14:42:04 -07:00
Remove-Item $filePath -Force -ErrorAction SilentlyContinue
2016-07-22 15:09:03 -07:00
}
}
return $result
}
2017-01-16 13:31:14 -08:00
# This function calls either Invoke-WebRequest or Invoke-RestMethod with the given uri
2016-07-22 15:09:03 -07:00
# using the Headers parameter to disable keep-alive.
#
2018-01-09 15:43:25 -06:00
function ExecuteRequestWithHeaders {
2016-07-22 15:09:03 -07:00
param (
2017-01-16 13:31:14 -08:00
[ ValidateSet ( "Invoke-RestMethod" , "Invoke-WebRequest" )]
2016-07-22 15:09:03 -07:00
[ string ]
$cmdletName ,
2018-01-09 15:43:25 -06:00
2016-07-22 15:09:03 -07:00
[ string ]
2017-09-07 22:53:04 -05:00
$uri = ( Get-WebListenerUrl -Test 'Get' )
2016-07-22 15:09:03 -07:00
)
2017-01-16 13:31:14 -08:00
2016-07-22 15:09:03 -07:00
$result = [ PSObject ] @ { Output = $null ; Error = $null }
2018-01-09 15:43:25 -06:00
try {
2016-07-22 15:09:03 -07:00
$headers = @ { Connection = 'close' }
2018-01-09 15:43:25 -06:00
if ( $cmdletName -eq "Invoke-WebRequest" ) {
2018-02-02 13:56:06 -06:00
$result . Output = Invoke-WebRequest -Uri $uri -Headers $headers
2018-01-09 15:43:25 -06:00
} else {
2018-02-02 13:56:06 -06:00
$result . Output = Invoke-RestMethod -Uri $uri -Headers $headers
2016-07-22 15:09:03 -07:00
}
2018-01-09 15:43:25 -06:00
} catch {
2016-07-22 15:09:03 -07:00
$result . Error = $_
}
return $result
}
# Returns test data for the given content type.
#
2018-01-09 15:43:25 -06:00
function GetTestData {
param (
2016-07-22 15:09:03 -07:00
[ ValidateSet ( "text/plain" , "application/xml" , "application/json" )]
[ String ]
$contentType
)
$testData = @ { ItemID = 987123 ; Name = 'TestData' }
2018-01-09 15:43:25 -06:00
if ( $contentType -eq "text/plain" ) {
2016-07-22 15:09:03 -07:00
$body = $testData | Out-String
2018-01-09 15:43:25 -06:00
} elseif ( $contentType -eq "application/xml" ) {
2016-07-22 15:09:03 -07:00
$body = '
<?xml version="1.0" encoding="utf-8"?>
<Objects>
<Object>
<ItemID>987123</ItemID>
<Name>TestData</Name>
</Object>
</Objects>
'
2018-01-09 15:43:25 -06:00
} else {
# "application/json"
2016-07-22 15:09:03 -07:00
$body = $testData | ConvertTo-Json -Compress
}
return $body
}
2018-01-09 15:43:25 -06:00
function ExecuteRedirectRequest {
2017-06-15 15:52:08 -07:00
param (
[ Parameter ( Mandatory )]
[ string ]
$uri ,
[ ValidateSet ( 'Invoke-WebRequest' , 'Invoke-RestMethod' )]
2018-01-09 15:43:25 -06:00
[ string ]
$Cmdlet = 'Invoke-WebRequest' ,
2017-06-15 15:52:08 -07:00
[ ValidateSet ( 'POST' , 'GET' )]
2018-01-09 15:43:25 -06:00
[ string ]
$Method = 'GET' ,
2017-06-15 15:52:08 -07:00
2023-02-10 12:14:29 +01:00
[ ValidateSet ( 'POST' )]
[ string ]
$CustomMethod ,
2018-01-09 15:43:25 -06:00
[ switch ]
2023-01-13 14:31:03 +01:00
$PreserveAuthorizationOnRedirect ,
2023-02-14 17:40:42 +01:00
[ switch ]
$PreserveHttpMethodOnRedirect ,
2023-01-13 14:31:03 +01:00
[ ValidateRange ( 0 , [ int ]:: MaxValue )]
[ int ]
$MaximumRedirection
2017-06-15 15:52:08 -07:00
)
$result = [ PSObject ] @ { Output = $null ; Error = $null ; Content = $null }
2018-01-09 15:43:25 -06:00
try {
2017-06-15 15:52:08 -07:00
$headers = @ { "Authorization" = "test" }
2018-01-09 15:43:25 -06:00
if ( $Cmdlet -eq 'Invoke-WebRequest' ) {
2023-01-13 14:31:03 +01:00
if ( $MaximumRedirection -gt 0 ) {
$result . Output = Invoke-WebRequest -Uri $uri -Headers $headers -PreserveAuthorizationOnRedirect: $PreserveAuthorizationOnRedirect . IsPresent -Method $Method -MaximumRedirection: $MaximumRedirection
2023-02-10 12:14:29 +01:00
} elseif ( $CustomMethod ) {
$result . Output = Invoke-WebRequest -Uri $uri -Headers $headers -PreserveAuthorizationOnRedirect: $PreserveAuthorizationOnRedirect . IsPresent -CustomMethod $CustomMethod
2023-01-13 14:31:03 +01:00
} else {
2023-02-14 17:40:42 +01:00
$result . Output = Invoke-WebRequest -Uri $uri -Headers $headers -PreserveAuthorizationOnRedirect: $PreserveAuthorizationOnRedirect . IsPresent -PreserveHttpMethodOnRedirect: $PreserveHttpMethodOnRedirect . IsPresent -Method $Method
2023-01-13 14:31:03 +01:00
}
2017-06-15 15:52:08 -07:00
$result . Content = $result . Output . Content | ConvertFrom-Json
2018-01-09 15:43:25 -06:00
} else {
2023-02-10 12:14:29 +01:00
if ( $MaximumRedirection -gt 0 ) {
$result . Output = Invoke-RestMethod -Uri $uri -Headers $headers -PreserveAuthorizationOnRedirect: $PreserveAuthorizationOnRedirect . IsPresent -Method $Method -MaximumRedirection: $MaximumRedirection
} elseif ( $CustomMethod ) {
$result . Output = Invoke-RestMethod -Uri $uri -Headers $headers -PreserveAuthorizationOnRedirect: $PreserveAuthorizationOnRedirect . IsPresent -CustomMethod $CustomMethod
} else {
2023-02-14 17:40:42 +01:00
$result . Output = Invoke-RestMethod -Uri $uri -Headers $headers -PreserveAuthorizationOnRedirect: $PreserveAuthorizationOnRedirect . IsPresent -PreserveHttpMethodOnRedirect: $PreserveHttpMethodOnRedirect . IsPresent -Method $Method
2023-02-10 12:14:29 +01:00
}
2017-06-15 15:52:08 -07:00
# NOTE: $result.Output should already be a PSObject (Invoke-RestMethod converts the returned json automatically)
# so simply reference $result.Output
$result . Content = $result . Output
2017-07-07 09:25:46 -07:00
}
2018-01-09 15:43:25 -06:00
} catch {
2017-06-15 15:52:08 -07:00
$result . Error = $_
}
return $result
}
2017-07-14 10:24:20 -07:00
# This function calls either Invoke-WebRequest or Invoke-RestMethod with the given uri
2017-09-04 19:45:51 -07:00
# using the custum headers and the optional SkipHeaderValidation switch.
2018-01-09 15:43:25 -06:00
function ExecuteRequestWithCustomHeaders {
2017-07-14 10:24:20 -07:00
param (
[ Parameter ( Mandatory )]
[ string ]
$Uri ,
[ ValidateSet ( 'Invoke-WebRequest' , 'Invoke-RestMethod' )]
2018-01-09 15:43:25 -06:00
[ string ]
$Cmdlet = 'Invoke-WebRequest' ,
2017-07-14 10:24:20 -07:00
[ Parameter ( Mandatory )]
[ ValidateNotNull ()]
2018-01-09 15:43:25 -06:00
[ Hashtable ]
$Headers ,
2017-07-14 10:24:20 -07:00
2018-01-09 15:43:25 -06:00
[ switch ]
$SkipHeaderValidation
2017-07-14 10:24:20 -07:00
)
$result = [ PSObject ] @ { Output = $null ; Error = $null ; Content = $null }
2018-01-09 15:43:25 -06:00
try {
if ( $Cmdlet -eq 'Invoke-WebRequest' ) {
2018-02-02 13:56:06 -06:00
$result . Output = Invoke-WebRequest -Uri $Uri -Headers $Headers -SkipHeaderValidation: $SkipHeaderValidation . IsPresent
2017-07-14 10:24:20 -07:00
$result . Content = $result . Output . Content | ConvertFrom-Json
2018-01-09 15:43:25 -06:00
} else {
2018-02-02 13:56:06 -06:00
$result . Output = Invoke-RestMethod -Uri $Uri -Headers $Headers -SkipHeaderValidation: $SkipHeaderValidation . IsPresent
2017-07-14 10:24:20 -07:00
# NOTE: $result.Output should already be a PSObject (Invoke-RestMethod converts the returned json automatically)
# so simply reference $result.Output
$result . Content = $result . Output
}
2018-01-09 15:43:25 -06:00
} catch {
2017-07-14 10:24:20 -07:00
$result . Error = $_
}
return $result
}
2017-08-04 11:10:24 -05:00
# This function calls either Invoke-WebRequest or Invoke-RestMethod with the given uri
2017-09-04 19:45:51 -07:00
# using the custom UserAgent and the optional SkipHeaderValidation switch.
2017-08-04 11:10:24 -05:00
function ExecuteRequestWithCustomUserAgent {
param (
[ Parameter ( Mandatory )]
[ string ]
$Uri ,
[ ValidateSet ( 'Invoke-WebRequest' , 'Invoke-RestMethod' )]
2018-01-09 15:43:25 -06:00
[ string ]
$Cmdlet = 'Invoke-WebRequest' ,
2017-08-04 11:10:24 -05:00
[ Parameter ( Mandatory )]
[ ValidateNotNull ()]
2018-01-09 15:43:25 -06:00
[ string ]
$UserAgent ,
2017-08-04 11:10:24 -05:00
2018-01-09 15:43:25 -06:00
[ switch ]
$SkipHeaderValidation
2017-08-04 11:10:24 -05:00
)
$result = [ PSObject ] @ { Output = $null ; Error = $null ; Content = $null }
try {
$Params = @ {
2023-06-20 08:07:16 +10:00
Uri = $Uri
ConnectionTimeoutSeconds = 5
UserAgent = $UserAgent
SkipHeaderValidation = $SkipHeaderValidation . IsPresent
2017-08-04 11:10:24 -05:00
}
if ( $Cmdlet -eq 'Invoke-WebRequest' ) {
$result . Output = Invoke-WebRequest @Params
$result . Content = $result . Output . Content | ConvertFrom-Json
2018-01-09 15:43:25 -06:00
} else {
2017-08-04 11:10:24 -05:00
$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
}
2018-01-09 15:43:25 -06:00
} catch {
2017-08-04 11:10:24 -05:00
$result . Error = $_
}
return $result
}
2017-08-16 16:25:16 -07:00
# This function calls Invoke-WebRequest with the given uri
2018-01-09 15:43:25 -06:00
function ExecuteWebRequest {
2017-08-16 16:25:16 -07:00
param (
[ Parameter ( Mandatory )]
[ string ]
$Uri ,
2018-01-09 15:43:25 -06:00
[ switch ]
$UseBasicParsing
2017-08-16 16:25:16 -07:00
)
2018-01-09 15:43:25 -06:00
$result = [ PSObject ] @ { Output = $null ; Error = $null ; Content = $null }
2017-08-16 16:25:16 -07:00
2018-01-09 15:43:25 -06:00
try {
2018-02-02 13:56:06 -06:00
$result . Output = Invoke-WebRequest -Uri $Uri -UseBasicParsing: $UseBasicParsing . IsPresent
2017-08-16 16:25:16 -07:00
$result . Content = $result . Output . Content
2018-01-09 15:43:25 -06:00
} catch {
2017-08-16 16:25:16 -07:00
$result . Error = $_
}
return $result
}
2025-06-10 21:50:26 -07:00
[ string ] $debugEncodingPrefix = 'WebResponse content encoding: '
2017-08-31 10:47:54 -07:00
# This function calls Invoke-WebRequest with the given uri and
# parses the verbose output to determine the encoding used for the content.
2018-01-09 15:43:25 -06:00
function ExecuteRestMethod {
param (
2017-08-31 10:47:54 -07:00
[ Parameter ( Mandatory )]
[ string ]
$Uri ,
2018-01-09 15:43:25 -06:00
[ switch ]
$UseBasicParsing
2017-08-31 10:47:54 -07:00
)
$result = @ { Output = $null ; Error = $null ; Encoding = $null ; Content = $null }
2025-06-10 21:50:26 -07:00
$debugPreferenceSave = $DebugPreference
$DebugPreference = 'Continue'
2018-01-09 15:43:25 -06:00
try {
2025-06-10 21:50:26 -07:00
$debugFile = Join-Path $TestDrive -ChildPath ExecuteRestMethod . debug . txt
$result . Output = Invoke-RestMethod -Uri $Uri -UseBasicParsing: $UseBasicParsing . IsPresent 5 > $debugFile
2017-08-31 10:47:54 -07:00
$result . Content = $result . Output
2025-06-10 21:50:26 -07:00
# 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.
# This debug output is defined in InvokeRestMethodCommand.Common.cs ProcessResponse()
if ( Test-Path -Path $debugFile ) {
$result . Debug = Get-Content -Path $debugFile
foreach ( $item in $result . Debug ) {
2017-08-31 10:47:54 -07:00
$line = $item . Trim ()
2025-06-10 21:50:26 -07:00
if ( $line . StartsWith ( $debugEncodingPrefix )) {
$encodingName = [ int ]:: Parse ( $item . SubString ( $EncodingPrefix . Length ). Split ( 'CodePage: ' )[ 1 ]. Trim ())
2017-08-31 10:47:54 -07:00
$result . Encoding = [ System.Text.Encoding ]:: GetEncoding ( $encodingName )
break
}
}
2025-06-10 21:50:26 -07:00
if ( $null -eq $result . Encoding ) {
throw "Encoding not found in debug output. Lines: $( $result . Debug . Count ) Content: $( $result . Debug ) "
2017-08-31 10:47:54 -07:00
}
}
2025-06-10 21:50:26 -07:00
if ( $null -eq $result . Debug ) {
throw "No debug output was found"
2017-08-31 10:47:54 -07:00
}
2018-01-09 15:43:25 -06:00
} catch {
2020-05-07 13:00:30 +01:00
$result . Error = $_ | Select-Object * | Out-String
2018-01-09 15:43:25 -06:00
} finally {
2025-06-10 21:50:26 -07:00
$DebugPreference = $debugPreferenceSave
if ( Test-Path -Path $debugFile ) {
Remove-Item -Path $debugFile -ErrorAction SilentlyContinue
2017-08-31 10:47:54 -07:00
}
}
return $result
}
2018-01-09 15:43:25 -06:00
function GetMultipartBody {
param (
[ Switch ]
$String ,
[ Switch ]
$File
2017-09-12 11:41:36 -05:00
)
$multipartContent = [ System.Net.Http.MultipartFormDataContent ]:: new ()
2018-01-09 15:43:25 -06:00
if ( $String . IsPresent ) {
2017-09-12 11:41:36 -05:00
$stringHeader = [ System.Net.Http.Headers.ContentDispositionHeaderValue ]:: new ( "form-data" )
$stringHeader . Name = "TestString"
$StringContent = [ System.Net.Http.StringContent ]:: new ( "TestValue" )
$StringContent . Headers . ContentDisposition = $stringHeader
$multipartContent . Add ( $stringContent )
}
2018-01-09 15:43:25 -06:00
if ( $File . IsPresent ) {
2017-09-12 11:41:36 -05:00
$multipartFile = Join-Path $TestDrive 'multipart.txt'
"TestContent" | Set-Content $multipartFile
$FileStream = [ System.IO.FileStream ]:: new ( $multipartFile , [ System.IO.FileMode ]:: Open )
$fileHeader = [ System.Net.Http.Headers.ContentDispositionHeaderValue ]:: new ( "form-data" )
$fileHeader . Name = "TestFile"
$fileHeader . FileName = 'multipart.txt'
$fileContent = [ System.Net.Http.StreamContent ]:: new ( $FileStream )
$fileContent . Headers . ContentDisposition = $fileHeader
$fileContent . Headers . ContentType = [ System.Net.Http.Headers.MediaTypeHeaderValue ]:: Parse ( "text/plain" )
$multipartContent . Add ( $fileContent )
}
# unary comma required to prevent $multipartContent from being unwrapped/enumerated
2018-01-09 15:43:25 -06:00
return , $multipartContent
2017-09-12 11:41:36 -05:00
}
2017-06-15 15:52:08 -07:00
<#
Defines the list of redirect codes to test as well as the
expected Method when the redirection is handled.
2023-07-17 17:54:17 -05:00
See https://learn.microsoft.com/dotnet/api/system.net.httpstatuscode
2017-06-15 15:52:08 -07:00
for additonal details.
#>
$redirectTests = @ (
2018-05-14 13:37:30 -05:00
@ { redirectType = 'MultipleChoices' ; redirectedMethod = 'GET' }
@ { redirectType = 'Ambiguous' ; redirectedMethod = 'GET' } # Synonym for MultipleChoices
2017-06-15 15:52:08 -07:00
2018-01-09 15:43:25 -06:00
@ { redirectType = 'Moved' ; redirectedMethod = 'GET' }
@ { redirectType = 'MovedPermanently' ; redirectedMethod = 'GET' } # Synonym for Moved
2017-06-15 15:52:08 -07:00
2018-01-09 15:43:25 -06:00
@ { redirectType = 'Found' ; redirectedMethod = 'GET' }
@ { redirectType = 'Redirect' ; redirectedMethod = 'GET' } # Synonym for Found
2017-06-15 15:52:08 -07:00
2018-01-09 15:43:25 -06:00
@ { redirectType = 'redirectMethod' ; redirectedMethod = 'GET' }
@ { redirectType = 'SeeOther' ; redirectedMethod = 'GET' } # Synonym for RedirectMethod
2017-06-15 15:52:08 -07:00
2018-05-14 13:37:30 -05:00
@ { redirectType = 'TemporaryRedirect' ; redirectedMethod = 'POST' }
@ { redirectType = 'RedirectKeepVerb' ; redirectedMethod = 'POST' } # Synonym for TemporaryRedirect
2018-03-09 08:28:20 -08:00
@ { redirectType = 'relative' ; redirectedMethod = 'GET' }
2017-06-15 15:52:08 -07:00
)
2018-12-11 14:15:33 -08:00
Describe "Invoke-WebRequest tests" -Tags "Feature" , "RequireAdminOnWindows" {
2017-05-24 15:54:02 -07:00
BeforeAll {
2022-01-03 11:20:33 -08:00
$oldProgress = $ProgressPreference
$ProgressPreference = 'SilentlyContinue'
2017-08-31 04:30:35 -05:00
$WebListener = Start-WebListener
2019-11-07 12:38:24 -08:00
$NotFoundQuery = @ {
statuscode = 404
responsephrase = 'Not Found'
contenttype = 'text/plain'
body = 'oops'
headers = "{}"
}
2017-05-24 15:54:02 -07:00
}
2022-01-03 11:20:33 -08:00
AfterAll {
$ProgressPreference = $oldProgress
}
2016-07-22 15:09:03 -07:00
# Validate the output of Invoke-WebRequest
#
2018-01-09 15:43:25 -06:00
function ValidateResponse {
2016-07-22 15:09:03 -07:00
param ( $response )
2018-03-01 23:00:00 -06:00
$response . Error | Should -Be $null
2016-07-22 15:09:03 -07:00
2016-08-25 17:49:32 +00:00
# A successful call returns: Status = 200, and StatusDescription = "OK"
2018-03-01 23:00:00 -06:00
$response . Output . StatusDescription | Should -Match "OK"
$response . Output . StatusCode | Should -Be 200
2016-07-22 15:09:03 -07:00
# Make sure the response contains the following properties:
2018-03-01 23:00:00 -06:00
$response . Output . RawContent | Should -Not -Be $null
$response . Output . Headers | Should -Not -Be $null
$response . Output . RawContent | Should -Not -Be $null
$response . Output . RawContentLength | Should -Not -Be $null
$response . Output . Content | Should -Not -Be $null
2016-07-22 15:09:03 -07:00
}
2017-10-06 22:59:31 +02:00
#User-Agent changes on different platforms, so tests should only be run if on the correct platform
It "Invoke-WebRequest returns Correct User-Agent on MacOSX" -Skip: (! $IsMacOS ) {
$uri = Get-WebListenerUrl -Test 'Get'
2018-02-02 13:56:06 -06:00
$command = "Invoke-WebRequest -Uri ' $uri '"
2017-10-06 22:59:31 +02:00
$result = ExecuteWebCommand -command $command
ValidateResponse -response $result
# Validate response content
$jsonContent = $result . Output . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$jsonContent . headers . 'User-Agent' | Should -MatchExactly '.*\(Macintosh;.*\) PowerShell\/\d+\.\d+\.\d+.*'
2017-10-06 22:59:31 +02:00
}
It "Invoke-WebRequest returns Correct User-Agent on Linux" -Skip: (! $IsLinux ) {
$uri = Get-WebListenerUrl -Test 'Get'
2018-02-02 13:56:06 -06:00
$command = "Invoke-WebRequest -Uri ' $uri '"
2017-10-06 22:59:31 +02:00
$result = ExecuteWebCommand -command $command
ValidateResponse -response $result
# Validate response content
$jsonContent = $result . Output . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$jsonContent . headers . 'User-Agent' | Should -MatchExactly '.*\(Linux;.*\) PowerShell\/\d+\.\d+\.\d+.*'
2017-10-06 22:59:31 +02:00
}
It "Invoke-WebRequest returns Correct User-Agent on Windows" -Skip: (! $IsWindows ) {
2017-09-14 00:23:29 -05:00
$uri = Get-WebListenerUrl -Test 'Get'
2018-02-02 13:56:06 -06:00
$command = "Invoke-WebRequest -Uri ' $uri '"
2017-01-16 13:31:14 -08:00
2016-07-22 15:09:03 -07:00
$result = ExecuteWebCommand -command $command
ValidateResponse -response $result
# Validate response content
$jsonContent = $result . Output . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$jsonContent . headers . 'User-Agent' | Should -MatchExactly '.*\(Windows NT \d+\.\d*;.*\) PowerShell\/\d+\.\d+\.\d+.*'
2016-07-22 15:09:03 -07:00
}
It "Invoke-WebRequest returns headers dictionary" {
2017-09-14 00:22:52 -05:00
$uri = Get-WebListenerUrl -Test 'Get'
2018-02-02 13:56:06 -06:00
$command = "Invoke-WebRequest -Uri ' $uri '"
2017-01-16 13:31:14 -08:00
2016-07-22 15:09:03 -07:00
$result = ExecuteWebCommand -command $command
ValidateResponse -response $result
# Validate response content
$jsonContent = $result . Output . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$jsonContent . headers . Host | Should -Be $Uri . Authority
2016-07-22 15:09:03 -07:00
}
2020-01-06 12:11:55 -08:00
It "Invoke-WebRequest with blank ContentType succeeds" {
$uri = Get-WebListenerUrl -Test 'Get'
$command = "Invoke-WebRequest -Uri ' $uri ' -ContentType ''"
$result = ExecuteWebCommand -command $command
# Validate response
ValidateResponse -response $result
2022-01-03 11:20:33 -08:00
$result . Output . Headers . 'Content-Length' | Should -BeNullOrEmpty
2020-01-06 12:11:55 -08:00
}
2016-07-22 15:09:03 -07:00
It "Validate Invoke-WebRequest -DisableKeepAlive" {
# Operation options
2017-09-07 22:53:04 -05:00
$uri = Get-WebListenerUrl -Test 'Get'
2018-02-02 13:56:06 -06:00
$command = "Invoke-WebRequest -Uri $uri -DisableKeepAlive"
2016-07-22 15:09:03 -07:00
$result = ExecuteWebCommand -command $command
ValidateResponse -response $result
2018-03-01 23:00:00 -06:00
$result . Output . Headers . Connection | Should -Be "Close"
2016-07-22 15:09:03 -07:00
}
2021-11-03 02:53:36 +03:00
It "Validate Invoke-WebRequest -HttpVersion '<httpVersion>'" -Skip: (! $IsWindows ) -TestCases @ (
@ { httpVersion = '1.1' },
@ { httpVersion = '2' }
) {
param ( $httpVersion )
2023-08-16 11:28:59 -07:00
if ( Test-IsWinServer2012R2 -and $httpVersion -eq '2' ) {
Set-ItResult -Skipped -Because "HTTP/2 is not supported on Windows Server 2012R2"
return
}
2021-11-03 02:53:36 +03:00
# Operation options
$uri = Get-WebListenerUrl -Test 'Get' -Https
$command = "Invoke-WebRequest -Uri $uri -HttpVersion $httpVersion -SkipCertificateCheck"
$result = ExecuteWebCommand -command $command
ValidateResponse -response $result
# Validate response content
$jsonContent = $result . Output . Content | ConvertFrom-Json
$jsonContent . protocol | Should -Be "HTTP/ $httpVersion "
}
2016-07-22 15:09:03 -07:00
It "Validate Invoke-WebRequest -MaximumRedirection" {
2017-09-25 14:50:15 -05:00
$uri = Get-WebListenerUrl -Test 'Redirect' -TestValue '3'
2017-09-18 11:26:01 -05:00
$command = "Invoke-WebRequest -Uri ' $uri ' -MaximumRedirection 4"
2017-01-16 13:31:14 -08:00
2016-07-22 15:09:03 -07:00
$result = ExecuteWebCommand -command $command
ValidateResponse -response $result
# Validate response content
$jsonContent = $result . Output . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$jsonContent . headers . Host | Should -Match $uri . Authority
2016-07-22 15:09:03 -07:00
}
2017-07-07 09:25:46 -07:00
2016-07-22 15:09:03 -07:00
It "Validate Invoke-WebRequest error for -MaximumRedirection" {
2017-09-25 14:50:15 -05:00
$uri = Get-WebListenerUrl -Test 'Redirect' -TestValue '3'
2017-09-18 11:26:01 -05:00
$command = "Invoke-WebRequest -Uri ' $uri ' -MaximumRedirection 2"
2017-01-16 13:31:14 -08:00
2016-07-22 15:09:03 -07:00
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
$result . Error . FullyQualifiedErrorId | Should -Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
2016-07-22 15:09:03 -07:00
}
2017-07-07 09:25:46 -07:00
2023-01-13 13:37:55 +01:00
It "Validate Invoke-WebRequest redirect with -Query destination Http" {
$httpUri = Get-WebListenerUrl -Test 'Get'
$uri = Get-WebListenerUrl -Test 'Redirect' -Query @ { destination = $httpUri }
$command = "Invoke-WebRequest -Uri ' $uri '"
$result = ExecuteWebCommand -command $command
$jsonContent = $result . Output . Content | ConvertFrom-Json
$jsonContent . headers . Host | Should -Match $httpUri . Authority
}
It "Validate Invoke-WebRequest redirect with -Query destination Https" {
$httpsUri = Get-WebListenerUrl -Test 'Get' -Https
$uri = Get-WebListenerUrl -Test 'Redirect' -Https -Query @ { destination = $httpsUri }
$command = "Invoke-WebRequest -Uri ' $uri ' -SkipCertificateCheck"
$result = ExecuteWebCommand -command $command
$jsonContent = $result . Output . Content | ConvertFrom-Json
$jsonContent . headers . Host | Should -Match $httpsUri . Authority
}
2016-07-22 15:09:03 -07:00
It "Invoke-WebRequest supports request that returns page containing UTF-8 data." {
2017-09-25 14:50:15 -05:00
$uri = Get-WebListenerUrl -Test 'Encoding' -TestValue 'Utf8'
2017-09-22 12:09:49 -05:00
$command = "Invoke-WebRequest -Uri ' $uri '"
2017-01-16 13:31:14 -08:00
2016-07-22 15:09:03 -07:00
$result = ExecuteWebCommand -command $command
ValidateResponse -response $result
2018-03-01 23:00:00 -06:00
$Result . Output . Encoding . BodyName | Should -Be 'utf-8'
$Result . Output . Content | Should -Match '⡌⠁⠧⠑ ⠼⠁⠒ ⡍⠜⠇⠑⠹⠰⠎ ⡣⠕⠌'
2016-07-22 15:09:03 -07:00
}
2023-03-01 18:56:05 +01:00
It "Invoke-WebRequest -ContentType overwrites Content-Type from -Headers." {
$uri = Get-WebListenerUrl -Test 'POST'
$command = "Invoke-WebRequest -Uri ' $uri ' -ContentType 'application/json' -Headers @{'Content-Type'='plain/text'} -Method 'POST'"
$result = ExecuteWebCommand -command $command
$result . Output . BaseResponse . RequestMessage . Content . Headers . ContentType . MediaType | Should -BeExactly 'application/json'
}
2019-01-25 23:48:47 -08:00
It "Invoke-WebRequest supports sending request as UTF-8." {
$uri = Get-WebListenerUrl -Test 'POST'
# Body must contain non-ASCII characters
$command = "Invoke-WebRequest -Uri ' $uri ' -Body 'проверка' -ContentType 'application/json; charset=utf-8' -Method 'POST'"
$result = ExecuteWebCommand -command $command
ValidateResponse -response $result
2023-03-01 18:56:05 +01:00
$result . Output . Encoding . BodyName | Should -BeExactly 'utf-8'
2019-01-25 23:48:47 -08:00
$object = $Result . Output . Content | ConvertFrom-Json
$object . Data | Should -BeExactly 'проверка'
}
2023-03-07 05:35:36 +01:00
It "Invoke-WebRequest supports sending XML requests without encoding" {
$uri = Get-WebListenerUrl -Test POST
$body = '<?xml version="1.0"?><foo />'
$result = Invoke-WebRequest -Uri $uri -body ([ xml ] $body ) -ContentType 'text/xml' -method 'POST'
$object = $result . Content | ConvertFrom-Json
$object . Data | Should -BeExactly $body
}
2019-01-22 10:45:40 -08:00
It "Invoke-WebRequest supports request that returns page containing CodPage 936 data." {
$uri = Get-WebListenerUrl -Test 'Encoding' -TestValue 'CP936'
$command = "Invoke-WebRequest -Uri ' $uri '"
$result = ExecuteWebCommand -command $command
ValidateResponse -response $result
$Result . Output . Encoding . CodePage | Should -Be 936
$Result . Output . Content | Should -Match '测试123'
}
2023-06-20 08:07:16 +10:00
It "Invoke-WebRequest validate ConnectionTimeoutSeconds option" {
$uri = Get-WebListenerUrl -Test 'Delay' -TestValue '5'
$command = "Invoke-WebRequest -Uri ' $uri ' -ConnectionTimeoutSeconds 2"
$result = ExecuteWebCommand -command $command
$result . Error . FullyQualifiedErrorId | Should -Be "ConnectionTimeoutReached,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
}
It "Invoke-WebRequest validate TimeoutSec alias" {
2017-10-06 13:17:52 -05:00
$uri = Get-WebListenerUrl -Test 'Delay' -TestValue '5'
$command = "Invoke-WebRequest -Uri ' $uri ' -TimeoutSec 2"
2017-01-16 13:31:14 -08:00
2016-07-22 15:09:03 -07:00
$result = ExecuteWebCommand -command $command
2023-06-20 08:07:16 +10:00
$result . Error . FullyQualifiedErrorId | Should -Be "ConnectionTimeoutReached,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
2017-03-28 21:25:13 +02:00
}
2016-07-22 15:09:03 -07:00
2017-03-28 21:25:13 +02:00
It "Validate Invoke-WebRequest error with -Proxy and -NoProxy option" {
2017-09-25 14:50:15 -05:00
$uri = Get-WebListenerUrl -Test 'Delay' -TestValue '10'
2018-01-31 22:26:05 -06:00
$command = "Invoke-WebRequest -Uri ' $uri ' -Proxy 'http://127.0.0.1:8080' -NoProxy -TimeoutSec 2"
2017-03-28 21:25:13 +02:00
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
$result . Error . FullyQualifiedErrorId | Should -Be "AmbiguousParameterSet,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
2017-03-28 21:25:13 +02:00
}
$testCase = @ (
2018-05-08 09:15:49 +05:00
@ { proxy_address = ( Get-WebListenerUrl ). Authority ; name = 'HTTP proxy' ; protocol = 'http' }
@ { proxy_address = ( Get-WebListenerUrl -https ). Authority ; name = 'HTTPS proxy' ; protocol = 'https' }
2017-03-28 21:25:13 +02:00
)
2018-05-03 04:58:39 +05:00
It "Validate Invoke-WebRequest with -Proxy option set - '<name>'" -TestCases $testCase {
2017-03-28 21:25:13 +02:00
param ( $proxy_address , $name , $protocol )
2018-05-03 04:58:39 +05:00
# use external url, but with proxy the external url should not actually be called
2023-03-01 20:04:20 +01:00
$command = "Invoke-WebRequest -Uri ${protocol} ://httpbin.org -Proxy ' ${protocol} :// ${proxy_address} '"
2017-03-28 21:25:13 +02:00
$result = ExecuteWebCommand -command $command
2018-05-03 04:58:39 +05:00
$command = "Invoke-WebRequest -Uri ' ${protocol} :// ${proxy_address} ' -NoProxy"
$expectedResult = ExecuteWebCommand -command $command
$result . Output . Content | Should -BeExactly $expectedResult . Output . Content
2017-03-28 21:25:13 +02:00
}
2016-07-22 15:09:03 -07:00
# Perform the following operation for Invoke-WebRequest
# gzip Returns gzip-encoded data.
# deflate Returns deflate-encoded data.
2023-01-10 04:07:00 +01:00
# brotli Returns brotli-encoded data.
2017-01-16 13:31:14 -08:00
# $dataEncodings = @("Chunked", "Compress", "Deflate", "GZip", "Identity")
2017-10-02 15:46:53 -05:00
# Note: These are the supported options, but we do not have a web service to test them all.
It "Invoke-WebRequest supports request that returns <DataEncoding>-encoded data." -TestCases @ (
2022-10-04 21:33:37 +05:00
@ { DataEncoding = "gzip" }
@ { DataEncoding = "deflate" }
2023-01-10 04:07:00 +01:00
@ { DataEncoding = "brotli" }
2017-10-02 15:46:53 -05:00
) {
param ( $dataEncoding )
$uri = Get-WebListenerUrl -Test 'Compression' -TestValue $dataEncoding
$command = "Invoke-WebRequest -Uri ' $uri '"
2016-07-22 15:09:03 -07:00
2017-10-02 15:46:53 -05:00
$result = ExecuteWebCommand -command $command
ValidateResponse -response $result
2017-01-16 13:31:14 -08:00
2017-10-02 15:46:53 -05:00
# Validate response content
2022-10-04 21:33:37 +05:00
# The content should be de-compressed, and otherwise converting from JSON will fail.
2017-10-27 05:12:19 +08:00
$jsonContent = $result . Output . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$jsonContent . Headers . Host | Should -BeExactly $uri . Authority
2016-07-22 15:09:03 -07:00
}
# Perform the following operation for Invoke-WebRequest using the following content types: "text/plain", "application/xml", "application/xml"
# post Returns POST data.
# patch Returns PATCH data.
# put Returns PUT data.
# delete Returns DELETE data
2017-12-13 09:28:05 -06:00
$testMethods = @ ( "POST" , "PATCH" , "PUT" , "DELETE" )
2016-07-22 15:09:03 -07:00
$contentTypes = @ ( "text/plain" , "application/xml" , "application/json" )
2018-01-09 15:43:25 -06:00
foreach ( $contentType in $contentTypes ) {
foreach ( $method in $testMethods ) {
2016-07-22 15:09:03 -07:00
# Operation options
2017-12-13 09:28:05 -06:00
$uri = Get-WebListenerUrl -Test $method
2016-07-22 15:09:03 -07:00
$body = GetTestData -contentType $contentType
2017-12-13 09:28:05 -06:00
$command = "Invoke-WebRequest -Uri $uri -Body ' $body ' -Method $method -ContentType $contentType "
2024-07-02 00:35:23 +02:00
$commandNoContentType = "Invoke-WebRequest -Uri $uri -Body ' $body ' -Method $method "
2016-07-22 15:09:03 -07:00
2024-07-02 00:35:23 +02:00
It "Invoke-WebRequest -Uri $uri -Method $method -ContentType $contentType -Body [body data]" {
2016-07-22 15:09:03 -07:00
$result = ExecuteWebCommand -command $command
ValidateResponse -response $result
# Validate response content
$jsonContent = $result . Output . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$jsonContent . url | Should -Match $uri
$jsonContent . headers . 'Content-Type' | Should -Match $contentType
2017-12-13 09:28:05 -06:00
# Validate that the response Content.data field is the same as what we sent.
2018-03-01 23:00:00 -06:00
$jsonContent . data | Should -Be $body
2017-01-16 13:31:14 -08:00
}
2024-07-02 00:35:23 +02:00
It "Invoke-WebRequest -Uri $uri -Method $method -Body [body data]" {
$result = ExecuteWebCommand -command $commandNoContentType
ValidateResponse -response $result
# Validate response content
$jsonContent = $result . Output . Content | ConvertFrom-Json
$jsonContent . url | Should -Match $uri
if ( $method -eq "POST" )
{
$jsonContent . headers . 'Content-Type' | Should -Match "application/x-www-form-urlencoded"
# Validate that the response Content.form field is the same as what we sent.
[ string ] $jsonContent . form | Should -Be ([ string][PSCustomObject ] @ { $body . Split ( "=" )[ 0 ] = [ System.Object[] ]})
$jsonContent . data | Should -BeNullOrEmpty
}
else
{
# Validate that the response Content.data field is the same as what we sent.
$jsonContent . data | Should -Be $body
}
}
2016-07-22 15:09:03 -07:00
}
}
It "Validate Invoke-WebRequest -Headers --> Set KeepAlive to false via headers" {
2017-09-07 22:53:04 -05:00
$uri = Get-WebListenerUrl -Test 'Get'
2016-07-22 15:09:03 -07:00
$result = ExecuteRequestWithHeaders -cmdletName Invoke-WebRequest -uri $uri
ValidateResponse -response $result
2018-03-01 23:00:00 -06:00
$result . Output . Headers . Connection | Should -Be "Close"
2016-07-22 15:09:03 -07:00
}
# Validate all available user agents for Invoke-WebRequest
2018-01-09 15:43:25 -06:00
$agents = @ {
InternetExplorer = "MSIE 9.0"
Chrome = "Chrome"
Opera = "Opera"
Safari = "Safari"
FireFox = "Firefox"
}
2016-07-22 15:09:03 -07:00
2018-01-09 15:43:25 -06:00
foreach ( $agentName in $agents . Keys ) {
2016-07-22 15:09:03 -07:00
$expectedAgent = $agents [ $agentName ]
2017-09-07 22:53:04 -05:00
$uri = Get-WebListenerUrl -Test 'Get'
2016-07-22 15:09:03 -07:00
$userAgent = "[Microsoft.PowerShell.Commands.PSUserAgent]:: $agentName "
2018-02-02 13:56:06 -06:00
$command = "Invoke-WebRequest -Uri $uri -UserAgent ( $userAgent ) "
2016-07-22 15:09:03 -07:00
It "Validate Invoke-WebRequest UserAgent. Execute--> $command " {
$result = ExecuteWebCommand -command $command
ValidateResponse -response $result
# Validate response content
$jsonContent = $result . Output . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$jsonContent . headers . Host | Should -Be $uri . Authority
$jsonContent . headers . 'User-Agent' | Should -Match $expectedAgent
2016-07-22 15:09:03 -07:00
}
}
It "Validate Invoke-WebRequest -OutFile" {
2017-09-07 22:53:04 -05:00
$uri = Get-WebListenerUrl -Test 'Get'
2016-07-22 15:09:03 -07:00
$result = ExecuteRequestWithOutFile -cmdletName "Invoke-WebRequest" -uri $uri
$jsonContent = $result . Output | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$jsonContent . headers . Host | Should -Be $uri . Authority
2016-07-22 15:09:03 -07:00
}
2023-03-21 09:06:50 +01:00
It "Invoke-WebRequest -OutFile folder Downloads the file and names it" {
$uri = Get-WebListenerUrl -Test 'Get'
$content = Invoke-WebRequest -Uri $uri
$outFile = Join-Path $TestDrive $content . BaseResponse . RequestMessage . RequestUri . Segments [ -1 ]
# ensure the file does not exist
Remove-Item -Force -ErrorAction Ignore -Path $outFile
Invoke-WebRequest -Uri $uri -OutFile $TestDrive
Test-Path $outFile | Should -Be $true
Get-Item $outFile | Select-Object -ExpandProperty Length | Should -Be $content . Content . Length
}
2024-07-23 16:04:20 -05:00
It "Invoke-WebRequest -PassThru -OutFile <directory> saves the downloaded file path as a property in WebResponseObject" {
$uri = Get-WebListenerUrl -Test 'Get'
$content = Invoke-WebRequest -Uri $uri -PassThru -OutFile $TestDrive
$content . OutFile | Should -exist
$content . OutFile | Should -Be ( Join-Path $TestDrive 'Get' )
}
It "Invoke-WebRequest -PassThru -OutFile <file> saves the downloaded file path as a property in WebResponseObject" {
$uri = Get-WebListenerUrl -Test 'Get'
$filePath = Join-Path $TestDrive "pestertest-outfile"
$content = Invoke-WebRequest -Uri $uri -PassThru -OutFile $filePath
$content . OutFile | Should -exist
$content . OutFile | Should -Be $filePath
}
It "Invoke-WebRequest -PassThru -OutFile -Verbose File Name reflects the downloaded file name" {
$uri = Get-WebListenerUrl -Test 'Get'
$filePath = Join-Path $TestDrive "pestertest-outfile"
$content = Invoke-WebRequest -Verbose -Uri $uri -PassThru -OutFile $filePath 4 > variable : verbo
$verbo [ -1 ]. Message | Should -Match "pestertest-outfile"
}
2023-02-01 17:45:09 +01:00
It "Invoke-WebRequest should fail if -OutFile is <Name>." -TestCases @ (
@ { Name = "empty" ; Value = [ string ]:: Empty }
@ { Name = "null" ; Value = $null }
) {
param ( $value )
$uri = Get-WebListenerUrl -Test 'Get'
$errorId = "ParameterArgumentValidationError,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
{ Invoke-WebRequest -Uri $uri -OutFile $value } | Should -Throw -ErrorId $errorId
}
2016-11-15 08:35:07 +11:00
It "Validate Invoke-WebRequest handles missing Content-Type in response header" {
#Validate that exception is not thrown when response headers are missing Content-Type.
2017-10-18 14:24:02 -05:00
$uri = Get-WebListenerUrl -Test 'ResponseHeaders' -Query @ { 'Content-Type' = '' }
$command = "Invoke-WebRequest -Uri ' $uri '"
2016-11-15 08:35:07 +11:00
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
$result . Error | Should -BeNullOrEmpty
2016-11-15 08:35:07 +11:00
}
2017-02-24 22:29:11 -08:00
2017-03-06 19:41:14 +00:00
It "Validate Invoke-WebRequest StandardMethod and CustomMethod parameter sets" {
2017-12-18 22:29:46 -06:00
$uri = Get-WebListenerUrl -Test 'Get'
2017-03-06 19:41:14 +00:00
#Validate that parameter sets are functioning correctly
$errorId = "AmbiguousParameterSet,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
2018-05-17 14:42:04 -07:00
{ Invoke-WebRequest -Uri $uri -Method GET -CustomMethod TEST } | Should -Throw -ErrorId $errorId
2017-03-06 19:41:14 +00:00
}
It "Validate Invoke-WebRequest CustomMethod method is used" {
2017-12-18 22:29:46 -06:00
$uri = Get-WebListenerUrl -Test 'Get'
$command = "Invoke-WebRequest -Uri ' $uri ' -CustomMethod TEST"
2017-03-06 19:41:14 +00:00
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
$result . Error | Should -BeNullOrEmpty
( $result . Output . Content | ConvertFrom-Json ). method | Should -Be "TEST"
2017-03-06 19:41:14 +00:00
}
2024-02-26 11:51:12 -08:00
It "Validate Invoke-WebRequest default ContentType for CustomMethod POST" {
$uri = Get-WebListenerUrl -Test 'Post'
$command = "Invoke-WebRequest -Uri ' $uri ' -CustomMethod POST -Body 'testparam=testvalue'"
2017-03-06 19:41:14 +00:00
$result = ExecuteWebCommand -command $command
2017-12-13 09:28:05 -06:00
$jsonResult = $result . Output . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$jsonResult . form . testparam | Should -Be "testvalue"
$jsonResult . Headers . 'Content-Type' | Should -Be "application/x-www-form-urlencoded"
2017-03-06 19:41:14 +00:00
}
It "Validate Invoke-WebRequest body is converted to query params for CustomMethod GET" {
2017-09-07 22:53:04 -05:00
$uri = Get-WebListenerUrl -Test 'Get'
$command = "Invoke-WebRequest -Uri ' $uri ' -CustomMethod GET -Body @{'testparam'='testvalue'}"
2017-03-06 19:41:14 +00:00
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
( $result . Output . Content | ConvertFrom-Json ). args . testparam | Should -Be "testvalue"
2017-03-06 19:41:14 +00:00
}
2017-07-07 09:25:46 -07:00
2022-01-03 11:20:33 -08:00
It 'Validate Invoke-WebRequest empty body CustomMethod GET' {
$uri = Get-WebListenerUrl -Test 'Get'
$command = "Invoke-WebRequest -Uri ' $uri ' -CustomMethod GET"
$result = ExecuteWebCommand -command $command
$result . Output . Headers . 'Content-Length' | Should -BeNullOrEmpty
}
2021-02-04 19:06:04 -08:00
It "Validate Invoke-WebRequest body is converted to query params for CustomMethod GET and -NoProxy" {
$uri = Get-WebListenerUrl -Test 'Get'
$command = "Invoke-WebRequest -Uri ' $uri ' -CustomMethod GET -Body @{'testparam'='testvalue'} -NoProxy"
$result = ExecuteWebCommand -command $command
( $result . Output . Content | ConvertFrom-Json ). query | Should -Be "?testparam=testvalue"
}
2017-02-24 22:29:11 -08:00
It "Validate Invoke-WebRequest returns HTTP errors in exception" {
2017-12-13 09:28:05 -06:00
$query = @ {
2018-01-09 15:43:25 -06:00
body = "I am a teapot!!!"
statuscode = 418
2017-12-13 09:28:05 -06:00
responsephrase = "I am a teapot"
}
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2017-12-13 09:28:05 -06:00
$command = "Invoke-WebRequest -Uri ' $uri '"
2017-02-24 22:29:11 -08:00
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
$result . Error . ErrorDetails . Message | Should -Be $query . body
2020-01-24 19:00:37 +00:00
$result . Error . Exception | Should -BeOfType Microsoft . PowerShell . Commands . HttpResponseException
2018-03-01 23:00:00 -06:00
$result . Error . Exception . Response . StatusCode | Should -Be 418
$result . Error . Exception . Response . ReasonPhrase | Should -Be $query . responsephrase
$result . Error . Exception . Message | Should -Match ": 418 \( $( $query . responsephrase ) \)\."
$result . Error . FullyQualifiedErrorId | Should -Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
2017-02-24 22:29:11 -08:00
}
2017-03-16 17:59:15 -07:00
2023-02-09 09:22:04 +01:00
It "Validate Invoke-WebRequest returns <type> errors in exception" -TestCases @ (
@ { type = "XML"
query = @ {
contenttype = 'application/xml'
body = '<?xml version="1.0" encoding="UTF-8"?><Error><Code>418</Code><Message>I am a teapot!!!</Message></Error>'
statuscode = 418
responsephrase = "I am a teapot"
}
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>"
}
@ { type = "Json"
query = @ {
contenttype = 'application/json'
body = '{"error":{"code":"418", "message":"I am a teapot!!!"}}'
statuscode = 418
responsephrase = "I am a teapot"
}
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 }"
}
) {
param ( $query , $expectederror )
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
$command = "Invoke-WebRequest -Uri ' $uri '"
$result = ExecuteWebCommand -command $command
$result . Error . ErrorDetails . Message | Should -Be $expectederror
}
2017-05-24 15:54:02 -07:00
It "Validate Invoke-WebRequest returns empty RelationLink property if there is no Link Header" {
2017-12-04 11:52:14 -06:00
$uri = $uri = Get-WebListenerUrl -Test 'Get'
$command = "Invoke-WebRequest -Uri ' $uri '"
2017-05-24 15:54:02 -07:00
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
$result . Output . RelationLink . Count | Should -Be 0
2017-05-24 15:54:02 -07:00
}
2023-02-10 17:50:01 +01:00
It "Validate Invoke-WebRequest returns valid RelationLink property with absolute uris if Link Header is present <name>" -TestCases @ (
$originalUri = Get-WebListenerUrl -Test 'Link' -Query @ { maxlinks = 5 ; linknumber = 2 }
@ { name = '(URI with scheme)' ; uri = $originalUri }
@ { name = '(URI without scheme)' ; uri = $originalUri . OriginalString . Split ( "//" )[ 1 ]}
) {
param ( $uri )
2017-11-01 16:06:30 -05:00
$command = "Invoke-WebRequest -Uri ' $uri '"
$result = ExecuteWebCommand -command $command
2018-01-16 11:23:22 -06:00
2018-03-01 23:00:00 -06:00
$result . Output . RelationLink . Count | Should -BeExactly 5
2018-01-16 11:23:22 -06:00
$baseUri = Get-WebListenerUrl -Test 'Link'
2018-03-01 23:00:00 -06:00
$result . Output . RelationLink [ "next" ] | Should -BeExactly " ${baseUri} ?maxlinks=5&linknumber=3&type=default"
$result . Output . RelationLink [ "last" ] | Should -BeExactly " ${baseUri} ?maxlinks=5&linknumber=5&type=default"
$result . Output . RelationLink [ "prev" ] | Should -BeExactly " ${baseUri} ?maxlinks=5&linknumber=1&type=default"
$result . Output . RelationLink [ "first" ] | Should -BeExactly " ${baseUri} ?maxlinks=5&linknumber=1&type=default"
$result . Output . RelationLink [ "self" ] | Should -BeExactly " ${baseUri} ?maxlinks=5&linknumber=2&type=default"
2018-01-16 11:23:22 -06:00
}
It "Validate Invoke-WebRequest returns valid RelationLink property with absolute uris if Multiple Link Headers are present" {
$uri = Get-WebListenerUrl -Test 'Link' -Query @ { maxlinks = 5 ; linknumber = 2 ; type = 'multiple' }
$command = "Invoke-WebRequest -Uri ' $uri '"
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
$result . Output . RelationLink . Count | Should -BeExactly 5
2018-01-16 11:23:22 -06:00
$baseUri = Get-WebListenerUrl -Test 'Link'
2018-03-01 23:00:00 -06:00
$result . Output . RelationLink [ "next" ] | Should -BeExactly " ${baseUri} ?maxlinks=5&linknumber=3&type=multiple"
$result . Output . RelationLink [ "last" ] | Should -BeExactly " ${baseUri} ?maxlinks=5&linknumber=5&type=multiple"
$result . Output . RelationLink [ "prev" ] | Should -BeExactly " ${baseUri} ?maxlinks=5&linknumber=1&type=multiple"
$result . Output . RelationLink [ "first" ] | Should -BeExactly " ${baseUri} ?maxlinks=5&linknumber=1&type=multiple"
$result . Output . RelationLink [ "self" ] | Should -BeExactly " ${baseUri} ?maxlinks=5&linknumber=2&type=multiple"
2017-05-24 15:54:02 -07:00
}
2018-03-08 15:54:42 -08:00
It "Validate Invoke-WebRequest RelationLink keys are treated case-insensitively" {
$uri = Get-WebListenerUrl -Test 'Link' -Query @ { maxlinks = 5 ; linknumber = 2 ; type = 'multiple' }
$command = "Invoke-WebRequest -Uri ' $uri '"
$result = ExecuteWebCommand -command $command
$result . Output . RelationLink [ "next" ] | Should -Not -BeNullOrEmpty
$result . Output . RelationLink [ "next" ] | Should -BeExactly $result . Output . RelationLink [ "Next" ]
$result . Output . RelationLink [ "last" ] | Should -Not -BeNullOrEmpty
$result . Output . RelationLink [ "last" ] | Should -BeExactly $result . Output . RelationLink [ "LAST" ]
$result . Output . RelationLink [ "prev" ] | Should -Not -BeNullOrEmpty
$result . Output . RelationLink [ "prev" ] | Should -BeExactly $result . Output . RelationLink [ "preV" ]
$result . Output . RelationLink [ "first" ] | Should -Not -BeNullOrEmpty
$result . Output . RelationLink [ "first" ] | Should -BeExactly $result . Output . RelationLink [ "FiRsT" ]
$result . Output . RelationLink [ "self" ] | Should -Not -BeNullOrEmpty
$result . Output . RelationLink [ "self" ] | Should -BeExactly $result . Output . RelationLink [ "self" ]
}
2017-07-07 09:25:46 -07:00
It "Validate Invoke-WebRequest quietly ignores invalid Link Headers in RelationLink property: <type>" -TestCases @ (
2017-05-24 15:54:02 -07:00
@ { type = "noUrl" }
@ { type = "malformed" }
2017-07-07 09:25:46 -07:00
@ { type = "noRel" }
2017-05-24 15:54:02 -07:00
) {
param ( $type )
2018-01-16 11:23:22 -06:00
$uri = Get-WebListenerUrl -Test 'Link' -Query @ { type = $type }
$command = "Invoke-WebRequest -Uri ' $uri '"
2017-05-24 15:54:02 -07:00
$result = ExecuteWebCommand -command $command
2018-01-16 11:23:22 -06:00
2018-03-01 23:00:00 -06:00
$result . Output . RelationLink . Count | Should -BeExactly 3
2018-01-16 11:23:22 -06:00
$baseUri = Get-WebListenerUrl -Test 'Link'
2018-03-01 23:00:00 -06:00
$result . Output . RelationLink [ "last" ] | Should -BeExactly " ${baseUri} ?maxlinks=3&linknumber=3&type= ${type} "
$result . Output . RelationLink [ "first" ] | Should -BeExactly " ${baseUri} ?maxlinks=3&linknumber=1&type= ${type} "
$result . Output . RelationLink [ "self" ] | Should -BeExactly " ${baseUri} ?maxlinks=3&linknumber=1&type= ${type} "
2017-05-24 15:54:02 -07:00
}
2018-07-23 22:56:00 -07:00
It "Validate Invoke-WebRequest handles different whitespace for Link Headers: <type>" -TestCases @ (
@ { type = "noWhitespace" }
@ { type = "extraWhitespace" }
) {
param ( $type )
$uri = Get-WebListenerUrl -Test 'Link' -Query @ { type = $type }
$command = "Invoke-WebRequest -Uri ' $uri '"
$result = ExecuteWebCommand -command $command
$result . Output . RelationLink . Count | Should -BeExactly 4
$baseUri = Get-WebListenerUrl -Test 'Link'
$result . Output . RelationLink [ "last" ] | Should -BeExactly " ${baseUri} ?maxlinks=3&linknumber=3&type= ${type} "
$result . Output . RelationLink [ "first" ] | Should -BeExactly " ${baseUri} ?maxlinks=3&linknumber=1&type= ${type} "
$result . Output . RelationLink [ "self" ] | Should -BeExactly " ${baseUri} ?maxlinks=3&linknumber=1&type= ${type} "
$result . Output . RelationLink [ "next" ] | Should -BeExactly " ${baseUri} ?maxlinks=3&linknumber=2&type= ${type} "
}
2019-11-07 12:38:24 -08:00
It "Verify Invoke-WebRequest supresses terminating errors with -SkipHttpErrorCheck" {
$uri = Get-WebListenerUrl -Test 'Response' -Query $NotFoundQuery
$command = "Invoke-WebRequest -SkipHttpErrorCheck -Uri ' $uri '"
$result = ExecuteWebCommand -Command $command
$result . output . StatusCode | Should -Be 404
$result . output . Content | Should -BeExactly "oops"
$result . error | Should -BeNullOrEmpty
}
It "Verify Invoke-WebRequest terminates without -SkipHttpErrorCheck" {
$uri = Get-WebListenerUrl -Test 'Response' -Query $NotFoundQuery
$command = "Invoke-WebRequest -Uri ' $uri '"
$result = ExecuteWebCommand -Command $command
$result . output | Should -BeNullOrEmpty
$result . error | Should -Not -BeNullOrEmpty
}
2019-07-15 19:52:01 +00:00
Context "Redirect" {
It "Validates Invoke-WebRequest with -PreserveAuthorizationOnRedirect preserves the authorization header on redirect: <redirectType> <redirectedMethod>" -TestCases $redirectTests {
param ( $redirectType , $redirectedMethod )
$uri = Get-WebListenerUrl -Test 'Redirect' -Query @ { type = $redirectType }
$response = ExecuteRedirectRequest -Uri $uri -PreserveAuthorizationOnRedirect
2017-06-15 15:52:08 -07:00
2019-07-15 19:52:01 +00:00
$response . Error | Should -BeNullOrEmpty
$response . Content . Headers . "Authorization" | Should -BeExactly "test"
}
2023-02-01 17:45:09 +01:00
2023-01-13 14:31:03 +01:00
It "Validates Invoke-WebRequest with -PreserveAuthorizationOnRedirect respects -MaximumRedirection on redirect: <redirectType> <redirectedMethod>" -TestCases $redirectTests {
param ( $redirectType , $redirectedMethod )
$uri = Get-WebListenerUrl -Test 'Redirect' -TestValue '3' -Query @ { type = $redirectType }
$response = ExecuteRedirectRequest -Uri $uri -PreserveAuthorizationOnRedirect -MaximumRedirection 2
$response . Error . FullyQualifiedErrorId | Should -Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
}
2017-07-07 09:25:46 -07:00
2019-07-15 19:52:01 +00:00
It "Validates Invoke-WebRequest preserves the authorization header on multiple redirects: <redirectType>" -TestCases $redirectTests {
param ( $redirectType )
$uri = Get-WebListenerUrl -Test 'Redirect' -TestValue 3 -Query @ { type = $redirectType }
$response = ExecuteRedirectRequest -Uri $uri -PreserveAuthorizationOnRedirect
$response . Error | Should -BeNullOrEmpty
$response . Content . Headers . "Authorization" | Should -BeExactly "test"
}
2023-03-01 20:04:20 +01:00
It "Validates Invoke-WebRequest with -WebSession and -PreserveAuthorizationOnRedirect doesn't change session variable on multiple redirects: <redirectType>" -TestCases $redirectTests {
param ( $redirectType )
#[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Demo/doc/test secret.")]
$token = "testpassword" | ConvertTo-SecureString -AsPlainText -Force
$credential = [ pscredential ]:: new ( "testuser" , $token )
$certificate = Get-WebListenerClientCertificate
$headers = @ { "Authorization" = "test" }
$proxy = ( Get-WebListenerUrl ). Authority
$uri = Get-WebListenerUrl -Test 'Redirect' -TestValue 2 -Query @ { type = $redirectType }
$session = [ Microsoft.PowerShell.Commands.WebRequestSession ]:: new ()
$session . MaximumRedirection = 2
$session . MaximumRetryCount = 2
$session . RetryIntervalInSeconds = 2
$session . UseDefaultCredentials = $true
$null = Invoke-WebRequest -Uri $uri -PreserveAuthorizationOnRedirect -WebSession $session -AllowUnencryptedAuthentication -Headers $headers
$session . MaximumRedirection | Should -BeExactly 2
$session . MaximumRetryCount | Should -BeExactly 2
$session . RetryIntervalInSeconds | Should -BeExactly 2
$session . UseDefaultCredentials | Should -BeExactly $true
$session = [ Microsoft.PowerShell.Commands.WebRequestSession ]:: new ()
$session . Credentials = $credential
$session . Certificates = [ System.Security.Cryptography.X509Certificates.X509CertificateCollection ]:: new ([ X509Certificate ] $certificate )
$null = Invoke-WebRequest -Uri $uri -PreserveAuthorizationOnRedirect -WebSession $session -SkipCertificateCheck -Headers $headers
$session . Credentials . UserName | Should -BeExactly $credential . UserName
$session . Credentials . Password | Should -BeExactly $credential . GetNetworkCredential (). Password
$session . Certificates . Thumbprint | Should -BeExactly $certificate . Thumbprint
$session = [ Microsoft.PowerShell.Commands.WebRequestSession ]:: new ()
$session . Proxy = [ System.Net.WebProxy ]:: new ( $proxy )
$null = Invoke-WebRequest -Uri $uri -PreserveAuthorizationOnRedirect -WebSession $session -Headers $headers
$session . Proxy . GetProxy ( $uri ). Authority | Should -BeExactly $proxy
}
2019-07-15 19:52:01 +00:00
It "Validates Invoke-WebRequest strips the authorization header on various redirects: <redirectType>" -TestCases $redirectTests {
param ( $redirectType )
$uri = Get-WebListenerUrl -Test 'Redirect' -Query @ { type = $redirectType }
$response = ExecuteRedirectRequest -Uri $uri
$response . Error | Should -BeNullOrEmpty
# ensure user-agent is present (i.e., no false positives )
$response . Content . Headers . "User-Agent" | Should -Not -BeNullOrEmpty
# ensure Authorization header has been removed.
$response . Content . Headers . "Authorization" | Should -BeNullOrEmpty
}
# NOTE: Only testing redirection of POST -> GET for unique underlying values of HttpStatusCode.
# Some names overlap in underlying value.
It "Validates Invoke-WebRequest strips the authorization header redirects and switches from POST to GET when it handles the redirect: <redirectType> <redirectedMethod>" -TestCases $redirectTests {
param ( $redirectType , $redirectedMethod )
$uri = Get-WebListenerUrl -Test 'Redirect' -Query @ { type = $redirectType }
$response = ExecuteRedirectRequest -Uri $uri -Method 'POST'
$response . Error | Should -BeNullOrEmpty
# ensure user-agent is present (i.e., no false positives )
$response . Content . Headers . "User-Agent" | Should -Not -BeNullOrEmpty
# ensure Authorization header has been removed.
$response . Content . Headers . "Authorization" | Should -BeNullOrEmpty
# ensure POST was changed to GET for selected redirections and remains as POST for others.
$response . Content . Method | Should -Be $redirectedMethod
}
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 {
param ( $redirectType , $redirectedMethod )
$uri = Get-WebListenerUrl -Test 'Redirect' -Query @ { type = $redirectType }
$response = ExecuteRedirectRequest -PreserveAuthorizationOnRedirect -Uri $uri -Method 'POST'
$response . Error | Should -BeNullOrEmpty
# ensure user-agent is present (i.e., no false positives )
$response . Content . Headers . "User-Agent" | Should -Not -BeNullOrEmpty
2023-02-10 12:14:29 +01:00
# ensure Authorization header has been preserved.
$response . Content . Headers . "Authorization" | Should -BeExactly 'test'
# ensure POST was changed to GET for selected redirections and remains as POST for others.
$response . Content . Method | Should -Be $redirectedMethod
}
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 {
param ( $redirectType , $redirectedMethod )
$uri = Get-WebListenerUrl -Test 'Redirect' -Query @ { type = $redirectType }
$response = ExecuteRedirectRequest -PreserveAuthorizationOnRedirect -Uri $uri -CustomMethod 'POST'
$response . Error | Should -BeNullOrEmpty
# ensure user-agent is present (i.e., no false positives )
$response . Content . Headers . "User-Agent" | Should -Not -BeNullOrEmpty
# ensure Authorization header has been preserved.
2019-07-15 19:52:01 +00:00
$response . Content . Headers . "Authorization" | Should -BeExactly 'test'
# ensure POST was changed to GET for selected redirections and remains as POST for others.
$response . Content . Method | Should -Be $redirectedMethod
}
2026-08-20 16:57:20 -04:00
It "Validates Invoke-WebRequest -PreserveHttpMethodOnRedirect strips the authorization header and remains POST when it handles the redirect: <redirectType>" -TestCases $redirectTests {
2023-02-14 17:40:42 +01:00
param ( $redirectType )
$uri = Get-WebListenerUrl -Test 'Redirect' -Query @ { type = $redirectType }
$response = ExecuteRedirectRequest -PreserveHttpMethodOnRedirect -Uri $uri -Method 'POST'
$response . Error | Should -BeNullOrEmpty
# ensure user-agent is present (i.e., no false positives )
$response . Content . Headers . "User-Agent" | Should -Not -BeNullOrEmpty
2026-08-20 16:57:20 -04:00
# ensure Authorization header has been removed.
$response . Content . Headers . "Authorization" | Should -BeNullOrEmpty
# ensure POST doesn't change.
$response . Content . Method | Should -Be 'POST'
}
It "Validates Invoke-WebRequest -PreserveHttpMethodOnRedirect -PreserveAuthorizationOnRedirect keeps the authorization header and remains POST when it handles the redirect: <redirectType>" -TestCases $redirectTests {
param ( $redirectType )
$uri = Get-WebListenerUrl -Test 'Redirect' -Query @ { type = $redirectType }
$response = ExecuteRedirectRequest -PreserveAuthorizationOnRedirect -PreserveHttpMethodOnRedirect -Uri $uri -Method 'POST'
$response . Error | Should -BeNullOrEmpty
# ensure user-agent is present (i.e., no false positives )
$response . Content . Headers . "User-Agent" | Should -Not -BeNullOrEmpty
# ensure Authorization header has been preserved.
2023-02-14 17:40:42 +01:00
$response . Content . Headers . "Authorization" | Should -BeExactly 'test'
# ensure POST doesn't change.
$response . Content . Method | Should -Be 'POST'
}
2019-07-15 19:52:01 +00:00
It "Validates Invoke-WebRequest handles responses without Location header for requests with Authorization header and redirect: <redirectType>" -TestCases $redirectTests {
param ( $redirectType , $redirectedMethod )
# Skip relative test as it is not a valid response type.
if ( $redirectType -eq 'relative' ) { return }
# When an Authorization request header is present,
# and -PreserveAuthorizationOnRedirect is not present,
# PowerShell should throw an HTTP Response Exception
# for a redirect response which does not contain a Location response header.
# The correct redirect status code should be included in the exception.
$StatusCode = [ int][System.Net.HttpStatusCode ] $redirectType
$uri = Get-WebListenerUrl -Test Response -Query @ { statuscode = $StatusCode }
$command = "Invoke-WebRequest -Uri ' $uri ' -Headers @{Authorization = 'foo'}"
$response = ExecuteWebCommand -command $command
2020-01-24 19:00:37 +00:00
$response . Error . Exception | Should -BeOfType Microsoft . PowerShell . Commands . HttpResponseException
2019-07-15 19:52:01 +00:00
$response . Error . Exception . Response . StatusCode | Should -Be $StatusCode
$response . Error . Exception . Response . Headers . Location | Should -BeNullOrEmpty
}
2023-01-13 13:37:55 +01:00
It "Validate Invoke-WebRequest Https to Http redirect with -AllowInsecureRedirect" {
$httpUri = Get-WebListenerUrl -Test 'Get'
$uri = Get-WebListenerUrl -Test 'Redirect' -Https -Query @ { destination = $httpUri }
$command = "Invoke-WebRequest -Uri ' $uri ' -SkipCertificateCheck -AllowInsecureRedirect"
$result = ExecuteWebCommand -command $command
$jsonContent = $result . Output . Content | ConvertFrom-Json
$jsonContent . headers . Host | Should -Match $httpUri . Authority
}
It "Validate Invoke-WebRequest Https to Http redirect without -AllowInsecureRedirect" {
$httpUri = Get-WebListenerUrl -Test 'Get'
$uri = Get-WebListenerUrl -Test 'Redirect' -Https -Query @ { destination = $httpUri }
$command = "Invoke-WebRequest -Uri ' $uri ' -SkipCertificateCheck"
$result = ExecuteWebCommand -command $command
2023-02-14 04:32:48 +01:00
$result . Error . FullyQualifiedErrorId | Should -Be "InsecureRedirection,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
2023-01-13 13:37:55 +01:00
}
2023-04-12 02:56:24 +02:00
It "Validate Invoke-WebRequest Https to Http (No Scheme) redirect without -AllowInsecureRedirect" {
$httpUri = Get-WebListenerUrl -Test 'Get'
$uri = Get-WebListenerUrl -Test 'Redirect' -Https -Query @ { destination = $httpUri . Authority }
$command = "Invoke-WebRequest -Uri ' $uri ' -SkipCertificateCheck"
$result = ExecuteWebCommand -command $command
$result . Error . FullyQualifiedErrorId | Should -Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
}
2017-06-15 15:52:08 -07:00
}
2018-02-22 13:15:05 -06:00
Context "Invoke-WebRequest SkipHeaderVerification Tests" {
BeforeAll {
$Testfile = Join-Path $testdrive 'SkipHeaderVerification.txt'
'bar' | Set-Content $Testfile
}
2017-07-14 10:24:20 -07:00
2018-02-22 13:15:05 -06:00
It "Verifies Invoke-WebRequest default header handling with no errors" {
$uri = Get-WebListenerUrl -Test 'Get'
$headers = @ { "If-Match" = "*" }
$response = ExecuteRequestWithCustomHeaders -Uri $uri -headers $headers
2017-07-14 10:24:20 -07:00
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
$response . Content . Headers . "If-Match" | Should -BeExactly "*"
2018-02-22 13:15:05 -06:00
}
It "Verifies Invoke-WebRequest default header handling reports an error is returned for an invalid If-Match header value" {
$uri = Get-WebListenerUrl -Test 'Get'
$headers = @ { "If-Match" = "12345" }
$response = ExecuteRequestWithCustomHeaders -Uri $uri -headers $headers
2018-03-01 23:00:00 -06:00
$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."
2018-02-22 13:15:05 -06:00
}
It "Verifies Invoke-WebRequest header handling does not report an error when using -SkipHeaderValidation" {
$uri = Get-WebListenerUrl -Test 'Get'
$headers = @ { "If-Match" = "12345" }
$response = ExecuteRequestWithCustomHeaders -Uri $uri -headers $headers -SkipHeaderValidation
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
$response . Content . Headers . "If-Match" | Should -BeExactly "12345"
2018-02-22 13:15:05 -06:00
}
It "Verifies Invoke-WebRequest default UserAgent handling with no errors" {
$uri = Get-WebListenerUrl -Test 'Get'
$UserAgent = [ Microsoft.PowerShell.Commands.PSUserAgent ]:: InternetExplorer
$response = ExecuteRequestWithCustomUserAgent -Uri $uri -UserAgent $UserAgent -Cmdlet "Invoke-WebRequest"
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
2018-02-22 13:15:05 -06:00
$Pattern = [ regex ]:: Escape ( $UserAgent )
2018-03-01 23:00:00 -06:00
$response . Content . Headers . "User-Agent" | Should -Match $Pattern
2018-02-22 13:15:05 -06:00
}
It "Verifies Invoke-WebRequest default UserAgent handling reports an error is returned for an invalid UserAgent value" {
$uri = Get-WebListenerUrl -Test 'Get'
$UserAgent = 'Invalid:Agent'
$response = ExecuteRequestWithCustomUserAgent -Uri $uri -UserAgent $UserAgent -Cmdlet "Invoke-WebRequest"
2018-03-01 23:00:00 -06:00
$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 'Invalid:Agent' is invalid."
2018-02-22 13:15:05 -06:00
}
It "Verifies Invoke-WebRequest UserAgent handling does not report an error when using -SkipHeaderValidation" {
$uri = Get-WebListenerUrl -Test 'Get'
$UserAgent = 'Invalid:Agent'
$response = ExecuteRequestWithCustomUserAgent -Uri $uri -UserAgent $UserAgent -SkipHeaderValidation -Cmdlet "Invoke-WebRequest"
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
2018-02-22 13:15:05 -06:00
$Pattern = [ regex ]:: Escape ( $UserAgent )
2018-03-01 23:00:00 -06:00
$response . Content . Headers . "User-Agent" | Should -Match $Pattern
2018-02-22 13:15:05 -06:00
}
It "Verifies Invoke-WebRequest default ContentType handling reports no error is returned for a valid Content-Type header value and -Body" {
$contentType = 'text/plain'
$body = "bar"
$uri = Get-WebListenerUrl -Test 'Post'
$response = Invoke-WebRequest -Uri $uri -Method 'Post' -ContentType $contentType -Body $body
$result = $response . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$result . data | Should -BeExactly $body
$result . headers . 'Content-Type' | Should -BeExactly $contentType
2018-02-22 13:15:05 -06:00
}
It "Verifies Invoke-WebRequest default ContentType handling reports an error is returned for an invalid Content-Type header value and -Body" {
$contentType = 'foo'
$body = "bar"
$uri = Get-WebListenerUrl -Test 'Post'
{ Invoke-WebRequest -Uri $uri -Method 'Post' -ContentType $contentType -Body $body -ErrorAction 'Stop' } |
2018-05-17 14:42:04 -07:00
Should -Throw -ErrorId "WebCmdletContentTypeException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
2018-02-22 13:15:05 -06:00
}
It "Verifies Invoke-WebRequest ContentType handling reports no error is returned for an invalid Content-Type header value, -Body, and -SkipHeaderValidation" {
$contentType = 'foo'
$body = "bar"
$uri = Get-WebListenerUrl -Test 'Post'
$response = Invoke-WebRequest -Uri $uri -Method 'Post' -ContentType $contentType -Body $body -SkipHeaderValidation
$result = $response . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$result . data | Should -BeExactly 'bar'
$result . headers . 'Content-Type' | Should -BeExactly $contentType
2018-02-22 13:15:05 -06:00
}
It "Verifies Invoke-WebRequest default ContentType handling reports no error is returned for a valid Content-Type header value and -InFile" {
$contentType = 'text/plain'
$uri = Get-WebListenerUrl -Test 'Post'
$response = Invoke-WebRequest -Uri $uri -Method 'Post' -ContentType $contentType -InFile $Testfile
$result = $response . Content | ConvertFrom-Json
# Match used due to inconsistent newline rendering
2018-03-01 23:00:00 -06:00
$result . data | Should -Match 'bar'
$result . headers . 'Content-Type' | Should -BeExactly $contentType
2018-02-22 13:15:05 -06:00
}
It "Verifies Invoke-WebRequest default ContentType handling reports an error is returned for an invalid Content-Type header value and -InFile" {
$contentType = 'foo'
$uri = Get-WebListenerUrl -Test 'Post'
{ Invoke-WebRequest -Uri $uri -Method 'Post' -ContentType $contentType -InFile $Testfile -ErrorAction 'Stop' } |
2018-05-17 14:42:04 -07:00
Should -Throw -ErrorId "WebCmdletContentTypeException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
2018-02-22 13:15:05 -06:00
}
It "Verifies Invoke-WebRequest default ContentType handling reports no error is returned for an invalid Content-Type header value, -Infile, and -SkipHeaderValidation" {
$contentType = 'foo'
$uri = Get-WebListenerUrl -Test 'Post'
$response = Invoke-WebRequest -Uri $uri -Method 'Post' -ContentType $contentType -InFile $Testfile -SkipHeaderValidation
$result = $response . Content | ConvertFrom-Json
# Match used due to inconsistent newline rendering
2018-03-01 23:00:00 -06:00
$result . data | Should -Match 'bar'
$result . headers . 'Content-Type' | Should -BeExactly $contentType
2018-02-22 13:15:05 -06:00
}
2019-07-02 12:01:06 -07:00
It "Verifies Invoke-WebRequest applies -ContentType when no -Body is present" {
$contentType = 'application/json'
$uri = Get-WebListenerUrl -Test 'Get'
$response = Invoke-WebRequest -Uri $uri -Method 'GET' -ContentType $contentType
$result = $response . Content | ConvertFrom-Json
$result . data | Should -BeNullOrEmpty
$result . headers . 'Content-Type' | Should -BeExactly $contentType
}
It "Verifies Invoke-WebRequest applies an invalid -ContentType when no -Body is present and -SkipHeaderValidation is present" {
$contentType = 'foo'
$uri = Get-WebListenerUrl -Test 'Get'
$response = Invoke-WebRequest -Uri $uri -Method 'GET' -ContentType $contentType -SkipHeaderValidation
$result = $response . Content | ConvertFrom-Json
$result . data | Should -BeNullOrEmpty
$result . headers . 'Content-Type' | Should -BeExactly $contentType
}
2017-07-14 10:24:20 -07:00
}
2017-08-16 16:25:16 -07:00
#region charset encoding tests
Context "BasicHtmlWebResponseObject Encoding tests" {
It "Verifies Invoke-WebRequest detects charset meta value when the ContentType header does not define it." {
2017-12-04 11:52:14 -06:00
$query = @ {
contenttype = 'text/html'
2018-01-09 15:43:25 -06:00
body = '<html><head><meta charset="Unicode"></head></html>'
2017-12-04 11:52:14 -06:00
}
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2017-08-16 16:25:16 -07:00
$expectedEncoding = [ System.Text.Encoding ]:: GetEncoding ( 'Unicode' )
2017-12-04 11:52:14 -06:00
$response = ExecuteWebRequest -Uri $uri -UseBasicParsing
2017-08-16 16:25:16 -07:00
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
$response . Output . Encoding . EncodingName | Should -Be $expectedEncoding . EncodingName
2020-01-24 19:00:37 +00:00
$response . Output | Should -BeOfType Microsoft . PowerShell . Commands . BasicHtmlWebResponseObject
2017-08-16 16:25:16 -07:00
}
It "Verifies Invoke-WebRequest detects charset meta value when newlines are encountered in the element." {
2017-12-04 11:52:14 -06:00
$query = @ {
contenttype = 'text/html'
2018-01-09 15:43:25 -06:00
body = "<html> `n <head> `n <meta `n charset= `" Unicode `"`n > `n </head> `n </html>"
2017-12-04 11:52:14 -06:00
}
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2017-08-16 16:25:16 -07:00
$expectedEncoding = [ System.Text.Encoding ]:: GetEncoding ( 'Unicode' )
2017-12-04 11:52:14 -06:00
$response = ExecuteWebRequest -Uri $uri -UseBasicParsing
2017-08-16 16:25:16 -07:00
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
$response . Output . Encoding . EncodingName | Should -Be $expectedEncoding . EncodingName
2020-01-24 19:00:37 +00:00
$response . Output | Should -BeOfType Microsoft . PowerShell . Commands . BasicHtmlWebResponseObject
2017-08-16 16:25:16 -07:00
}
It "Verifies Invoke-WebRequest detects charset meta value when the attribute value is unquoted." {
2017-12-04 11:52:14 -06:00
$query = @ {
contenttype = 'text/html'
2018-01-09 15:43:25 -06:00
body = '<html><head><meta charset = Unicode></head></html>'
2017-12-04 11:52:14 -06:00
}
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2017-08-16 16:25:16 -07:00
$expectedEncoding = [ System.Text.Encoding ]:: GetEncoding ( 'Unicode' )
2017-12-04 11:52:14 -06:00
$response = ExecuteWebRequest -Uri $uri -UseBasicParsing
2017-08-16 16:25:16 -07:00
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
$response . Output . Encoding . EncodingName | Should -Be $expectedEncoding . EncodingName
2020-01-24 19:00:37 +00:00
$response . Output | Should -BeOfType Microsoft . PowerShell . Commands . BasicHtmlWebResponseObject
2017-08-16 16:25:16 -07:00
}
It "Verifies Invoke-WebRequest detects http-equiv charset meta value when the ContentType header does not define it." {
2017-12-04 11:52:14 -06:00
$query = @ {
contenttype = 'text/html'
2018-01-09 15:43:25 -06:00
body = "<html><head> `n <meta http-equiv= `" content-type `" content= `" text/html; charset=Unicode `" > `n </head> `n </html>"
2017-12-04 11:52:14 -06:00
}
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2017-08-16 16:25:16 -07:00
$expectedEncoding = [ System.Text.Encoding ]:: GetEncoding ( 'Unicode' )
2017-12-04 11:52:14 -06:00
$response = ExecuteWebRequest -Uri $uri -UseBasicParsing
2017-08-16 16:25:16 -07:00
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
$response . Output . Encoding . EncodingName | Should -Be $expectedEncoding . EncodingName
2020-01-24 19:00:37 +00:00
$response . Output | Should -BeOfType Microsoft . PowerShell . Commands . BasicHtmlWebResponseObject
2017-08-16 16:25:16 -07:00
}
It "Verifies Invoke-WebRequest detects http-equiv charset meta value newlines are encountered in the element." {
2017-12-04 11:52:14 -06:00
$query = @ {
contenttype = 'text/html'
2018-01-09 15:43:25 -06:00
body = "<html><head> `n <meta `n http-equiv= `" content-type `"`n content= `" text/html; charset=Unicode `" > `n </head> `n </html>"
2017-12-04 11:52:14 -06:00
}
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2017-08-16 16:25:16 -07:00
$expectedEncoding = [ System.Text.Encoding ]:: GetEncoding ( 'Unicode' )
2017-12-04 11:52:14 -06:00
$response = ExecuteWebRequest -Uri $uri -UseBasicParsing
2017-08-16 16:25:16 -07:00
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
$response . Output . Encoding . EncodingName | Should -Be $expectedEncoding . EncodingName
2020-01-24 19:00:37 +00:00
$response . Output | Should -BeOfType Microsoft . PowerShell . Commands . BasicHtmlWebResponseObject
2017-08-16 16:25:16 -07:00
}
It "Verifies Invoke-WebRequest ignores meta charset value when Content-Type header defines it." {
2017-12-04 11:52:14 -06:00
$query = @ {
contenttype = 'text/html; charset=utf-8'
2018-01-09 15:43:25 -06:00
body = '<html><head><meta charset="utf-32"></head></html>'
2017-12-04 11:52:14 -06:00
}
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2017-08-16 16:25:16 -07:00
# NOTE: meta charset should be ignored
$expectedEncoding = [ System.Text.Encoding ]:: UTF8
2017-12-04 11:52:14 -06:00
$response = ExecuteWebRequest -Uri $uri -UseBasicParsing
2017-08-16 16:25:16 -07:00
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
$response . Output . Encoding . EncodingName | Should -Be $expectedEncoding . EncodingName
2020-01-24 19:00:37 +00:00
$response . Output | Should -BeOfType Microsoft . PowerShell . Commands . BasicHtmlWebResponseObject
2017-08-16 16:25:16 -07:00
}
It "Verifies Invoke-WebRequest honors non-utf8 charsets in the Content-Type header" {
2017-12-04 11:52:14 -06:00
$query = @ {
contenttype = 'text/html; charset=utf-16'
2018-01-09 15:43:25 -06:00
body = '<html><head><meta charset="utf-32"></head></html>'
2017-12-04 11:52:14 -06:00
}
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2017-08-16 16:25:16 -07:00
# NOTE: meta charset should be ignored
$expectedEncoding = [ System.Text.Encoding ]:: GetEncoding ( 'utf-16' )
2017-12-04 11:52:14 -06:00
$response = ExecuteWebRequest -Uri $uri -UseBasicParsing
2017-08-16 16:25:16 -07:00
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
$response . Output . Encoding . EncodingName | Should -Be $expectedEncoding . EncodingName
2020-01-24 19:00:37 +00:00
$response . Output | Should -BeOfType Microsoft . PowerShell . Commands . BasicHtmlWebResponseObject
2017-08-16 16:25:16 -07:00
}
2022-11-02 18:34:09 +01:00
It "Verifies Invoke-WebRequest defaults to iso-UTF-8 when an unsupported/invalid charset is declared" {
2017-12-04 11:52:14 -06:00
$query = @ {
contenttype = 'text/html'
2018-01-09 15:43:25 -06:00
body = '<html><head><meta charset="invalid"></head></html>'
2017-12-04 11:52:14 -06:00
}
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2018-02-21 23:31:00 -06:00
$expectedEncoding = [ System.Text.Encoding ]:: UTF8
$response = ExecuteWebRequest -Uri $uri -UseBasicParsing
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
$response . Output . Encoding . EncodingName | Should -Be $expectedEncoding . EncodingName
2020-01-24 19:00:37 +00:00
$response . Output | Should -BeOfType Microsoft . PowerShell . Commands . BasicHtmlWebResponseObject
2022-11-02 18:34:09 +01:00
}
It "Verifies Invoke-WebRequest defaults to UTF-8 when an unsupported/invalid charset is declared using http-equiv" {
$query = @ {
contenttype = 'text/html'
body = "<html><head> `n <meta http-equiv= `" content-type `" content= `" text/html; charset=Invalid `" > `n </head> `n </html>"
}
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
$expectedEncoding = [ System.Text.Encoding ]:: UTF8
$response = ExecuteWebRequest -Uri $uri -UseBasicParsing
$response . Error | Should -BeNullOrEmpty
$response . Output . Encoding . EncodingName | Should -Be $expectedEncoding . EncodingName
$response . Output | Should -BeOfType Microsoft . PowerShell . Commands . BasicHtmlWebResponseObject
2018-02-21 23:31:00 -06:00
}
2017-08-16 16:25:16 -07:00
}
#endregion charset encoding tests
2017-08-21 12:48:25 -05:00
#region Content Header Inclusion
2019-07-15 19:52:01 +00:00
Context "Content Header" {
It "Verifies Invoke-WebRequest includes Content headers in Headers property" {
$query = @ {
contenttype = 'text/plain'
body = 'OK'
}
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
$command = "Invoke-WebRequest -Uri ' $uri '"
$result = ExecuteWebCommand -command $command
ValidateResponse $result
2017-12-04 11:52:14 -06:00
2019-07-15 19:52:01 +00:00
$result . Output . Headers . 'Content-Type' | Should -Be 'text/plain'
$result . Output . Headers . 'Content-Length' | Should -Be 2
2017-12-04 11:52:14 -06:00
}
2017-08-21 12:48:25 -05:00
2019-07-15 19:52:01 +00:00
It "Verifies Invoke-WebRequest includes Content headers in RawContent property" {
$query = @ {
contenttype = 'text/plain'
body = 'OK'
}
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
$command = "Invoke-WebRequest -Uri ' $uri '"
$result = ExecuteWebCommand -command $command
ValidateResponse $result
2017-08-21 12:48:25 -05:00
2019-07-15 19:52:01 +00:00
$result . Output . RawContent | Should -Match ([ regex ]:: Escape ( 'Content-Type: text/plain' ))
$result . Output . RawContent | Should -Match ([ regex ]:: Escape ( 'Content-Length: 2' ))
2017-12-04 11:52:14 -06:00
}
2017-08-21 12:48:25 -05:00
2019-07-15 19:52:01 +00:00
It "Verifies Invoke-WebRequest Supports Multiple response headers with same name" {
$query = @ {
contenttype = 'text/plain'
body = 'OK'
headers = @ {
'X-Fake-Header' = @ ( 'testvalue01' , 'testvalue02' )
} | ConvertTo-Json -Compress
}
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
$command = "Invoke-WebRequest -Uri ' $uri '"
$result = ExecuteWebCommand -command $command
ValidateResponse $result
2017-08-21 12:48:25 -05:00
2019-07-15 19:52:01 +00:00
$result . Output . Headers . 'X-Fake-Header' . Count | Should -Be 2
$result . Output . Headers . 'X-Fake-Header' . Contains ( 'testvalue01' ) | Should -BeTrue
$result . Output . Headers . 'X-Fake-Header' . Contains ( 'testvalue02' ) | Should -BeTrue
$result . Output . RawContent | Should -Match ([ regex ]:: Escape ( 'X-Fake-Header: testvalue01' ))
$result . Output . RawContent | Should -Match ([ regex ]:: Escape ( 'X-Fake-Header: testvalue02' ))
2017-12-04 11:52:14 -06:00
}
2017-08-21 12:48:25 -05:00
2019-07-15 19:52:01 +00:00
It "Verifies Invoke-WebRequest does not sent expect 100-continue headers by default" {
$uri = Get-WebListenerUrl -Test 'Get'
2017-08-21 12:48:25 -05:00
2019-07-15 19:52:01 +00:00
$response = Invoke-WebRequest -Uri $uri
$result = $response . Content | ConvertFrom-Json
2019-01-18 22:16:18 -08:00
2019-07-15 19:52:01 +00:00
$result . headers . Expect | Should -BeNullOrEmpty
$result . method | Should -BeExactly "GET"
$result . url | Should -BeExactly $uri . ToString ()
}
2019-01-18 22:16:18 -08:00
2019-07-15 19:52:01 +00:00
It "Verifies Invoke-WebRequest sends expect 100-continue header when defined in -Headers" {
$uri = Get-WebListenerUrl -Test 'Get'
2019-01-18 22:16:18 -08:00
2019-07-15 19:52:01 +00:00
$response = Invoke-WebRequest -Uri $uri -Headers @ { Expect = '100-continue' }
$result = $response . Content | ConvertFrom-Json
2019-01-18 22:16:18 -08:00
2019-07-15 19:52:01 +00:00
$result . headers . Expect | Should -BeExactly '100-continue'
$result . method | Should -BeExactly "GET"
$result . url | Should -BeExactly $uri . ToString ()
}
2019-01-18 22:16:18 -08:00
}
2017-08-21 12:48:25 -05:00
#endregion Content Header Inclusion
2017-09-01 13:31:15 -05:00
Context "HTTPS Tests" {
It "Validate Invoke-WebRequest -SkipCertificateCheck" {
# validate that exception is thrown for URI with expired certificate
$Uri = Get-WebListenerUrl -Https
$command = "Invoke-WebRequest -Uri ' $Uri '"
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
$result . Error . FullyQualifiedErrorId | Should -Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
2017-10-05 09:46:33 -07:00
2017-09-01 13:31:15 -05:00
# validate that no exception is thrown for URI with expired certificate when using -SkipCertificateCheck option
$Uri = Get-WebListenerUrl -Https
$command = "Invoke-WebRequest -Uri ' $Uri ' -SkipCertificateCheck"
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
$result . Error | Should -BeNullOrEmpty
2017-09-01 13:31:15 -05:00
}
2017-10-05 09:46:33 -07:00
2017-09-01 13:31:15 -05:00
It "Validate Invoke-WebRequest returns native HTTPS error message in exception" {
$uri = Get-WebListenerUrl -Https
$command = "Invoke-WebRequest -Uri ' $uri '"
$result = ExecuteWebCommand -command $command
2017-10-05 09:46:33 -07:00
2017-09-01 13:31:15 -05:00
# need to check against inner exception since Linux and Windows uses different HTTP client libraries so errors aren't the same
2018-03-01 23:00:00 -06:00
$result . Error . ErrorDetails . Message | Should -Match $result . Error . Exception . InnerException . Message
$result . Error . FullyQualifiedErrorId | Should -Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
2017-09-01 13:31:15 -05:00
}
2017-10-05 09:46:33 -07:00
2018-01-09 15:43:25 -06:00
It "Verifies Invoke-WebRequest Certificate Authentication Fails without -Certificate" {
2017-09-01 13:31:15 -05:00
$uri = Get-WebListenerUrl -Https -Test 'Cert'
2017-10-05 09:46:33 -07:00
$result = Invoke-WebRequest -Uri $uri -SkipCertificateCheck |
2017-09-01 13:31:15 -05:00
Select-Object -ExpandProperty Content |
ConvertFrom-Json
2017-10-05 09:46:33 -07:00
2018-03-01 23:00:00 -06:00
$result . Status | Should -Be 'FAILED'
2017-09-01 13:31:15 -05:00
}
2017-10-05 09:46:33 -07:00
2018-05-09 06:35:52 -05:00
It "Verifies Invoke-WebRequest Certificate Authentication Successful with -Certificate" {
2017-09-01 13:31:15 -05:00
$uri = Get-WebListenerUrl -Https -Test 'Cert'
$certificate = Get-WebListenerClientCertificate
2017-10-05 09:46:33 -07:00
$result = Invoke-WebRequest -Uri $uri -Certificate $certificate -SkipCertificateCheck |
2017-09-01 13:31:15 -05:00
Select-Object -ExpandProperty Content |
ConvertFrom-Json
2017-10-05 09:46:33 -07:00
2018-03-01 23:00:00 -06:00
$result . Status | Should -Be 'OK'
$result . Thumbprint | Should -Be $certificate . Thumbprint
2017-09-01 13:31:15 -05:00
}
2017-08-31 04:30:35 -05:00
}
2017-09-12 11:41:36 -05:00
Context "Multipart/form-data Tests" {
2018-01-24 23:17:55 -06:00
<#
Content-Type request headers for multipart/form-data appear as:
multipart/form-data; boundary="0ab0cb90-f01b-4c15-bd4d-53d073efcc1d"
MultipartFormDataContent sets a random GUID for the boundary before submitting the request
to the remote endpoint. Tests in this context for Content-Type match 'multipart/form-data'
as we do not have access to the random GUID.
#>
<#
Kestrel/ASP.NET inconsistently renders the new line for uploaded text files.
File content tests in this context use match as a workaround.
#>
BeforeAll {
$file1Name = "testfile1.txt"
$file1Path = Join-Path $testdrive $file1Name
$file1Contents = "Test123"
$file1Contents | Set-Content $file1Path -Force
$file2Name = "testfile2.txt"
$file2Path = Join-Path $testdrive $file2Name
$file2Contents = "Test456"
$file2Contents | Set-Content $file2Path -Force
2023-06-12 18:55:32 +02:00
$file3Name = "Kündigung_Mustermann_Max.TTA_2023_01_30.txt"
$file3Path = Join-Path $testdrive $file3Name
$file3Contents = "Test789"
$file3Contents | Set-Content $file3Path -Force
2018-01-24 23:17:55 -06:00
}
2017-09-12 11:41:36 -05:00
It "Verifies Invoke-WebRequest Supports Multipart String Values" {
$body = GetMultipartBody -String
$uri = Get-WebListenerUrl -Test 'Multipart'
$response = Invoke-WebRequest -Uri $uri -Body $body -Method 'POST'
$result = $response . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$result . Headers . 'Content-Type' | Should -Match 'multipart/form-data'
$result . Items . TestString [ 0 ] | Should -Be 'TestValue'
2017-09-12 11:41:36 -05:00
}
2018-01-24 23:17:55 -06:00
2017-09-12 11:41:36 -05:00
It "Verifies Invoke-WebRequest Supports Multipart File Values" {
$body = GetMultipartBody -File
$uri = Get-WebListenerUrl -Test 'Multipart'
$response = Invoke-WebRequest -Uri $uri -Body $body -Method 'POST'
$result = $response . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$result . Headers . 'Content-Type' | Should -Match 'multipart/form-data'
$result . Files [ 0 ]. FileName | Should -Be 'multipart.txt'
$result . Files [ 0 ]. ContentType | Should -Be 'text/plain'
$result . Files [ 0 ]. Content | Should -Match 'TestContent'
2017-09-12 11:41:36 -05:00
}
2018-01-24 23:17:55 -06:00
2017-09-12 11:41:36 -05:00
It "Verifies Invoke-WebRequest Supports Mixed Multipart String and File Values" {
$body = GetMultipartBody -String -File
$uri = Get-WebListenerUrl -Test 'Multipart'
$response = Invoke-WebRequest -Uri $uri -Body $body -Method 'POST'
$result = $response . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$result . Headers . 'Content-Type' | Should -Match 'multipart/form-data'
$result . Items . TestString [ 0 ] | Should -Be 'TestValue'
$result . Files [ 0 ]. FileName | Should -Be 'multipart.txt'
$result . Files [ 0 ]. ContentType | Should -Be 'text/plain'
$result . Files [ 0 ]. Content | Should -Match 'TestContent'
2017-09-12 11:41:36 -05:00
}
2018-01-24 23:17:55 -06:00
It "Verifies Invoke-WebRequest -Form supports string values" {
$form = @ { TestString = "TestValue" }
$uri = Get-WebListenerUrl -Test 'Multipart'
$response = Invoke-WebRequest -Uri $uri -Form $form -Method 'POST'
$result = $response . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$result . Headers . 'Content-Type' | Should -Match 'multipart/form-data'
$result . Items . TestString . Count | Should -Be 1
$result . Items . TestString [ 0 ] | Should -BeExactly 'TestValue'
2018-01-24 23:17:55 -06:00
}
It "Verifies Invoke-WebRequest -Form supports a collection of string values" {
$form = @ { TestStrings = "TestValue" , "TestValue2" }
$uri = Get-WebListenerUrl -Test 'Multipart'
$response = Invoke-WebRequest -Uri $uri -Form $form -Method 'POST'
$result = $response . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$result . Headers . 'Content-Type' | Should -Match 'multipart/form-data'
$result . Items . TestStrings . Count | Should -Be 2
$result . Items . TestStrings [ 0 ] | Should -BeExactly 'TestValue'
$result . Items . TestStrings [ 1 ] | Should -BeExactly 'TestValue2'
2018-01-24 23:17:55 -06:00
}
It "Verifies Invoke-WebRequest -Form supports file values" {
$form = @ { TestFile = [ System.IO.FileInfo ] $file1Path }
$uri = Get-WebListenerUrl -Test 'Multipart'
$response = Invoke-WebRequest -Uri $uri -Form $form -Method 'POST'
$result = $response . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$result . Headers . 'Content-Type' | Should -Match 'multipart/form-data'
$result . Files . Count | Should -Be 1
2018-01-24 23:17:55 -06:00
2018-03-01 23:00:00 -06:00
$result . Files [ 0 ]. Name | Should -BeExactly "TestFile"
$result . Files [ 0 ]. FileName | Should -BeExactly $file1Name
$result . Files [ 0 ]. ContentType | Should -BeExactly 'application/octet-stream'
$result . Files [ 0 ]. Content | Should -Match $file1Contents
2018-01-24 23:17:55 -06:00
}
2025-11-18 21:49:38 +09:00
It "Verifies Invoke-WebRequest -Form supports read-only file values" {
# Create a read-only test file
$readOnlyFile = Join-Path $TestDrive "readonly-test.txt"
"ReadOnly test content" | Out-File -FilePath $readOnlyFile -Encoding utf8
Set-ItemProperty -Path $readOnlyFile -Name IsReadOnly -Value $true
$form = @ { TestFile = [ System.IO.FileInfo ] $readOnlyFile }
$uri = Get-WebListenerUrl -Test 'Multipart'
$response = Invoke-WebRequest -Uri $uri -Form $form -Method 'POST'
$result = $response . Content | ConvertFrom-Json
$result . Headers . 'Content-Type' | Should -Match 'multipart/form-data'
$result . Files . Count | Should -Be 1
$result . Files [ 0 ]. Name | Should -BeExactly "TestFile"
$result . Files [ 0 ]. FileName | Should -BeExactly "readonly-test.txt"
$result . Files [ 0 ]. ContentType | Should -BeExactly 'application/octet-stream'
$result . Files [ 0 ]. Content | Should -Match "ReadOnly test content"
}
2023-06-12 18:55:32 +02:00
It "Verifies Invoke-WebRequest -Form sets Content-Disposition FileName and FileNameStar." {
$ContentDisposition = [ System.Net.Http.Headers.ContentDispositionHeaderValue ]:: new ( "attachment" )
$ContentDisposition . FileName = $fileName
$ContentDisposition . FileNameStar = $fileName
$form = @ { TestFile = [ System.IO.FileInfo ] $file3Path }
$uri = Get-WebListenerUrl -Test 'Multipart'
$response = Invoke-WebRequest -Uri $uri -Form $form -Method 'POST'
$result = $response . Content | ConvertFrom-Json
$result . Headers . 'Content-Type' | Should -Match 'multipart/form-data'
$result . Files . Count | Should -Be 1
$result . Files [ 0 ]. ContentDisposition . FileName | Should -Be $ContentDisposition . FileName
$result . Files [ 0 ]. ContentDisposition . FileNameStar | Should -Be $ContentDisposition . FileNameStar
}
2018-01-24 23:17:55 -06:00
It "Verifies Invoke-WebRequest -Form supports a collection of file values" {
$form = @ { TestFiles = [ System.IO.FileInfo ] $file1Path , [ System.IO.FileInfo ] $file2Path }
$uri = Get-WebListenerUrl -Test 'Multipart'
$response = Invoke-WebRequest -Uri $uri -Form $form -Method 'POST'
$result = $response . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$result . Headers . 'Content-Type' | Should -Match 'multipart/form-data'
$result . Files . Count | Should -Be 2
2018-01-24 23:17:55 -06:00
2018-03-01 23:00:00 -06:00
$result . Files [ 0 ]. Name | Should -BeExactly "TestFiles"
$result . Files [ 0 ]. FileName | Should -BeExactly $file1Name
$result . Files [ 0 ]. ContentType | Should -BeExactly 'application/octet-stream'
$result . Files [ 0 ]. Content | Should -Match $file1Contents
2018-01-24 23:17:55 -06:00
2018-03-01 23:00:00 -06:00
$result . Files [ 1 ]. Name | Should -BeExactly "TestFiles"
$result . Files [ 1 ]. FileName | Should -BeExactly $file2Name
$result . Files [ 1 ]. ContentType | Should -BeExactly 'application/octet-stream'
$result . Files [ 1 ]. Content | Should -Match $file2Contents
2018-01-24 23:17:55 -06:00
}
It "Verifies Invoke-WebRequest -Form supports combinations of strings and files" {
$form = @ {
TestStrings = "TestValue" , "TestValue2"
TestFiles = [ System.IO.FileInfo ] $file1Path , [ System.IO.FileInfo ] $file2Path
}
$uri = Get-WebListenerUrl -Test 'Multipart'
$response = Invoke-WebRequest -Uri $uri -Form $form -Method 'POST'
$result = $response . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$result . Headers . 'Content-Type' | Should -Match 'multipart/form-data'
$result . Items . TestStrings . Count | Should -Be 2
$result . Files . Count | Should -Be 2
2018-01-24 23:17:55 -06:00
2018-03-01 23:00:00 -06:00
$result . Items . TestStrings [ 0 ] | Should -BeExactly 'TestValue'
$result . Items . TestStrings [ 1 ] | Should -BeExactly 'TestValue2'
2018-01-24 23:17:55 -06:00
2018-03-01 23:00:00 -06:00
$result . Files [ 0 ]. Name | Should -Be "TestFiles"
$result . Files [ 0 ]. FileName | Should -BeExactly $file1Name
$result . Files [ 0 ]. ContentType | Should -BeExactly 'application/octet-stream'
$result . Files [ 0 ]. Content | Should -Match $file1Contents
2018-01-24 23:17:55 -06:00
2018-03-01 23:00:00 -06:00
$result . Files [ 1 ]. Name | Should -BeExactly "TestFiles"
$result . Files [ 1 ]. FileName | Should -BeExactly $file2Name
$result . Files [ 1 ]. ContentType | Should -BeExactly 'application/octet-stream'
$result . Files [ 1 ]. Content | Should -Match $file2Contents
2018-01-24 23:17:55 -06:00
}
It "Verifies Invoke-WebRequest -Form is mutually exclusive with -Body" {
$form = @ { TestString = "TestValue" }
$body = "test"
$uri = Get-WebListenerUrl -Test 'Multipart'
{ Invoke-WebRequest -Uri $uri -Form $form -Body $Body -ErrorAction 'Stop' } |
2018-05-17 14:42:04 -07:00
Should -Throw -ErrorId 'WebCmdletBodyFormConflictException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand'
2018-01-24 23:17:55 -06:00
}
It "Verifies Invoke-WebRequest -Form is mutually exclusive with -InFile" {
$form = @ { TestString = "TestValue" }
$uri = Get-WebListenerUrl -Test 'Multipart'
{ Invoke-WebRequest -Uri $uri -Form $form -InFile $file1Path -ErrorAction 'Stop' } |
2018-05-17 14:42:04 -07:00
Should -Throw -ErrorId 'WebCmdletFormInFileConflictException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand'
2018-01-24 23:17:55 -06:00
}
2017-09-12 11:41:36 -05:00
}
2017-10-17 21:08:06 -05:00
Context "Invoke-WebRequest -Authentication tests" {
BeforeAll {
#[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Demo/doc/test secret.")]
$token = "testpassword" | ConvertTo-SecureString -AsPlainText -Force
2018-01-09 15:43:25 -06:00
$credential = [ pscredential ]:: new ( "testuser" , $token )
2017-10-17 21:08:06 -05:00
$httpUri = Get-WebListenerUrl -Test 'Get'
$httpsUri = Get-WebListenerUrl -Test 'Get' -Https
2017-11-10 10:11:57 -06:00
$httpBasicUri = Get-WebListenerUrl -Test 'Auth' -TestValue 'Basic'
$httpsBasicUri = Get-WebListenerUrl -Test 'Auth' -TestValue 'Basic' -Https
2017-10-17 21:08:06 -05:00
$testCases = @ (
@ { Authentication = "bearer" }
@ { Authentication = "OAuth" }
)
}
It "Verifies Invoke-WebRequest -Authentication Basic" {
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpsUri
Authentication = "Basic"
Credential = $credential
2017-10-17 21:08:06 -05:00
SkipCertificateCheck = $true
}
$Response = Invoke-WebRequest @params
$result = $response . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$result . Headers . Authorization | Should -BeExactly "Basic dGVzdHVzZXI6dGVzdHBhc3N3b3Jk"
2017-10-17 21:08:06 -05:00
}
2019-05-06 17:15:04 -07:00
It "Verifies Invoke-WebRequest -Authentication Basic with null username" {
$credential = [ pscredential ]:: new ([ PSCustomObject ] @ { UserName = $null ; Password = $token . psobject . BaseObject })
$params = @ {
Uri = $httpsUri
Authentication = "Basic"
Credential = $credential
SkipCertificateCheck = $true
}
$Response = Invoke-WebRequest @params
$result = $response . Content | ConvertFrom-Json
$result . Headers . Authorization | Should -BeExactly "Basic OnRlc3RwYXNzd29yZA=="
}
2017-10-17 21:08:06 -05:00
It "Verifies Invoke-WebRequest -Authentication <Authentication>" -TestCases $testCases {
param ( $Authentication )
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpsUri
Authentication = $Authentication
Token = $token
2017-10-17 21:08:06 -05:00
SkipCertificateCheck = $true
}
$Response = Invoke-WebRequest @params
$result = $response . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$result . Headers . Authorization | Should -BeExactly "Bearer testpassword"
2017-10-17 21:08:06 -05:00
}
It "Verifies Invoke-WebRequest -Authentication does not support -UseDefaultCredentials" {
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpsUri
Token = $token
Authentication = "OAuth"
2017-10-17 21:08:06 -05:00
UseDefaultCredentials = $true
2018-01-09 15:43:25 -06:00
ErrorAction = 'Stop'
SkipCertificateCheck = $true
2017-10-17 21:08:06 -05:00
}
2018-05-17 14:42:04 -07:00
{ Invoke-WebRequest @params } | Should -Throw -ErrorId "WebCmdletAuthenticationConflictException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
2017-10-17 21:08:06 -05:00
}
It "Verifies Invoke-WebRequest -Authentication does not support Both -Credential and -Token" {
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpsUri
Token = $token
Credential = $credential
Authentication = "OAuth"
ErrorAction = 'Stop'
2017-10-17 21:08:06 -05:00
SkipCertificateCheck = $true
}
2018-05-17 14:42:04 -07:00
{ Invoke-WebRequest @params } | Should -Throw -ErrorId "WebCmdletAuthenticationTokenConflictException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
2017-10-17 21:08:06 -05:00
}
It "Verifies Invoke-WebRequest -Authentication <Authentication> requires -Token" -TestCases $testCases {
param ( $Authentication )
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpsUri
Authentication = $Authentication
ErrorAction = 'Stop'
2017-10-17 21:08:06 -05:00
SkipCertificateCheck = $true
}
2018-05-17 14:42:04 -07:00
{ Invoke-WebRequest @params } | Should -Throw -ErrorId "WebCmdletAuthenticationTokenNotSuppliedException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
2017-10-17 21:08:06 -05:00
}
It "Verifies Invoke-WebRequest -Authentication Basic requires -Credential" {
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpsUri
Authentication = "Basic"
ErrorAction = 'Stop'
2017-10-17 21:08:06 -05:00
SkipCertificateCheck = $true
}
2018-05-17 14:42:04 -07:00
{ Invoke-WebRequest @params } | Should -Throw -ErrorId "WebCmdletAuthenticationCredentialNotSuppliedException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
2017-10-17 21:08:06 -05:00
}
It "Verifies Invoke-WebRequest -Authentication Requires HTTPS" {
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpUri
Token = $token
2017-10-17 21:08:06 -05:00
Authentication = "OAuth"
2018-01-09 15:43:25 -06:00
ErrorAction = 'Stop'
2017-10-17 21:08:06 -05:00
}
2018-05-17 14:42:04 -07:00
{ Invoke-WebRequest @params } | Should -Throw -ErrorId "WebCmdletAllowUnencryptedAuthenticationRequiredException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
2017-10-17 21:08:06 -05:00
}
It "Verifies Invoke-WebRequest -Authentication Can use HTTP with -AllowUnencryptedAuthentication" {
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpUri
Token = $token
Authentication = "OAuth"
2017-10-17 21:08:06 -05:00
AllowUnencryptedAuthentication = $true
}
$Response = Invoke-WebRequest @params
$result = $response . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$result . Headers . Authorization | Should -BeExactly "Bearer testpassword"
2017-10-17 21:08:06 -05:00
}
2017-11-10 10:11:57 -06:00
It "Verifies Invoke-WebRequest Negotiated -Credential over HTTPS" {
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpsBasicUri
Credential = $credential
2017-11-10 10:11:57 -06:00
SkipCertificateCheck = $true
}
$Response = Invoke-WebRequest @params
$result = $response . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$result . Headers . Authorization | Should -BeExactly "Basic dGVzdHVzZXI6dGVzdHBhc3N3b3Jk"
2017-11-10 10:11:57 -06:00
}
It "Verifies Invoke-WebRequest Negotiated -Credential Requires HTTPS" {
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpBasicUri
Credential = $credential
2017-11-10 10:11:57 -06:00
ErrorAction = 'Stop'
}
2018-05-17 14:42:04 -07:00
{ Invoke-WebRequest @params } | Should -Throw -ErrorId "WebCmdletAllowUnencryptedAuthenticationRequiredException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
2017-11-10 10:11:57 -06:00
}
It "Verifies Invoke-WebRequest Negotiated -Credential Can use HTTP with -AllowUnencryptedAuthentication" {
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpBasicUri
Credential = $credential
2017-11-10 10:11:57 -06:00
AllowUnencryptedAuthentication = $true
}
$Response = Invoke-WebRequest @params
$result = $response . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$result . Headers . Authorization | Should -BeExactly "Basic dGVzdHVzZXI6dGVzdHBhc3N3b3Jk"
2017-11-10 10:11:57 -06:00
}
# UseDefaultCredentials is only reliably testable on Windows
It "Verifies Invoke-WebRequest Negotiated -UseDefaultCredentials with '<AuthType>' over HTTPS" -Skip: $ (! $IsWindows ) -TestCases @ (
@ { AuthType = 'NTLM' }
@ { AuthType = 'Negotiate' }
) {
param ( $AuthType )
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = Get-WebListenerUrl -Test 'Auth' -TestValue $AuthType -Https
2017-11-10 10:11:57 -06:00
UseDefaultCredentials = $true
2018-01-09 15:43:25 -06:00
SkipCertificateCheck = $true
2017-11-10 10:11:57 -06:00
}
$Response = Invoke-WebRequest @params
$result = $response . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$result . Headers . Authorization | Should -Match "^ $AuthType "
2017-11-10 10:11:57 -06:00
}
# The error condition can at least be tested on all platforms.
It "Verifies Invoke-WebRequest Negotiated -UseDefaultCredentials Requires HTTPS" {
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpUri
2017-11-10 10:11:57 -06:00
UseDefaultCredentials = $true
2018-01-09 15:43:25 -06:00
ErrorAction = 'Stop'
2017-11-10 10:11:57 -06:00
}
2018-05-17 14:42:04 -07:00
{ Invoke-WebRequest @params } | Should -Throw -ErrorId "WebCmdletAllowUnencryptedAuthenticationRequiredException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
2017-11-10 10:11:57 -06:00
}
# UseDefaultCredentials is only reliably testable on Windows
It "Verifies Invoke-WebRequest Negotiated -UseDefaultCredentials with '<AuthType>' Can use HTTP with -AllowUnencryptedAuthentication" -Skip: $ (! $IsWindows ) -TestCases @ (
@ { AuthType = 'NTLM' }
@ { AuthType = 'Negotiate' }
) {
param ( $AuthType )
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = Get-WebListenerUrl -Test 'Auth' -TestValue $AuthType
UseDefaultCredentials = $true
2017-11-10 10:11:57 -06:00
AllowUnencryptedAuthentication = $true
}
$Response = Invoke-WebRequest @params
$result = $response . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$result . Headers . Authorization | Should -Match "^ $AuthType "
2017-11-10 10:11:57 -06:00
}
2017-10-17 21:08:06 -05:00
}
2017-11-13 12:45:46 -06:00
Context "Invoke-WebRequest -SslProtocol Test" {
2017-12-04 11:38:30 -08:00
BeforeAll {
2020-09-02 22:18:15 +05:00
# We put Tls13 tests at pending due to modern OS limitations.
# Tracking issue https://github.com/PowerShell/PowerShell/issues/13439
2022-03-25 16:15:16 -07:00
$skipForTls1 = $true
2020-09-23 14:04:01 -07:00
2017-12-04 11:38:30 -08:00
## Test cases for the 1st 'It'
$testCases1 = @ (
@ { Test = @ { SslProtocol = 'Default' ; ActualProtocol = 'Default' }; Pending = $false }
2022-03-25 16:15:16 -07:00
@ { Test = @ { SslProtocol = 'Tls' ; ActualProtocol = 'Tls' }; Pending = $skipForTls1 }
@ { Test = @ { SslProtocol = 'Tls11' ; ActualProtocol = 'Tls11' }; Pending = $skipForTls1 }
2017-12-06 14:20:44 -06:00
@ { Test = @ { SslProtocol = 'Tls12' ; ActualProtocol = 'Tls12' }; Pending = $false }
2020-09-02 22:18:15 +05:00
@ { Test = @ { SslProtocol = 'Tls13' ; ActualProtocol = 'Tls13' }; Pending = $true }
2018-05-09 06:35:52 -05:00
@ { Test = @ { SslProtocol = 'Tls, Tls11, Tls12' ; ActualProtocol = 'Tls12' }; Pending = $false }
2020-09-02 22:18:15 +05:00
@ { Test = @ { SslProtocol = 'Tls, Tls11, Tls12, Tls13' ; ActualProtocol = 'Tls13' }; Pending = $true }
2018-05-09 06:35:52 -05:00
@ { Test = @ { SslProtocol = 'Tls11, Tls12' ; ActualProtocol = 'Tls12' }; Pending = $false }
2022-03-25 16:15:16 -07:00
@ { Test = @ { SslProtocol = 'Tls, Tls11, Tls12' ; ActualProtocol = 'Tls11' }; Pending = $skipForTls1 }
@ { Test = @ { SslProtocol = 'Tls, Tls11, Tls12, Tls13' ; ActualProtocol = 'Tls11' }; Pending = $skipForTls1 }
@ { Test = @ { SslProtocol = 'Tls11, Tls12' ; ActualProtocol = 'Tls11' }; Pending = $skipForTls1 }
@ { Test = @ { SslProtocol = 'Tls, Tls11' ; ActualProtocol = 'Tls11' }; Pending = $skipForTls1 }
@ { Test = @ { SslProtocol = 'Tls, Tls11, Tls12' ; ActualProtocol = 'Tls' }; Pending = $skipForTls1 }
2020-09-02 22:18:15 +05:00
@ { Test = @ { SslProtocol = 'Tls, Tls11, Tls13' ; ActualProtocol = 'Tls' }; Pending = $true }
2022-03-25 16:15:16 -07:00
@ { Test = @ { SslProtocol = 'Tls, Tls11' ; ActualProtocol = 'Tls' }; Pending = $skipForTls1 }
2018-05-09 06:35:52 -05:00
# Skipping intermediary protocols is not supported on all platforms
2022-03-25 16:15:16 -07:00
# Removed this as Tls now default to Tls12
# @{ Test = @{SslProtocol = 'Tls, Tls12'; ActualProtocol = 'Tls'}; Pending = -not $IsWindows }
2017-12-04 11:38:30 -08:00
@ { Test = @ { SslProtocol = 'Tls, Tls12' ; ActualProtocol = 'Tls12' }; Pending = -not $IsWindows }
)
2017-12-04 11:52:14 -06:00
2017-12-04 11:38:30 -08:00
$testCases2 = @ (
2020-09-02 22:18:15 +05:00
@ { Test = @ { IntendedProtocol = 'Tls' ; ActualProtocol = 'Tls13' }; Pending = $true }
@ { Test = @ { IntendedProtocol = 'Tls11' ; ActualProtocol = 'Tls13' }; Pending = $true }
@ { Test = @ { IntendedProtocol = 'Tls13' ; ActualProtocol = 'Tls' }; Pending = $true }
@ { Test = @ { IntendedProtocol = 'Tls11, Tls12, Tls13' ; ActualProtocol = 'Tls' }; Pending = $true }
@ { Test = @ { IntendedProtocol = 'Tls, Tls12' ; ActualProtocol = 'Tls13' }; Pending = $true }
@ { Test = @ { IntendedProtocol = 'Tls, Tls11' ; ActualProtocol = 'Tls13' }; Pending = $true }
2017-12-04 11:38:30 -08:00
)
2017-11-13 12:45:46 -06:00
}
2017-12-04 11:38:30 -08:00
foreach ( $entry in $testCases1 ) {
It "Verifies Invoke-WebRequest -SslProtocol <SslProtocol> works on <ActualProtocol>" -TestCases ( $entry . Test ) -Pending: ( $entry . Pending ) {
param ( $SslProtocol , $ActualProtocol )
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = Get-WebListenerUrl -Test 'Get' -Https -SslProtocol $ActualProtocol
SslProtocol = $SslProtocol
2017-12-04 11:38:30 -08:00
SkipCertificateCheck = $true
}
$response = Invoke-WebRequest @params
$result = $Response . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$result . headers . Host | Should -Be $params . Uri . Authority
2017-11-13 12:45:46 -06:00
}
}
2017-12-04 11:38:30 -08:00
foreach ( $entry in $testCases2 ) {
It "Verifies Invoke-WebRequest -SslProtocol -SslProtocol <IntendedProtocol> fails on a <ActualProtocol> only connection" -TestCases ( $entry . Test ) -Pending: ( $entry . Pending ) {
param ( $IntendedProtocol , $ActualProtocol )
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = Get-WebListenerUrl -Test 'Get' -Https -SslProtocol $ActualProtocol
SslProtocol = $IntendedProtocol
2017-12-04 11:38:30 -08:00
SkipCertificateCheck = $true
2018-01-09 15:43:25 -06:00
ErrorAction = 'Stop'
2017-12-04 11:38:30 -08:00
}
2018-05-17 14:42:04 -07:00
{ Invoke-WebRequest @params } | Should -Throw -ErrorId 'WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand'
2017-12-04 11:38:30 -08:00
}
}
2017-11-13 12:45:46 -06:00
}
2018-03-26 12:23:24 -07:00
Context "Invoke-WebRequest File Resume Feature" {
BeforeAll {
$outFile = Join-Path $TestDrive "resume.txt"
# Download the entire file to reference in tests
$referenceFile = Join-Path $TestDrive "reference.txt"
$resumeUri = Get-WebListenerUrl -Test 'Resume'
2020-05-07 13:00:30 +01:00
Invoke-WebRequest -Uri $resumeUri -OutFile $referenceFile -ErrorAction Stop
2018-03-26 12:23:24 -07:00
$referenceFileHash = Get-FileHash -Algorithm SHA256 -Path $referenceFile
$referenceFileSize = Get-Item $referenceFile | Select-Object -ExpandProperty Length
}
AfterEach {
Remove-Item -Force -ErrorAction 'SilentlyContinue' -Path $outFile
}
It "Invoke-WebRequest -Resume requires -OutFile" {
{ Invoke-WebRequest -Resume -Uri $resumeUri -ErrorAction Stop } |
Should -Throw -ErrorId 'WebCmdletOutFileMissingException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand'
}
2023-03-21 09:06:50 +01:00
It "Invoke-WebRequest -Resume should fail if -OutFile folder" {
{ Invoke-WebRequest -Resume -Uri $resumeUri -OutFile $TestDrive -ErrorAction Stop } |
Should -Throw -ErrorId 'WebCmdletResumeNotFilePathException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand'
}
2018-03-26 12:23:24 -07:00
It "Invoke-WebRequest -Resume Downloads the whole file when the file does not exist" {
2020-05-07 13:00:30 +01:00
$response = Invoke-WebRequest -Uri $resumeUri -OutFile $outFile -Resume -PassThru
2018-03-26 12:23:24 -07:00
$outFileHash = Get-FileHash -Algorithm SHA256 -Path $outFile
$outFileHash . Hash | Should -BeExactly $referenceFileHash . Hash
Get-Item $outFile | Select-Object -ExpandProperty Length | Should -Be $referenceFileSize
$response . Headers . 'X-WebListener-Has-Range' [ 0 ] | Should -BeExactly 'true'
$response . Headers . 'X-WebListener-Request-Range' [ 0 ] | Should -BeExactly 'bytes=0-'
$response . StatusCode | Should -Be 206
$response . Headers . 'Content-Range' [ 0 ] | Should -BeExactly "bytes 0- $( $referenceFileSize - 1 ) / $referenceFileSize "
}
It "Invoke-WebRequest -Resume overwrites an existing file that is larger than the remote file" {
# Create a file larger than the download file
$largerFileSize = $referenceFileSize + 20
1 .. $largerFileSize | ForEach-Object { [ Byte ] $_ } | Set-Content -AsByteStream $outFile
$largerFileSize = Get-Item $outFile | Select-Object -ExpandProperty Length
2020-05-07 13:00:30 +01:00
$response = Invoke-WebRequest -Uri $resumeUri -OutFile $outFile -Resume -PassThru
2018-03-26 12:23:24 -07:00
$outFileHash = Get-FileHash -Algorithm SHA256 -Path $outFile
$outFileHash . Hash | Should -BeExactly $referenceFileHash . Hash
Get-Item $outFile | Select-Object -ExpandProperty Length | Should -Be $referenceFileSize
Get-Item $outFile | Select-Object -ExpandProperty Length | Should -BeLessThan $largerFileSize
$response . Headers . 'X-WebListener-Has-Range' [ 0 ] | Should -BeExactly 'false'
$response . StatusCode | Should -Be 200
$response . Headers . ContainsKey ( 'Content-Range' ) | Should -BeFalse
}
It "Invoke-WebRequest -Resume overwrites existing file when remote server does not support resume" {
# Create a file larger than the download file
$largerFileSize = $referenceFileSize + 20
1 .. $largerFileSize | ForEach-Object { [ Byte ] $_ } | Set-Content -AsByteStream $outFile
$largerFileSize = Get-Item $outFile | Select-Object -ExpandProperty Length
$uri = Get-WebListenerUrl -Test 'Resume' -TestValue 'NoResume'
$response = Invoke-WebRequest -Uri $uri -OutFile $outFile -Resume -PassThru
$outFileHash = Get-FileHash -Algorithm SHA256 -Path $outFile
$outFileHash . Hash | Should -BeExactly $referenceFileHash . Hash
Get-Item $outFile | Select-Object -ExpandProperty Length | Should -Be $referenceFileSize
$response . Headers . 'X-WebListener-Has-Range' [ 0 ] | Should -BeExactly 'true'
$response . Headers . 'X-WebListener-Request-Range' [ 0 ] | Should -BeExactly "bytes= $largerFileSize -"
$response . StatusCode | Should -Be 200
$response . Headers . ContainsKey ( 'Content-Range' ) | Should -BeFalse
}
It "Invoke-WebRequest -Resume resumes downloading from <bytes> bytes" -TestCases @ (
@ { bytes = 4 }
@ { bytes = 8 }
@ { bytes = 12 }
@ { bytes = 16 }
) {
param ( $bytes , $statuscode )
# Simulate partial download
$uri = Get-WebListenerUrl -Test 'Resume' -TestValue "Bytes/ $bytes "
2020-05-07 13:00:30 +01:00
$null = Invoke-WebRequest -Uri $uri -OutFile $outFile
2018-03-26 12:23:24 -07:00
Get-Item $outFile | Select-Object -ExpandProperty Length | Should -Be $bytes
2020-05-07 13:00:30 +01:00
$response = Invoke-WebRequest -Uri $resumeUri -OutFile $outFile -Resume -PassThru
2018-03-26 12:23:24 -07:00
$outFileHash = Get-FileHash -Algorithm SHA256 -Path $outFile
$outFileHash . Hash | Should -BeExactly $referenceFileHash . Hash
Get-Item $outFile | Select-Object -ExpandProperty Length | Should -Be $referenceFileSize
$response . Headers . 'X-WebListener-Has-Range' [ 0 ] | Should -BeExactly 'true'
$response . Headers . 'X-WebListener-Request-Range' [ 0 ] | Should -BeExactly "bytes= $bytes -"
$response . StatusCode | Should -Be 206
$response . Headers . 'Content-Range' [ 0 ] | Should -BeExactly "bytes $bytes - $( $referenceFileSize - 1 ) / $referenceFileSize "
}
It "Invoke-WebRequest -Resume assumes the file was successfully completed when the local and remote file are the same size." {
# Download the entire file
$uri = Get-WebListenerUrl -Test 'Resume' -TestValue 'NoResume'
2020-05-07 13:00:30 +01:00
$null = Invoke-WebRequest -Uri $uri -OutFile $outFile
2018-03-26 12:23:24 -07:00
$fileSize = Get-Item $outFile | Select-Object -ExpandProperty Length
2020-05-07 13:00:30 +01:00
$response = Invoke-WebRequest -Uri $resumeUri -OutFile $outFile -Resume -PassThru
2018-03-26 12:23:24 -07:00
$outFileHash = Get-FileHash -Algorithm SHA256 -Path $outFile
$outFileHash . Hash | Should -BeExactly $referenceFileHash . Hash
Get-Item $outFile | Select-Object -ExpandProperty Length | Should -Be $referenceFileSize
$response . Headers . 'X-WebListener-Has-Range' [ 0 ] | Should -BeExactly 'true'
$response . Headers . 'X-WebListener-Request-Range' [ 0 ] | Should -BeExactly "bytes= $fileSize -"
# The web cmdlets special case 416 as a success code when the local file and remote file are the same size
$response . StatusCode | Should -Be 416
$response . Headers . 'Content-Range' [ 0 ] | Should -BeExactly "bytes */ $referenceFileSize "
}
}
2018-06-28 21:06:53 -07:00
Context "Invoke-WebRequest retry tests" {
It "Invoke-WebRequest can retry - <Name>" -TestCases @ (
@ { Name = "specified number of times - error 304" ; failureCount = 2 ; failureCode = 304 ; retryCount = 2 }
@ { Name = "specified number of times - error 400" ; failureCount = 3 ; failureCode = 400 ; retryCount = 3 }
@ { Name = "specified number of times - error 599" ; failureCount = 1 ; failureCode = 599 ; retryCount = 2 }
@ { Name = "specified number of times - error 404" ; failureCount = 2 ; failureCode = 404 ; retryCount = 2 }
@ { Name = "when retry count is higher than failure count" ; failureCount = 2 ; failureCode = 404 ; retryCount = 4 }
) {
param ( $failureCount , $retryCount , $failureCode )
$uri = Get-WebListenerUrl -Test 'Retry' -Query @ { sessionid = ( New-Guid ). Guid ; failureCode = $failureCode ; failureCount = $failureCount }
$commandStr = "Invoke-WebRequest -Uri ' $uri ' -MaximumRetryCount $retryCount -RetryIntervalSec 1"
$result = ExecuteWebCommand -command $commandStr
$result . output . StatusCode | Should -Be "200"
$jsonResult = $result . output . Content | ConvertFrom-Json
$jsonResult . failureResponsesSent | Should -Be $failureCount
}
It "Invoke-WebRequest should fail when failureCount is greater than MaximumRetryCount" {
$uri = Get-WebListenerUrl -Test 'Retry' -Query @ { sessionid = ( New-Guid ). Guid ; failureCode = 400 ; failureCount = 4 }
$command = "Invoke-WebRequest -Uri ' $uri ' -MaximumRetryCount 1 -RetryIntervalSec 1"
$result = ExecuteWebCommand -command $command
$jsonError = $result . error | ConvertFrom-Json
$jsonError . error | Should -BeExactly 'Error: HTTP - 400 occurred.'
}
It "Invoke-WebRequest can retry with POST" {
$uri = Get-WebListenerUrl -Test 'Retry'
$sessionId = ( New-Guid ). Guid
$body = @ { sessionid = $sessionId ; failureCode = 404 ; failureCount = 1 }
$commandStr = "Invoke-WebRequest -Uri ' $uri ' -MaximumRetryCount 2 -RetryIntervalSec 1 -Method POST -Body `$ body"
$result = ExecuteWebCommand -command $commandStr
$result . output . StatusCode | Should -Be "200"
$jsonResult = $result . output . Content | ConvertFrom-Json
$jsonResult . SessionId | Should -BeExactly $sessionId
}
2023-05-09 07:57:27 +09:00
It "Invoke-WebRequest respects the Retry-After header value in 429 status" {
$Query = @ {
statusCode = 429
reposnsephrase = 'Too Many Requests'
contenttype = 'application/json'
body = '{"message":"oops"}'
headers = '{"Retry-After":"1"}'
}
$uri = Get-WebListenerUrl -Test 'Response' -Query $Query
$verboseFile = Join-Path $TestDrive -ChildPath verbose . txt
$result = Invoke-WebRequest -Uri $uri -MaximumRetryCount 1 -RetryIntervalSec 3 -SkipHttpErrorCheck -Verbose 4 > $verbosefile
$verboseFile | Should -FileContentMatch 'Retrying after interval of 1 seconds. Status code for previous attempt: TooManyRequests'
}
It "Invoke-WebRequest ignores the Retry-After header value NOT in 429 status" {
$Query = @ {
statusCode = 409
reposnsephrase = 'Conflict'
contenttype = 'application/json'
body = '{"message":"oops"}'
headers = '{"Retry-After":"1"}'
}
$uri = Get-WebListenerUrl -Test 'Response' -Query $Query
$verboseFile = Join-Path $TestDrive -ChildPath verbose . txt
$result = Invoke-WebRequest -Uri $uri -MaximumRetryCount 1 -RetryIntervalSec 3 -SkipHttpErrorCheck -Verbose 4 > $verbosefile
$verboseFile | Should -FileContentMatch 'Retrying after interval of 3 seconds. Status code for previous attempt: Conflict'
}
2018-06-28 21:06:53 -07:00
}
2019-07-15 19:52:01 +00:00
2020-03-24 13:51:55 -04:00
Context "Regex Parsing" {
It 'correctly parses an image with id, class, and src attributes' {
$dosUri = Get-WebListenerUrl -Test 'Dos' -query @ {
dosType = 'img-attribute'
}
$response = Invoke-WebRequest -Uri $dosUri
$response . Images | Should -Not -BeNullOrEmpty
}
2021-11-02 12:39:28 -04:00
$singleInputExpected = @ (
@ { Name = 'foo' ; Value = 'bar' }
)
It 'correctly parses input tag(s) for `<markup>`' -TestCases @ (
@ {
Markup = "<input name='foo' value='bar'>" ;
ExpectedFields = $singleInputExpected
},
@ {
Markup = "<input name='foo' value='bar'/>" ;
ExpectedFields = $singleInputExpected
},
@ {
Markup = "<input name='foo' value='bar'>baz</input>" ;
ExpectedFields = $singleInputExpected
}
@ {
Markup = "<input name='item1' value='bar'><input name='item2' value='foo'><input name='item3'></input><input name='item4' value='fu'><input name='item5' value='bahr'/>" ;
ExpectedFields = @ (
@ { Name = 'item1' ; Value = 'bar' },
@ { Name = 'item2' ; Value = 'foo' },
@ { Name = 'item3' ; Value = $null },
@ { Name = 'item4' ; Value = 'fu' },
@ { Name = 'item5' ; Value = 'bahr' }
)
}
) {
param ( $markup , $expectedFields )
$query = @ {
contenttype = 'text/html'
body = "<html><body> ${markup} </body></html>"
}
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
$response = Invoke-WebRequest -Uri $uri -UseBasicParsing
$response . Error | Should -BeNullOrEmpty
ForEach ( $expectedField in $expectedFields ) {
$actualField = $response . InputFields . FindByName ( $expectedField . Name )
$actualField . Value | Should -Be $expectedField . Value
}
}
2020-03-24 13:51:55 -04:00
}
2019-07-15 19:52:01 +00:00
Context "Denial of service" -Tag 'DOS' {
2020-03-24 13:51:55 -04:00
It "Image Parsing" {
Set-ItResult -Pending -Because "The pathological regex runs fast due to https://github.com/dotnet/runtime/issues/33399. Fixed in .NET 5 preview.2"
$dosUri = Get-WebListenerUrl -Test 'Dos' -query @ {
dosType = 'img'
dosLength = '5000'
}
$script:content = ''
[ TimeSpan ] $timeSpan = Measure-Command {
$response = Invoke-WebRequest -Uri $dosUri
$script:content = $response . content
2020-05-07 13:00:30 +01:00
$response . Images | Out-Null
2020-03-24 13:51:55 -04:00
}
$script:content | Should -Not -BeNullOrEmpty
# pathological regex
$regex = [ RegEx ]:: new ( '<img\s+[^>]*>' )
[ TimeSpan ] $pathologicalTimeSpan = Measure-Command {
$regex . Match ( $content )
}
$pathologicalRatio = $pathologicalTimeSpan . TotalMilliseconds / $timeSpan . TotalMilliseconds
Write-Verbose "Pathological ratio: $pathologicalRatio " -Verbose
# dosLength 4,000 on my 3.5 GHz 6-Core Intel Xeon E5 macpro produced a ratio of 12
# dosLength 5,000 on my 3.5 GHz 6-Core Intel Xeon E5 macpro produced a ratio of 21
# dosLength 10,000 on my 3.5 GHz 6-Core Intel Xeon E5 macpro produced a ratio of 75
# in some cases we will be running in a Docker container with modest resources
$pathologicalRatio | Should -BeGreaterThan 5
}
2019-07-15 19:52:01 +00:00
It "Charset Parsing" {
2022-11-09 15:04:21 -08:00
Set-ItResult -Pending -Because "We need a better way to test this and .NET has made bad regex's run faster"
2019-07-15 19:52:01 +00:00
$dosUri = Get-WebListenerUrl -Test 'Dos' -query @ {
dosType = 'charset'
dosLength = '2850'
}
$script:content = ''
[ TimeSpan ] $timeSpan = Measure-Command {
$response = Invoke-WebRequest -Uri $dosUri
$script:content = $response . content
}
# Pathological regex
$regex = [ RegEx ]:: new ( '<meta\s[.\n]*[^><]*charset\s*=\s*["''\n]?(?<charset>[A-Za-z].[^\s"''\n<>]*)[\s"''\n>]' )
2020-01-11 15:41:59 +00:00
$script:content | Should -Not -BeNullOrEmpty
2019-07-15 19:52:01 +00:00
[ TimeSpan ] $pathologicalTimeSpan = Measure-Command {
$regex . Match ( $content )
}
$pathologicalRatio = $pathologicalTimeSpan . TotalMilliseconds / $timeSpan . TotalMilliseconds
Write-Verbose "Pathological ratio: $pathologicalRatio " -Verbose
# dosLength 2,750 on my 3.5 GHz 6-Core Intel Xeon E5 macpro produced a ratio of 13
# dosLength 2,850 on my 3.5 GHz 6-Core Intel Xeon E5 macpro produced a ratio of 22
# dosLength 3,000 on my 3.5 GHz 6-Core Intel Xeon E5 macpro produced a ratio of 31
2020-01-14 08:40:50 -08:00
# in some cases we will be running in a Docker container with modest resources
$pathologicalRatio | Should -BeGreaterThan 5
2019-07-15 19:52:01 +00:00
}
}
2023-03-08 03:42:08 +10:00
Context 'Invoke-WebSession: Connection persistence in a WebSession' {
# Match verbose message from resource name WebSessionConnectionRecreated with message:
# The WebSession properties were changed between requests forcing all HTTP connections in the session to be recreated.
$matchConnRecreatedMessage = [ regex ]:: new ( 'WebSession.+HTTP' )
function RunCheckingPersistence {
param (
[ uri ] $Uri ,
[ string ] $Command ,
[ object ] $Session ,
[ switch ] $ExpectConnectionRecreated ,
[ switch ] $CaptureSession
)
$pwsh = [ PowerShell ]:: Create ()
$pwsh . Runspace . SessionStateProxy . SetVariable ( 'uri' , $Uri )
if ( $Session ) {
$pwsh . Runspace . SessionStateProxy . SetVariable ( 'Session' , $Session )
$command = " $command -WebSession `$ Session"
}
if ( $CaptureSession ) {
$command = " $command -SessionVariable Session"
}
$script = " `$ null = $command -Verbose"
$pwsh . AddScript ( $script ). Invoke ()
$session = $pwsh . Runspace . SessionStateProxy . GetVariable ( 'Session' )
$expectedConnRecreatedCount = if ( $ExpectConnectionRecreated ) { 1 } else { 0 }
( $pwsh . Streams . Verbose | Where-Object { $matchConnRecreatedMessage . Matches ( $_ . Message ) }). Count | Should -Be $expectedConnRecreatedCount
$pwsh . Dispose ()
return $session
}
It 'Connection persistence maintained' {
$uri = Get-WebListenerUrl
$Session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri' -CaptureSession
1 .. 3 | ForEach-Object {
RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri' -Session $Session
}
}
It 'Connection persistence impacted by changing SkipCertificateCheck' {
$uri = Get-WebListenerUrl -Https
# This first request will throw because the certificate is invalid
$session = $null
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri' -CaptureSession
# No change in setting
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri -SkipCertificateCheck:$false' -Session $session
# Skipping cert check changes persistence
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri -SkipCertificateCheck' -Session $session -ExpectConnectionRecreated
# Same settings won't lose persistence
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri -SkipCertificateCheck' -Session $session
# Lose persistence due to changing cert check - this will also throw
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri -SkipCertificateCheck:$false' -Session $session -ExpectConnectionRecreated
}
It 'Connection persistence is not impacted by changing request headers' {
$uri = Get-WebListenerUrl
$session = $null
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri' -CaptureSession
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri -Headers @{ A = "B" }' -Session $session
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri -Headers @{}' -Session $session
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri -Headers @{ A = "C"; B = "D"}' -Session $session
}
It 'Connection persistence is impacted by changing the session cookie jar' {
$uri = Get-WebListenerUrl
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri' -CaptureSession
$session . Cookies = New-Object System . Net . CookieContainer
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri' -Session $session -ExpectConnectionRecreated
# Adding a cookie to the container does not lose persistence
$Session . Cookies . Add ( 'http://localhost' , [ system.net.cookie ]:: new ( 'cookie' , 'value' ))
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri' -Session $session
}
It 'Connection persistence is not impacted by changing the user agent' {
$uri = Get-WebListenerUrl
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri -UserAgent Powershell' -CaptureSession
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri -UserAgent "PowerShell Core"' -Session $session
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri -UserAgent "PowerShell Core with HttpClient"' -Session $session
# Ensure persistence is lost when we change a different setting
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri -NoProxy -UserAgent "PowerShell Core"' -Session $session -ExpectConnectionRecreated
}
It 'Connection persistence is not impacted when NoProxy parameter is not supplied' {
$uri = Get-WebListenerUrl
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri' -CaptureSession
# Explicitly prevent proxy - connection lost
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri -NoProxy' -Session $session -ExpectConnectionRecreated
# Provide explicit switch value - connection maintained
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri -NoProxy:$true' -Session $session
# No spec for proxy - connection maintained
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri' -Session $session
# Two follow up calls without altering anything do not lose connection
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri' -Session $session
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri' -Session $session
}
It 'Connection persistence is not impacted when SslProtocol parameter is not supplied' {
$uri = Get-WebListenerUrl
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri -SslProtocol Tls12' -CaptureSession
# No SslProtocol provided - keeps last value - connection retained
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri' -Session $session
# Explicit default - loses connection
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri -SslProtocol Default' -Session $session -ExpectConnectionRecreated
# No SslProtocol provided - keeps last value - connection retained
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri' -Session $session
# Explicitly set to same value as last time it was set - connection retained
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri -SslProtocol Default' -Session $session
}
It 'Connection persistence is not impacted by Proxy and NoProxy unless changed parameters are used between invocations' {
$uri = Get-WebListenerUrl
$session = RunCheckingPersistence -Uri $uri -Command 'Invoke-WebRequest -Uri $uri' -CaptureSession
$proxy = 'http://127.0.0.1:8080'
$session = RunCheckingPersistence -Uri $uri -Command "Invoke-WebRequest -Uri $uri -proxy $proxy " -Session $session -ExpectConnectionRecreated
# same proxy - do not lose persistence
$session = RunCheckingPersistence -Uri $uri -Command "Invoke-WebRequest -Uri $uri -proxy $proxy " -Session $session
# No proxy at all - use previous setting and don't lose connection
$session = RunCheckingPersistence -Uri $uri -Command "Invoke-WebRequest -Uri $uri " -Session $session
# NoProxy toggles proxy off - loses connection
$session = RunCheckingPersistence -Uri $uri -Command "Invoke-WebRequest -Uri $uri -NoProxy" -Session $session -ExpectConnectionRecreated
# No setting at all - retains NoProxy setting
$session = RunCheckingPersistence -Uri $uri -Command "Invoke-WebRequest -Uri $uri " -Session $session
# Use proxy again - lose connection
$session = RunCheckingPersistence -Uri $uri -Command "Invoke-WebRequest -Uri $uri -proxy $proxy " -Session $session -ExpectConnectionRecreated
# No proxy specified - connection retained
$session = RunCheckingPersistence -Uri $uri -Command "Invoke-WebRequest -Uri $uri " -Session $session
# Proxy changed - lose connection
$proxy = 'http://localhost:8080'
$session = RunCheckingPersistence -Uri $uri -Command "Invoke-WebRequest -Uri $uri -proxy $proxy " -Session $session -ExpectConnectionRecreated
# No proxy specified - connection retained
$session = RunCheckingPersistence -Uri $uri -Command "Invoke-WebRequest -Uri $uri " -Session $session
}
}
2016-07-22 15:09:03 -07:00
}
2018-12-11 14:15:33 -08:00
Describe "Invoke-RestMethod tests" -Tags "Feature" , "RequireAdminOnWindows" {
2017-05-24 15:54:02 -07:00
BeforeAll {
2022-01-03 11:20:33 -08:00
$oldProgress = $ProgressPreference
$ProgressPreference = 'SilentlyContinue'
2017-08-31 04:30:35 -05:00
$WebListener = Start-WebListener
2019-11-07 12:38:24 -08:00
$NotFoundQuery = @ {
statuscode = 404
responsephrase = 'Not Found'
contenttype = 'application/json'
body = '{"message": "oops"}'
headers = "{}"
}
2017-05-24 15:54:02 -07:00
}
2022-01-03 11:20:33 -08:00
AfterAll {
$ProgressPreference = $oldProgress
}
2017-10-06 22:59:31 +02:00
#User-Agent changes on different platforms, so tests should only be run if on the correct platform
It "Invoke-RestMethod returns Correct User-Agent on MacOSX" -Skip: (! $IsMacOS ) {
$uri = Get-WebListenerUrl -Test 'Get'
2018-02-02 13:56:06 -06:00
$command = "Invoke-RestMethod -Uri ' $uri '"
2017-10-06 22:59:31 +02:00
$result = ExecuteWebCommand -command $command
# Validate response
2018-03-01 23:00:00 -06:00
$result . Output . headers . 'User-Agent' | Should -MatchExactly '.*\(Macintosh;.*\) PowerShell\/\d+\.\d+\.\d+.*'
2017-10-06 22:59:31 +02:00
}
It "Invoke-RestMethod returns Correct User-Agent on Linux" -Skip: (! $IsLinux ) {
$uri = Get-WebListenerUrl -Test 'Get'
2018-02-02 13:56:06 -06:00
$command = "Invoke-RestMethod -Uri ' $uri '"
2017-10-06 22:59:31 +02:00
$result = ExecuteWebCommand -command $command
# Validate response
2018-03-01 23:00:00 -06:00
$result . Output . headers . 'User-Agent' | Should -MatchExactly '.*\(Linux;.*\) PowerShell\/\d+\.\d+\.\d+.*'
2017-10-06 22:59:31 +02:00
}
It "Invoke-RestMethod returns Correct User-Agent on Windows" -Skip: (! $IsWindows ) {
2017-09-14 00:23:29 -05:00
$uri = Get-WebListenerUrl -Test 'Get'
2018-02-02 13:56:06 -06:00
$command = "Invoke-RestMethod -Uri ' $uri '"
2016-07-22 15:09:03 -07:00
$result = ExecuteWebCommand -command $command
# Validate response
2018-03-01 23:00:00 -06:00
$result . Output . headers . 'User-Agent' | Should -MatchExactly '.*\(Windows NT \d+\.\d*;.*\) PowerShell\/\d+\.\d+\.\d+.*'
2016-07-22 15:09:03 -07:00
}
2020-01-06 12:11:55 -08:00
It "Invoke-RestMethod with blank ContentType succeeds" {
$uri = Get-WebListenerUrl -Test 'Get'
$command = "Invoke-RestMethod -Uri ' $uri ' -ContentType ''"
$result = ExecuteWebCommand -command $command
# Validate response
$result . Error | Should -BeNullOrEmpty
2022-01-03 11:20:33 -08:00
$result . Output . headers . 'Content-Length' | Should -Be 0
2020-01-06 12:11:55 -08:00
}
2016-07-22 15:09:03 -07:00
It "Invoke-RestMethod returns headers dictionary" {
2017-09-14 00:22:52 -05:00
$uri = Get-WebListenerUrl -Test 'Get'
2018-02-02 13:56:06 -06:00
$command = "Invoke-RestMethod -Uri ' $uri '"
2017-01-16 13:31:14 -08:00
2016-07-22 15:09:03 -07:00
$result = ExecuteWebCommand -command $command
# Validate response
2018-03-01 23:00:00 -06:00
$result . Output . headers . Host | Should -Be $Uri . Authority
2016-07-22 15:09:03 -07:00
}
It "Validate Invoke-RestMethod -DisableKeepAlive" {
# Operation options
2017-09-07 22:53:04 -05:00
$uri = Get-WebListenerUrl -Test 'Get'
2018-02-02 13:56:06 -06:00
$command = "Invoke-RestMethod -Uri ' $uri ' -DisableKeepAlive"
2016-07-22 15:09:03 -07:00
$result = ExecuteWebCommand -command $command
# Validate response
2018-03-01 23:00:00 -06:00
$result . Output . headers . Host | Should -Be $uri . Authority
$result . Output . Headers . Connection | Should -Be "Close"
2016-07-22 15:09:03 -07:00
}
2021-11-03 02:53:36 +03:00
It "Validate Invoke-RestMethod -HttpVersion '<httpVersion>'" -Skip: (! $IsWindows ) -TestCases @ (
@ { httpVersion = '1.1' },
@ { httpVersion = '2' }
) {
param ( $httpVersion )
2023-08-16 11:28:59 -07:00
if ( Test-IsWinServer2012R2 -and $httpVersion -eq '2' ) {
Set-ItResult -Skipped -Because "HTTP/2 is not supported on Windows Server 2012R2"
return
}
2021-11-03 02:53:36 +03:00
# Operation options
$uri = Get-WebListenerUrl -Test 'Get' -Https
$command = "Invoke-RestMethod -Uri $uri -HttpVersion $httpVersion -SkipCertificateCheck"
$result = ExecuteWebCommand -command $command
# Validate response
$result . Output . protocol | Should -Be "HTTP/ $httpVersion "
}
2016-07-22 15:09:03 -07:00
It "Validate Invoke-RestMethod -MaximumRedirection" {
2017-09-25 14:50:15 -05:00
$uri = Get-WebListenerUrl -Test 'Redirect' -TestValue '3'
2017-09-18 11:26:01 -05:00
$command = "Invoke-RestMethod -Uri ' $uri ' -MaximumRedirection 4"
2017-01-16 13:31:14 -08:00
2016-07-22 15:09:03 -07:00
$result = ExecuteWebCommand -command $command
# Validate response
2018-03-01 23:00:00 -06:00
$result . Output . headers . Host | Should -Match $uri . Authority
2016-07-22 15:09:03 -07:00
}
It "Validate Invoke-RestMethod error for -MaximumRedirection" {
2017-09-25 14:50:15 -05:00
$uri = Get-WebListenerUrl -Test 'Redirect' -TestValue '3'
2017-09-18 11:26:01 -05:00
$command = "Invoke-RestMethod -Uri ' $uri ' -MaximumRedirection 2"
2017-01-16 13:31:14 -08:00
2016-07-22 15:09:03 -07:00
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
$result . Error . FullyQualifiedErrorId | Should -Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
2016-07-22 15:09:03 -07:00
}
2023-01-13 13:37:55 +01:00
It "Validate Invoke-RestMethod redirect with -Query destination Http" {
$httpUri = Get-WebListenerUrl -Test 'Get'
$uri = Get-WebListenerUrl -Test 'Redirect' -Query @ { destination = $httpUri }
$command = "Invoke-RestMethod -Uri ' $uri '"
$result = ExecuteWebCommand -command $command
$result . Output . Headers . Host | Should -Be $httpUri . Authority
}
It "Validate Invoke-RestMethod redirect with -Query destination Https" {
$httpsUri = Get-WebListenerUrl -Test 'Get' -Https
$uri = Get-WebListenerUrl -Test 'Redirect' -Https -Query @ { destination = $httpsUri }
$command = "Invoke-RestMethod -Uri ' $uri ' -SkipCertificateCheck"
$result = ExecuteWebCommand -command $command
$result . Output . Headers . Host | Should -Be $httpsUri . Authority
}
2016-07-22 15:09:03 -07:00
It "Invoke-RestMethod supports request that returns page containing UTF-8 data." {
2017-09-25 14:50:15 -05:00
$uri = Get-WebListenerUrl -Test 'Encoding' -TestValue 'Utf8'
2017-09-22 12:09:49 -05:00
$command = "Invoke-RestMethod -Uri ' $uri '"
2017-01-16 13:31:14 -08:00
2017-10-05 09:46:33 -07:00
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
$Result . Output | Should -Match '⡌⠁⠧⠑ ⠼⠁⠒ ⡍⠜⠇⠑⠹⠰⠎ ⡣⠕⠌'
2016-07-22 15:09:03 -07:00
}
2023-03-01 18:56:05 +01:00
It "Invoke-RestMethod -ContentType overwrites Content-Type from -Headers." {
$uri = Get-WebListenerUrl -Test 'POST'
$command = "Invoke-RestMethod -Uri ' $uri ' -ContentType 'application/json' -Headers @{'Content-Type'='plain/text'} -Method 'POST'"
$result = ExecuteWebCommand -command $command
$result . Output . headers . "Content-Type" | Should -BeExactly 'application/json'
}
2019-01-25 23:48:47 -08:00
It "Invoke-RestMethod supports sending requests as UTF8" {
$uri = Get-WebListenerUrl -Test POST
# Body must contain non-ASCII characters
$command = "Invoke-RestMethod -Uri ' $uri ' -body 'проверка' -ContentType 'application/json; charset=utf-8' -method 'POST'"
$result = ExecuteWebCommand -command $command
$Result . Output . Data | Should -BeExactly 'проверка'
}
2023-03-07 05:35:36 +01:00
It "Invoke-RestMethod supports sending XML requests without encoding" {
$uri = Get-WebListenerUrl -Test POST
$body = '<?xml version="1.0"?><foo />'
$result = Invoke-RestMethod -Uri $uri -body ([ xml ] $body ) -ContentType 'text/xml' -method 'POST'
$result . Data | Should -BeExactly $body
}
2019-01-22 10:45:40 -08:00
It "Invoke-RestMethod supports request that returns page containing Code Page 936 data." {
$uri = Get-WebListenerUrl -Test 'Encoding' -TestValue 'CP936'
$command = "Invoke-RestMethod -Uri ' $uri '"
$result = ExecuteWebCommand -command $command
$Result . Output | Should -Match '测试123'
}
2023-06-20 08:07:16 +10:00
It "Invoke-RestMethod validate ConnectionTimeoutSeconds option" {
$uri = Get-WebListenerUrl -Test 'Delay' -TestValue '5'
$command = "Invoke-RestMethod -Uri ' $uri ' -ConnectionTimeoutSeconds 2"
$result = ExecuteWebCommand -command $command
$result . Error . FullyQualifiedErrorId | Should -Be "ConnectionTimeoutReached,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
}
It "Invoke-RestMethod validate TimeoutSec alias" {
2017-09-25 14:50:15 -05:00
$uri = Get-WebListenerUrl -Test 'Delay' -TestValue '5'
$command = "Invoke-RestMethod -Uri ' $uri ' -TimeoutSec 2"
2017-01-16 13:31:14 -08:00
2016-07-22 15:09:03 -07:00
$result = ExecuteWebCommand -command $command
2023-06-20 08:07:16 +10:00
$result . Error . FullyQualifiedErrorId | Should -Be "ConnectionTimeoutReached,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
2017-03-28 21:25:13 +02:00
}
2016-07-22 15:09:03 -07:00
2017-03-28 21:25:13 +02:00
It "Validate Invoke-RestMethod error with -Proxy and -NoProxy option" {
2017-09-25 14:50:15 -05:00
$uri = Get-WebListenerUrl -Test 'Delay' -TestValue '10'
2018-01-31 22:26:05 -06:00
$command = "Invoke-RestMethod -Uri ' $uri ' -Proxy 'http://127.0.0.1:8080' -NoProxy -TimeoutSec 2"
2017-03-28 21:25:13 +02:00
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
$result . Error . FullyQualifiedErrorId | Should -Be "AmbiguousParameterSet,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
2017-03-28 21:25:13 +02:00
}
$testCase = @ (
2018-05-08 09:15:49 +05:00
@ { proxy_address = ( Get-WebListenerUrl ). Authority ; name = 'HTTP proxy' ; protocol = 'http' }
@ { proxy_address = ( Get-WebListenerUrl -https ). Authority ; name = 'HTTPS proxy' ; protocol = 'https' }
2017-03-28 21:25:13 +02:00
)
2018-05-03 04:58:39 +05:00
It "Validate Invoke-RestMethod with -Proxy option - '<name>'" -TestCases $testCase {
2017-03-28 21:25:13 +02:00
param ( $proxy_address , $name , $protocol )
2018-05-03 04:58:39 +05:00
# use external url, but with proxy the external url should not actually be called
$command = "Invoke-RestMethod -Uri ${protocol} ://httpbin.org -Proxy ' ${protocol} :// ${proxy_address} '"
2017-03-28 21:25:13 +02:00
$result = ExecuteWebCommand -command $command
2018-05-03 04:58:39 +05:00
$command = "Invoke-RestMethod -Uri ' ${protocol} :// ${proxy_address} ' -NoProxy"
$expectedResult = ExecuteWebCommand -command $command
$result . Output | Should -BeExactly $expectedResult . Output
2017-03-28 21:25:13 +02:00
}
2016-07-22 15:09:03 -07:00
# Perform the following operation for Invoke-RestMethod
# gzip Returns gzip-encoded data.
# deflate Returns deflate-encoded data.
2023-01-10 04:07:00 +01:00
# brotli Returns brotli-encoded data.
2017-01-16 13:31:14 -08:00
# $dataEncodings = @("Chunked", "Compress", "Deflate", "GZip", "Identity")
2017-10-02 15:46:53 -05:00
# Note: These are the supported options, but we do not have a web service to test them all.
It "Invoke-RestMethod supports request that returns <DataEncoding>-encoded data." -TestCases @ (
2022-10-04 21:33:37 +05:00
@ { DataEncoding = "gzip" }
@ { DataEncoding = "deflate" }
2023-01-10 04:07:00 +01:00
@ { DataEncoding = "brotli" }
2017-10-02 15:46:53 -05:00
) {
param ( $dataEncoding )
$uri = Get-WebListenerUrl -Test 'Compression' -TestValue $dataEncoding
2022-10-04 21:33:37 +05:00
$result = Invoke-RestMethod -Uri $uri
2016-07-22 15:09:03 -07:00
2017-10-02 15:46:53 -05:00
# Validate response content
2022-10-04 21:33:37 +05:00
# The content should be de-compressed. Otherwise, the above 'Invoke-RestMethod' would have thrown because converting to JSON internally would fail.
2018-03-01 23:00:00 -06:00
$result . Headers . Host | Should -BeExactly $uri . Authority
2016-07-22 15:09:03 -07:00
}
# Perform the following operation for Invoke-RestMethod using the following content types: "text/plain", "application/xml", "application/xml"
# post Returns POST data.
# patch Returns PATCH data.
# put Returns PUT data.
# delete Returns DELETE data
2017-12-13 09:28:05 -06:00
$testMethods = @ ( "POST" , "PATCH" , "PUT" , "DELETE" )
2016-07-22 15:09:03 -07:00
$contentTypes = @ ( "text/plain" , "application/xml" , "application/json" )
2018-01-09 15:43:25 -06:00
foreach ( $contentType in $contentTypes ) {
foreach ( $method in $testMethods ) {
2016-07-22 15:09:03 -07:00
# Operation options
2017-12-13 09:28:05 -06:00
$uri = Get-WebListenerUrl -Test $method
2016-07-22 15:09:03 -07:00
$body = GetTestData -contentType $contentType
2017-12-13 09:28:05 -06:00
$command = "Invoke-RestMethod -Uri $uri -Body ' $body ' -Method $method -ContentType $contentType "
2024-07-02 00:35:23 +02:00
$commandNoContentType = "Invoke-RestMethod -Uri $uri -Body ' $body ' -Method $method "
2016-07-22 15:09:03 -07:00
2017-12-13 09:28:05 -06:00
It "Invoke-RestMethod -Uri $uri -Method $method -ContentType $contentType -Body [body data]" {
2016-07-22 15:09:03 -07:00
$result = ExecuteWebCommand -command $command
# Validate response
2018-03-01 23:00:00 -06:00
$result . Output . url | Should -Match $uri
$result . Output . headers . 'Content-Type' | Should -Match $contentType
2016-07-22 15:09:03 -07:00
2017-12-13 09:28:05 -06:00
# Validate that the response Content.data field is the same as what we sent.
2018-03-01 23:00:00 -06:00
$result . Output . data | Should -Be $body
2016-07-22 15:09:03 -07:00
}
2024-07-02 00:35:23 +02:00
It "Invoke-RestMethod -Uri $uri -Method $method -Body [body data]" {
$result = ExecuteWebCommand -command $commandNoContentType
# Validate response
$result . Output . url | Should -Match $uri
if ( $method -eq "POST" )
{
$result . Output . headers . 'Content-Type' | Should -Match "application/x-www-form-urlencoded"
# Validate that the response Content.form field is the same as what we sent.
[ string ] $result . Output . form | Should -Be ([ string][PSCustomObject ] @ { $body . Split ( "=" )[ 0 ] = [ System.Object[] ]})
$result . Output . data | Should -BeNullOrEmpty
}
else
{
# Validate that the response Content.data field is the same as what we sent.
$result . Output . data | Should -Be $body
}
}
2016-07-22 15:09:03 -07:00
}
}
It "Validate Invoke-RestMethod -Headers --> Set KeepAlive to false via headers" {
2017-09-07 22:53:04 -05:00
$uri = Get-WebListenerUrl -Test 'Get'
2016-07-22 15:09:03 -07:00
$result = ExecuteRequestWithHeaders -cmdletName Invoke-RestMethod -uri $uri
# Validate response
2018-03-01 23:00:00 -06:00
$result . Output . url | Should -Match $uri
$result . Output . Headers . Connection | Should -Be "Close"
2016-07-22 15:09:03 -07:00
}
# Validate all available user agents for Invoke-RestMethod
2018-01-09 15:43:25 -06:00
$agents = @ {
InternetExplorer = "MSIE 9.0"
Chrome = "Chrome"
Opera = "Opera"
Safari = "Safari"
FireFox = "Firefox"
}
2016-07-22 15:09:03 -07:00
2018-01-09 15:43:25 -06:00
foreach ( $agentName in $agents . Keys ) {
2016-07-22 15:09:03 -07:00
$expectedAgent = $agents [ $agentName ]
2017-09-07 22:53:04 -05:00
$uri = Get-WebListenerUrl -Test 'Get'
2016-07-22 15:09:03 -07:00
$userAgent = "[Microsoft.PowerShell.Commands.PSUserAgent]:: $agentName "
2018-02-02 13:56:06 -06:00
$command = "Invoke-RestMethod -Uri $uri -UserAgent ( $userAgent ) "
2016-07-22 15:09:03 -07:00
It "Validate Invoke-RestMethod UserAgent. Execute--> $command " {
$result = ExecuteWebCommand -command $command
# Validate response
2018-03-01 23:00:00 -06:00
$result . Output . headers . Host | Should -Be $uri . Authority
$result . Output . headers . 'User-Agent' | Should -Match $expectedAgent
2016-07-22 15:09:03 -07:00
}
}
It "Validate Invoke-RestMethod -OutFile" {
2017-09-07 22:53:04 -05:00
$uri = Get-WebListenerUrl -Test 'Get'
2016-07-22 15:09:03 -07:00
$result = ExecuteRequestWithOutFile -cmdletName "Invoke-RestMethod" -uri $uri
$jsonContent = $result . Output | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$jsonContent . headers . Host | Should -Be $uri . Authority
2016-07-22 15:09:03 -07:00
}
2016-11-03 22:29:17 +01:00
2023-03-21 09:06:50 +01:00
It "Invoke-RestMethod -OutFile folder Downloads the file and names it" {
$uri = Get-WebListenerUrl -Test 'Get'
$content = Invoke-WebRequest -Uri $uri
$outFile = Join-Path $TestDrive $content . BaseResponse . RequestMessage . RequestUri . Segments [ -1 ]
# ensure the file does not exist
Remove-Item -Force -ErrorAction Ignore -Path $outFile
Invoke-RestMethod -Uri $uri -OutFile $TestDrive
Test-Path $outFile | Should -Be $true
Get-Item $outFile | Select-Object -ExpandProperty Length | Should -Be $content . Content . Length
}
2024-08-05 14:23:47 -05:00
It "Invoke-RestMethod -PassThru -OutFile Downloads the file and pipes it" {
$uri = Get-WebListenerUrl -Test 'Get'
$content = Invoke-WebRequest -Uri $uri
$outFile = Join-Path $TestDrive $content . BaseResponse . RequestMessage . RequestUri . Segments [ -1 ]
# ensure the file does not exist
Remove-Item -Force -ErrorAction Ignore -Path $outFile
$response = Invoke-RestMethod -Uri $uri -PassThru -OutFile $outFile
# check if the file is downloaded.
Test-Path $outFile | Should -Be $true
# check if the file is correctly downloaded
Get-Content -Path $outFile | Should -BeExactly $content . Content
# check if the response stores the downloaded file contents
# response is a PSCustomObject so converted it string for comparison
$responseAsJsonString = $response | ConvertTo-Json -Compress
$responseAsJsonString | Should -BeExactly $content . Content
}
2023-02-01 17:45:09 +01:00
It "Invoke-RestMethod should fail if -OutFile is <Name>." -TestCases @ (
@ { Name = "empty" ; Value = [ string ]:: Empty }
@ { Name = "null" ; Value = $null }
) {
param ( $value )
$uri = Get-WebListenerUrl -Test 'Get'
$errorId = "ParameterArgumentValidationError,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
{ Invoke-RestMethod -Uri $uri -OutFile $value } | Should -Throw -ErrorId $errorId
}
2016-11-15 08:35:07 +11:00
It "Validate Invoke-RestMethod handles missing Content-Type in response header" {
#Validate that exception is not thrown when response headers are missing Content-Type.
2017-10-18 14:24:02 -05:00
$uri = Get-WebListenerUrl -Test 'ResponseHeaders' -Query @ { 'Content-Type' = '' }
$command = "Invoke-RestMethod -Uri ' $uri '"
2016-11-15 08:35:07 +11:00
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
$result . Error | Should -BeNullOrEmpty
2016-11-15 08:35:07 +11:00
}
2016-12-15 11:06:26 +03:00
2017-03-06 19:41:14 +00:00
It "Validate Invoke-RestMethod StandardMethod and CustomMethod parameter sets" {
2017-12-18 22:29:46 -06:00
$uri = Get-WebListenerUrl -Test 'Get'
2017-03-06 19:41:14 +00:00
$errorId = "AmbiguousParameterSet,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
2018-05-17 14:42:04 -07:00
{ Invoke-RestMethod -Uri $uri -Method GET -CustomMethod TEST } | Should -Throw -ErrorId $errorId
2017-03-06 19:41:14 +00:00
}
It "Validate CustomMethod method is used" {
2017-12-18 22:29:46 -06:00
$uri = Get-WebListenerUrl -Test 'Get'
$command = "Invoke-RestMethod -Uri ' $uri ' -CustomMethod TEST"
2017-03-06 19:41:14 +00:00
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
$result . Error | Should -BeNullOrEmpty
$result . Output . method | Should -Be "TEST"
2017-03-06 19:41:14 +00:00
}
2024-02-26 11:51:12 -08:00
It "Validate Invoke-RestMethod default ContentType for CustomMethod POST" {
$uri = Get-WebListenerUrl -Test 'Post'
$command = "Invoke-RestMethod -Uri ' $uri ' -CustomMethod POST -Body 'testparam=testvalue'"
2017-03-06 19:41:14 +00:00
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
$result . Output . form . testparam | Should -Be "testvalue"
$result . Output . Headers . 'Content-Type' | Should -Be "application/x-www-form-urlencoded"
2017-03-06 19:41:14 +00:00
}
It "Validate Invoke-RestMethod body is converted to query params for CustomMethod GET" {
2017-09-07 22:53:04 -05:00
$uri = Get-WebListenerUrl -Test 'Get'
$command = "Invoke-RestMethod -Uri ' $uri ' -CustomMethod GET -Body @{'testparam'='testvalue'}"
2017-03-06 19:41:14 +00:00
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
$result . Output . args . testparam | Should -Be "testvalue"
2017-03-06 19:41:14 +00:00
}
2022-01-03 11:20:33 -08:00
It 'Validate Invoke-RestMethod empty body CustomMethod GET' {
$uri = Get-WebListenerUrl -Test 'Get'
$command = "Invoke-RestMethod -Uri ' $uri ' -CustomMethod GET"
$result = ExecuteWebCommand -command $command
$result . Output . Headers . 'Content-Length' | Should -BeNullOrEmpty
}
2021-02-04 19:06:04 -08:00
It "Validate Invoke-RestMethod body is converted to query params for CustomMethod GET and -NoProxy" {
$uri = Get-WebListenerUrl -Test 'Get'
$command = "Invoke-RestMethod -Uri ' $uri ' -CustomMethod GET -Body @{'testparam'='testvalue'} -NoProxy"
$result = ExecuteWebCommand -command $command
$result . Output . Query | Should -Be "?testparam=testvalue"
}
2017-02-24 22:29:11 -08:00
It "Validate Invoke-RestMethod returns HTTP errors in exception" {
2017-12-13 09:28:05 -06:00
$query = @ {
2018-01-09 15:43:25 -06:00
body = "I am a teapot!!!"
statuscode = 418
2017-12-13 09:28:05 -06:00
responsephrase = "I am a teapot"
}
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2017-12-13 09:28:05 -06:00
$command = "Invoke-RestMethod -Uri ' $uri '"
2017-02-24 22:29:11 -08:00
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
$result . Error . ErrorDetails . Message | Should -Be $query . body
2020-01-24 19:00:37 +00:00
$result . Error . Exception | Should -BeOfType Microsoft . PowerShell . Commands . HttpResponseException
2018-03-01 23:00:00 -06:00
$result . Error . Exception . Response . StatusCode | Should -Be 418
$result . Error . Exception . Response . ReasonPhrase | Should -Be $query . responsephrase
$result . Error . Exception . Message | Should -Match ": 418 \( $( $query . responsephrase ) \)\."
$result . Error . FullyQualifiedErrorId | Should -Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
2017-02-24 22:29:11 -08:00
}
2017-03-16 17:59:15 -07:00
2017-05-24 15:54:02 -07:00
It "Validate Invoke-RestMethod -FollowRelLink doesn't fail if no Link Header is present" {
2017-12-04 11:52:14 -06:00
$query = @ {
contenttype = 'application/json'
2018-01-09 15:43:25 -06:00
body = '"foo"'
2017-12-04 11:52:14 -06:00
}
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2017-12-04 11:52:14 -06:00
$command = "Invoke-RestMethod -Uri ' $uri ' -FollowRelLink"
2017-05-24 15:54:02 -07:00
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
$result . Output | Should -BeExactly "foo"
2017-05-24 15:54:02 -07:00
}
2023-02-10 17:50:01 +01:00
It "Validate Invoke-RestMethod -FollowRelLink correctly follows all the available relation links <name>" -TestCases @ (
2017-05-24 15:54:02 -07:00
$maxLinks = 5
2023-02-10 17:50:01 +01:00
$originalUri = Get-WebListenerUrl -Test 'Link' -Query @ { maxlinks = $maxLinks }
@ { name = '(URI with scheme)' ; uri = $originalUri }
@ { name = '(URI without scheme)' ; uri = $originalUri . OriginalString . Split ( "//" )[ 1 ]}
) {
param ( $uri )
2018-01-16 11:23:22 -06:00
$command = "Invoke-RestMethod -Uri ' $uri ' -FollowRelLink"
2017-05-24 15:54:02 -07:00
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
$result . Output . Count | Should -BeExactly $maxLinks
1 .. $maxLinks | ForEach-Object { $result . Output [ $_ - 1 ]. linknumber | Should -BeExactly $_ }
2017-05-24 15:54:02 -07:00
}
It "Validate Invoke-RestMethod -FollowRelLink correctly limits to -MaximumRelLink" {
$maxLinks = 10
$maxLinksToFollow = 6
2018-01-16 11:23:22 -06:00
$uri = Get-WebListenerUrl -Test 'Link' -Query @ { maxlinks = $maxLinks }
$command = "Invoke-RestMethod -Uri ' $uri ' -FollowRelLink -MaximumFollowRelLink $maxLinksToFollow "
2017-05-24 15:54:02 -07:00
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
$result . Output . Count | Should -BeExactly $maxLinksToFollow
1 .. $maxLinksToFollow | ForEach-Object { $result . Output [ $_ - 1 ]. linknumber | Should -BeExactly $_ }
2017-05-24 15:54:02 -07:00
}
2026-08-20 16:57:20 -04:00
It "Validate Invoke-RestMethod -FollowRelLink strips the authorization header on followed relation links by default" {
$uri = Get-WebListenerUrl -Test 'Link' -Query @ { maxlinks = 3 }
$command = "Invoke-RestMethod -Uri ' $uri ' -FollowRelLink -Headers @{Authorization = 'test'}"
$result = ExecuteWebCommand -command $command
$result . Error | Should -BeNullOrEmpty
$result . Output . Count | Should -BeExactly 3
$result . Output [ 0 ]. headers . Authorization | Should -BeExactly 'test'
$result . Output [ 1 ]. headers . Authorization | Should -BeNullOrEmpty
$result . Output [ 2 ]. headers . Authorization | Should -BeNullOrEmpty
}
2017-07-07 09:25:46 -07:00
It "Validate Invoke-RestMethod quietly ignores invalid Link Headers if -FollowRelLink is specified: <type>" -TestCases @ (
2017-05-24 15:54:02 -07:00
@ { type = "noUrl" }
@ { type = "malformed" }
2017-07-07 09:25:46 -07:00
@ { type = "noRel" }
2017-05-24 15:54:02 -07:00
) {
param ( $type )
2018-01-16 11:23:22 -06:00
$uri = Get-WebListenerUrl -Test 'Link' -Query @ { type = $type }
$command = "Invoke-RestMethod -Uri ' $uri ' -FollowRelLink"
2017-05-24 15:54:02 -07:00
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
$result . Output . linknumber | Should -BeExactly 1
2017-05-24 15:54:02 -07:00
}
2018-07-23 22:56:00 -07:00
It "Validate Invoke-RestMethod handles whitespace for Link Headers if -FollowRelLink is specified: <type>" -TestCases @ (
@ { type = "noWhitespace" }
@ { type = "extraWhitespace" }
) {
param ( $type )
$uri = Get-WebListenerUrl -Test 'Link' -Query @ { type = $type }
$command = "Invoke-RestMethod -Uri ' $uri ' -FollowRelLink"
$result = ExecuteWebCommand -command $command
1 . .3 | ForEach-Object { $result . Output [ $_ - 1 ]. linknumber | Should -BeExactly $_ }
}
2023-01-11 17:39:04 +01:00
It "Validate Invoke-RestMethod -FollowRelLink correctly manages commas" {
$maxLinks = 5
$uri = Get-WebListenerUrl -Test 'Link' -Query @ { maxlinks = $maxLinks ; type = "with,comma" }
$command = "Invoke-RestMethod -Uri ' $uri ' -FollowRelLink"
$result = ExecuteWebCommand -command $command
$result . Output . Count | Should -BeExactly $maxLinks
1 .. $maxLinks | ForEach-Object { $result . Output [ $_ - 1 ]. linknumber | Should -BeExactly $_ }
}
2019-11-07 12:38:24 -08:00
It "Verify Invoke-RestMethod supresses terminating errors with -SkipHttpErrorCheck" {
$uri = Get-WebListenerUrl -Test 'Response' -Query $NotFoundQuery
$command = "Invoke-RestMethod -SkipHttpErrorCheck -Uri ' $uri '"
$result = ExecuteWebCommand -Command $command
$result . output . message | Should -BeExactly "oops"
$result . output . error | Should -BeNullOrEmpty
}
It "Verify Invoke-RestMethod terminates without -SkipHttpErrorCheck" {
$uri = Get-WebListenerUrl -Test 'Response' -Query $NotFoundQuery
$command = "Invoke-RestMethod -Uri ' $uri '"
$result = ExecuteWebCommand -Command $command
$result . output | Should -BeNullOrEmpty
$result . error | Should -Not -BeNullOrEmpty
}
It "Verify Invoke-RestMethod assigns 200 status code with -StatusCodeVariable" {
$query = @ {
statuscode = 200
responsephrase = 'OK'
contenttype = 'application/json'
body = '{"message": "works"}'
headers = "{}"
}
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
Invoke-RestMethod -StatusCodeVariable code -Uri " $uri "
$code | Should -Be 200
}
It "Verify Invoke-RestMethod assigns 404 status code with -StatusCodeVariable" {
$query = @ {
statuscode = 404
responsephrase = 'Not Found'
contenttype = 'application/json'
body = '{"message": "oops"}'
headers = "{}"
}
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
Invoke-RestMethod -SkipHttpErrorCheck -StatusCodeVariable code -Uri " $uri "
$code | Should -Be 404
}
It "Verify Invoke-RestMethod assigns 500 status code with -StatusCodeVariable" {
$query = @ {
statuscode = 500
responsephrase = 'Internal Server Error'
contenttype = 'application/json'
body = '{"message": "oops"}'
headers = "{}"
}
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
Invoke-RestMethod -SkipHttpErrorCheck -StatusCodeVariable code -Uri " $uri "
$code | Should -Be 500
}
2017-06-15 15:52:08 -07:00
#region Redirect tests
2018-05-14 13:37:30 -05:00
It "Validates Invoke-RestMethod with -PreserveAuthorizationOnRedirect preserves the authorization header on redirect: <redirectType> <redirectedMethod>" -TestCases $redirectTests {
2017-06-15 15:52:08 -07:00
param ( $redirectType , $redirectedMethod )
2018-01-13 01:51:04 -06:00
$uri = Get-WebListenerUrl -Test 'Redirect' -Query @ { type = $redirectType }
$response = ExecuteRedirectRequest -Cmdlet 'Invoke-RestMethod' -Uri $uri -PreserveAuthorizationOnRedirect
2017-07-07 09:25:46 -07:00
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
2017-06-15 15:52:08 -07:00
# ensure Authorization header has been preserved.
2018-03-01 23:00:00 -06:00
$response . Content . Headers . "Authorization" | Should -BeExactly "test"
2017-06-15 15:52:08 -07:00
}
2018-05-14 13:37:30 -05:00
It "Validates Invoke-RestMethod preserves the authorization header on multiple redirects: <redirectType>" -TestCases $redirectTests {
2017-06-15 15:52:08 -07:00
param ( $redirectType )
2018-01-13 01:51:04 -06:00
$uri = Get-WebListenerUrl -Test 'Redirect' -TestValue 3 -Query @ { type = $redirectType }
$response = ExecuteRedirectRequest -Cmdlet 'Invoke-RestMethod' -Uri $uri -PreserveAuthorizationOnRedirect
2017-06-15 15:52:08 -07:00
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
2017-06-15 15:52:08 -07:00
# ensure Authorization header was stripped
2018-03-01 23:00:00 -06:00
$response . Content . Headers . "Authorization" | Should -BeExactly "test"
2017-06-15 15:52:08 -07:00
}
2023-03-01 20:04:20 +01:00
It "Validates Invoke-RestMethod with -WebSession and -PreserveAuthorizationOnRedirect doesn't change session variable on multiple redirects: <redirectType>" -TestCases $redirectTests {
param ( $redirectType )
#[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Demo/doc/test secret.")]
$token = "testpassword" | ConvertTo-SecureString -AsPlainText -Force
$credential = [ pscredential ]:: new ( "testuser" , $token )
$certificate = Get-WebListenerClientCertificate
$headers = @ { "Authorization" = "test" }
$proxy = ( Get-WebListenerUrl ). Authority
$uri = Get-WebListenerUrl -Test 'Redirect' -TestValue 2 -Query @ { type = $redirectType }
$session = [ Microsoft.PowerShell.Commands.WebRequestSession ]:: new ()
$session . MaximumRedirection = 2
$session . MaximumRetryCount = 2
$session . RetryIntervalInSeconds = 2
$session . UseDefaultCredentials = $true
$null = Invoke-RestMethod -Uri $uri -PreserveAuthorizationOnRedirect -WebSession $session -AllowUnencryptedAuthentication -Headers $headers
$session . MaximumRedirection | Should -BeExactly 2
$session . MaximumRetryCount | Should -BeExactly 2
$session . RetryIntervalInSeconds | Should -BeExactly 2
$session . UseDefaultCredentials | Should -BeExactly $true
$session = [ Microsoft.PowerShell.Commands.WebRequestSession ]:: new ()
$session . Credentials = $credential
$session . Certificates = [ System.Security.Cryptography.X509Certificates.X509CertificateCollection ]:: new ([ X509Certificate ] $certificate )
$null = Invoke-RestMethod -Uri $uri -PreserveAuthorizationOnRedirect -WebSession $session -SkipCertificateCheck -Headers $headers
$session . Credentials . UserName | Should -BeExactly $credential . UserName
$session . Credentials . Password | Should -BeExactly $credential . GetNetworkCredential (). Password
$session . Certificates . Thumbprint | Should -BeExactly $certificate . Thumbprint
$session = [ Microsoft.PowerShell.Commands.WebRequestSession ]:: new ()
$session . Proxy = [ System.Net.WebProxy ]:: new ( $proxy )
$null = Invoke-RestMethod -Uri $uri -PreserveAuthorizationOnRedirect -WebSession $session -Headers $headers
$session . Proxy . GetProxy ( $uri ). Authority | Should -BeExactly $proxy
}
2018-05-14 13:37:30 -05:00
It "Validates Invoke-RestMethod strips the authorization header on various redirects: <redirectType>" -TestCases $redirectTests {
2017-06-15 15:52:08 -07:00
param ( $redirectType )
2018-01-13 01:51:04 -06:00
$uri = Get-WebListenerUrl -Test 'Redirect' -Query @ { type = $redirectType }
$response = ExecuteRedirectRequest -Cmdlet 'Invoke-RestMethod' -Uri $uri
2017-06-15 15:52:08 -07:00
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
2017-06-15 15:52:08 -07:00
# ensure user-agent is present (i.e., no false positives )
2018-03-01 23:00:00 -06:00
$response . Content . Headers . "User-Agent" | Should -Not -BeNullOrEmpty
2017-06-15 15:52:08 -07:00
# ensure Authorization header has been removed.
2018-03-01 23:00:00 -06:00
$response . Content . Headers . "Authorization" | Should -BeNullOrEmpty
2017-06-15 15:52:08 -07:00
}
# NOTE: Only testing redirection of POST -> GET for unique underlying values of HttpStatusCode.
# Some names overlap in underlying value.
2018-05-14 13:37:30 -05:00
It "Validates Invoke-RestMethod strips the authorization header redirects and switches from POST to GET when it handles the redirect: <redirectType> <redirectedMethod>" -TestCases $redirectTests {
2017-06-15 15:52:08 -07:00
param ( $redirectType , $redirectedMethod )
2018-01-13 01:51:04 -06:00
$uri = Get-WebListenerUrl -Test 'Redirect' -Query @ { type = $redirectType }
$response = ExecuteRedirectRequest -Cmdlet 'Invoke-RestMethod' -Uri $uri -Method 'POST'
2017-07-07 09:25:46 -07:00
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
2017-06-15 15:52:08 -07:00
# ensure user-agent is present (i.e., no false positives )
2018-03-01 23:00:00 -06:00
$response . Content . Headers . "User-Agent" | Should -Not -BeNullOrEmpty
2017-06-15 15:52:08 -07:00
# ensure Authorization header has been removed.
2018-05-14 13:37:30 -05:00
$response . Content . Headers . "Authorization" | Should -BeNullOrEmpty
# ensure POST was changed to GET for selected redirections and remains as POST for others.
$response . Content . Method | Should -Be $redirectedMethod
}
It "Validates Invoke-RestMethod -PreserveAuthorizationOnRedirect keeps the authorization header redirects and switches from POST to GET when it handles the redirect: <redirectType> <redirectedMethod>" -TestCases $redirectTests {
param ( $redirectType , $redirectedMethod )
$uri = Get-WebListenerUrl -Test 'Redirect' -Query @ { type = $redirectType }
$response = ExecuteRedirectRequest -PreserveAuthorizationOnRedirect -Cmdlet 'Invoke-RestMethod' -Uri $uri -Method 'POST'
$response . Error | Should -BeNullOrEmpty
# ensure user-agent is present (i.e., no false positives )
$response . Content . Headers . "User-Agent" | Should -Not -BeNullOrEmpty
2023-02-10 12:14:29 +01:00
# ensure Authorization header has been preserved.
$response . Content . Headers . "Authorization" | Should -BeExactly 'test'
# ensure POST was changed to GET for selected redirections and remains as POST for others.
$response . Content . Method | Should -Be $redirectedMethod
}
It "Validates Invoke-RestMethod -PreserveAuthorizationOnRedirect -CustomMethod POST keeps the authorization header redirects and switches from POST to GET when it handles the redirect: <redirectType> <redirectedMethod>" -TestCases $redirectTests {
param ( $redirectType , $redirectedMethod )
$uri = Get-WebListenerUrl -Test 'Redirect' -Query @ { type = $redirectType }
$response = ExecuteRedirectRequest -PreserveAuthorizationOnRedirect -Cmdlet 'Invoke-RestMethod' -Uri $uri -CustomMethod 'POST'
$response . Error | Should -BeNullOrEmpty
# ensure user-agent is present (i.e., no false positives )
$response . Content . Headers . "User-Agent" | Should -Not -BeNullOrEmpty
# ensure Authorization header has been preserved.
2018-05-14 13:37:30 -05:00
$response . Content . Headers . "Authorization" | Should -BeExactly 'test'
2017-06-15 15:52:08 -07:00
# ensure POST was changed to GET for selected redirections and remains as POST for others.
2018-03-01 23:00:00 -06:00
$response . Content . Method | Should -Be $redirectedMethod
2017-07-07 09:25:46 -07:00
}
2017-06-15 15:52:08 -07:00
2026-08-20 16:57:20 -04:00
It "Validates Invoke-RestMethod -PreserveHttpMethodOnRedirect strips the authorization header and remains POST when it handles the redirect: <redirectType>" -TestCases $redirectTests {
2023-02-14 17:40:42 +01:00
param ( $redirectType )
$uri = Get-WebListenerUrl -Test 'Redirect' -Query @ { type = $redirectType }
$response = ExecuteRedirectRequest -PreserveHttpMethodOnRedirect -Cmdlet 'Invoke-RestMethod' -Uri $uri -Method 'POST'
$response . Error | Should -BeNullOrEmpty
# ensure user-agent is present (i.e., no false positives )
$response . Content . Headers . "User-Agent" | Should -Not -BeNullOrEmpty
2026-08-20 16:57:20 -04:00
# ensure Authorization header has been removed.
$response . Content . Headers . "Authorization" | Should -BeNullOrEmpty
# ensure POST doesn't change.
$response . Content . Method | Should -Be 'POST'
}
It "Validates Invoke-RestMethod -PreserveHttpMethodOnRedirect -PreserveAuthorizationOnRedirect keeps the authorization header and remains POST when it handles the redirect: <redirectType>" -TestCases $redirectTests {
param ( $redirectType )
$uri = Get-WebListenerUrl -Test 'Redirect' -Query @ { type = $redirectType }
$response = ExecuteRedirectRequest -PreserveAuthorizationOnRedirect -PreserveHttpMethodOnRedirect -Cmdlet 'Invoke-RestMethod' -Uri $uri -Method 'POST'
$response . Error | Should -BeNullOrEmpty
# ensure user-agent is present (i.e., no false positives )
$response . Content . Headers . "User-Agent" | Should -Not -BeNullOrEmpty
# ensure Authorization header has been preserved.
2023-02-14 17:40:42 +01:00
$response . Content . Headers . "Authorization" | Should -BeExactly 'test'
# ensure POST doesn't change.
$response . Content . Method | Should -Be 'POST'
}
2018-04-08 14:51:17 +02:00
It "Validates Invoke-RestMethod handles responses without Location header for requests with Authorization header and redirect: <redirectType>" -TestCases $redirectTests {
param ( $redirectType , $redirectedMethod )
# Skip relative test as it is not a valid response type.
if ( $redirectType -eq 'relative' ) { return }
# When an Authorization request header is present,
# and -PreserveAuthorizationOnRedirect is not present,
# PowerShell should throw an HTTP Response Exception
# for a redirect response which does not contain a Location response header.
# The correct redirect status code should be included in the exception.
$StatusCode = [ int][System.Net.HttpStatusCode ] $redirectType
$uri = Get-WebListenerUrl -Test Response -Query @ { statuscode = $StatusCode }
$command = "Invoke-RestMethod -Uri ' $uri ' -Headers @{Authorization = 'foo'}"
$response = ExecuteWebCommand -command $command
2020-01-24 19:00:37 +00:00
$response . Error . Exception | Should -BeOfType Microsoft . PowerShell . Commands . HttpResponseException
2018-04-08 14:51:17 +02:00
$response . Error . Exception . Response . StatusCode | Should -Be $StatusCode
$response . Error . Exception . Response . Headers . Location | Should -BeNullOrEmpty
}
2023-01-13 13:37:55 +01:00
It "Validate Invoke-RestMethod Https to Http redirect with -AllowInsecureRedirect" {
$httpUri = Get-WebListenerUrl -Test 'Get'
$uri = Get-WebListenerUrl -Test 'Redirect' -Https -Query @ { destination = $httpUri }
$command = "Invoke-RestMethod -Uri ' $uri ' -SkipCertificateCheck -AllowInsecureRedirect"
$result = ExecuteWebCommand -command $command
$result . Output . Headers . Host | Should -Be $httpUri . Authority
}
It "Validate Invoke-RestMethod Https to Http redirect without -AllowInsecureRedirect" {
$httpUri = Get-WebListenerUrl -Test 'Get'
$uri = Get-WebListenerUrl -Test 'Redirect' -Https -Query @ { destination = $httpUri }
$command = "Invoke-RestMethod -Uri ' $uri ' -SkipCertificateCheck"
$result = ExecuteWebCommand -command $command
2023-02-14 04:32:48 +01:00
$result . Error . FullyQualifiedErrorId | Should -Be "InsecureRedirection,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
2023-01-13 13:37:55 +01:00
}
2023-04-12 02:56:24 +02:00
It "Validate Invoke-RestMethod Https to Http (No Scheme) redirect without -AllowInsecureRedirect" {
$httpUri = Get-WebListenerUrl -Test 'Get'
$uri = Get-WebListenerUrl -Test 'Redirect' -Https -Query @ { destination = $httpUri . Authority }
$command = "Invoke-RestMethod -Uri ' $uri ' -SkipCertificateCheck"
$result = ExecuteWebCommand -command $command
$result . Error . FullyQualifiedErrorId | Should -Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
}
2017-07-07 09:25:46 -07:00
#endregion Redirect tests
2017-06-15 15:52:08 -07:00
2018-02-22 13:15:05 -06:00
Context "Invoke-RestMethod SkipHeaderVerification Tests" {
BeforeAll {
$Testfile = Join-Path $testdrive 'SkipHeaderVerification.txt'
'bar' | Set-Content $Testfile
}
2017-07-14 10:24:20 -07:00
2018-02-22 13:15:05 -06:00
It "Verifies Invoke-RestMethod default header handling with no errors" {
$uri = Get-WebListenerUrl -Test 'Get'
$headers = @ { "If-Match" = "*" }
$response = ExecuteRequestWithCustomHeaders -Uri $uri -headers $headers -Cmdlet "Invoke-RestMethod"
2017-07-14 10:24:20 -07:00
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
$response . Content . Headers . "If-Match" | Should -BeExactly "*"
2018-02-22 13:15:05 -06:00
}
It "Verifies Invoke-RestMethod default header handling reports an error is returned for an invalid If-Match header value" {
$uri = Get-WebListenerUrl -Test 'Get'
$headers = @ { "If-Match" = "12345" }
$response = ExecuteRequestWithCustomHeaders -Uri $uri -headers $headers -Cmdlet "Invoke-RestMethod"
2018-03-01 23:00:00 -06:00
$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."
2018-02-22 13:15:05 -06:00
}
It "Verifies Invoke-RestMethod header handling does not report an error when using -SkipHeaderValidation" {
$uri = Get-WebListenerUrl -Test 'Get'
$headers = @ { "If-Match" = "12345" }
$response = ExecuteRequestWithCustomHeaders -Uri $uri -headers $headers -SkipHeaderValidation -Cmdlet "Invoke-RestMethod"
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
$response . Content . Headers . "If-Match" | Should -BeExactly "12345"
2018-02-22 13:15:05 -06:00
}
It "Verifies Invoke-RestMethod default UserAgent handling with no errors" {
$uri = Get-WebListenerUrl -Test 'Get'
$UserAgent = [ Microsoft.PowerShell.Commands.PSUserAgent ]:: InternetExplorer
$response = ExecuteRequestWithCustomUserAgent -Uri $uri -UserAgent $UserAgent -Cmdlet "Invoke-RestMethod"
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
2018-02-22 13:15:05 -06:00
$Pattern = [ regex ]:: Escape ( $UserAgent )
2018-03-01 23:00:00 -06:00
$response . Content . Headers . "User-Agent" | Should -Match $Pattern
2018-02-22 13:15:05 -06:00
}
It "Verifies Invoke-RestMethod default UserAgent handling reports an error is returned for an invalid UserAgent value" {
$uri = Get-WebListenerUrl -Test 'Get'
$UserAgent = 'Invalid:Agent'
$response = ExecuteRequestWithCustomUserAgent -Uri $uri -UserAgent $UserAgent -Cmdlet "Invoke-RestMethod"
2018-03-01 23:00:00 -06:00
$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."
2018-02-22 13:15:05 -06:00
}
It "Verifies Invoke-RestMethod UserAgent handling does not report an error when using -SkipHeaderValidation" {
$uri = Get-WebListenerUrl -Test 'Get'
$UserAgent = 'Invalid:Agent'
$response = ExecuteRequestWithCustomUserAgent -Uri $uri -UserAgent $UserAgent -SkipHeaderValidation -Cmdlet "Invoke-RestMethod"
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
2018-02-22 13:15:05 -06:00
$Pattern = [ regex ]:: Escape ( $UserAgent )
2018-03-01 23:00:00 -06:00
$response . Content . Headers . "User-Agent" | Should -Match $Pattern
2018-02-22 13:15:05 -06:00
}
It "Verifies Invoke-RestMethod default ContentType handling reports no error is returned for a valid Content-Type header value and -Body" {
$contentType = 'text/plain'
$body = "bar"
$uri = Get-WebListenerUrl -Test 'Post'
$result = Invoke-RestMethod -Uri $uri -Method 'Post' -ContentType $contentType -Body $body
2018-03-01 23:00:00 -06:00
$result . data | Should -BeExactly $body
$result . headers . 'Content-Type' | Should -BeExactly $contentType
2018-02-22 13:15:05 -06:00
}
It "Verifies Invoke-RestMethod default ContentType handling reports an error is returned for an invalid Content-Type header value and -Body" {
$contentType = 'foo'
$body = "bar"
$uri = Get-WebListenerUrl -Test 'Post'
{ Invoke-RestMethod -Uri $uri -Method 'Post' -ContentType $contentType -Body $body -ErrorAction 'Stop' } |
2018-05-17 14:42:04 -07:00
Should -Throw -ErrorId "WebCmdletContentTypeException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
2018-02-22 13:15:05 -06:00
}
It "Verifies Invoke-RestMethod ContentType handling reports no error is returned for an invalid Content-Type header value, -Body, and -SkipHeaderValidation" {
$contentType = 'foo'
$body = "bar"
$uri = Get-WebListenerUrl -Test 'Post'
$result = Invoke-RestMethod -Uri $uri -Method 'Post' -ContentType $contentType -Body $body -SkipHeaderValidation
2018-03-01 23:00:00 -06:00
$result . data | Should -BeExactly $body
$result . headers . 'Content-Type' | Should -BeExactly $contentType
2018-02-22 13:15:05 -06:00
}
It "Verifies Invoke-RestMethod default ContentType handling reports no error is returned for a valid Content-Type header value and -InFile" {
$contentType = 'text/plain'
$uri = Get-WebListenerUrl -Test 'Post'
$result = Invoke-RestMethod -Uri $uri -Method 'Post' -ContentType $contentType -InFile $Testfile
# Match used due to inconsistent newline rendering
2018-03-01 23:00:00 -06:00
$result . data | Should -Match 'bar'
$result . headers . 'Content-Type' | Should -BeExactly $contentType
2018-02-22 13:15:05 -06:00
}
It "Verifies Invoke-RestMethod default ContentType handling reports an error is returned for an invalid Content-Type header value and -InFile" {
$contentType = 'foo'
$uri = Get-WebListenerUrl -Test 'Post'
{ Invoke-RestMethod -Uri $uri -Method 'Post' -ContentType $contentType -InFile $Testfile -ErrorAction 'Stop' } |
2018-05-17 14:42:04 -07:00
Should -Throw -ErrorId "WebCmdletContentTypeException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
2018-02-22 13:15:05 -06:00
}
It "Verifies Invoke-RestMethod default ContentType handling reports no error is returned for an invalid Content-Type header value, -Infile, and -SkipHeaderValidation" {
$contentType = 'foo'
$uri = Get-WebListenerUrl -Test 'Post'
$result = Invoke-RestMethod -Uri $uri -Method 'Post' -ContentType $contentType -InFile $Testfile -SkipHeaderValidation
# Match used due to inconsistent newline rendering
2018-03-01 23:00:00 -06:00
$result . data | Should -Match 'bar'
$result . headers . 'Content-Type' | Should -BeExactly $contentType
2018-02-22 13:15:05 -06:00
}
2019-07-02 12:01:06 -07:00
It "Verifies Invoke-RestMethod applies -ContentType when no -Body is present" {
$contentType = 'application/json'
$uri = Get-WebListenerUrl -Test 'Get'
$result = Invoke-RestMethod -Uri $uri -Method 'GET' -ContentType $contentType
$result . data | Should -BeNullOrEmpty
$result . headers . 'Content-Type' | Should -BeExactly $contentType
}
It "Verifies Invoke-RestMethod applies an invalid -ContentType when no -Body is present and -SkipHeaderValidation is present" {
$contentType = 'foo'
$uri = Get-WebListenerUrl -Test 'Get'
$result = Invoke-RestMethod -Uri $uri -Method 'GET' -ContentType $contentType -SkipHeaderValidation
$result . data | Should -BeNullOrEmpty
$result . headers . 'Content-Type' | Should -BeExactly $contentType
}
2017-07-14 10:24:20 -07:00
}
2017-09-01 13:31:15 -05:00
Context "HTTPS Tests" {
It "Validate Invoke-RestMethod -SkipCertificateCheck" {
# HTTP method HEAD must be used to not retrieve an unparsable HTTP body
# validate that exception is thrown for URI with expired certificate
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Https
2017-09-01 13:31:15 -05:00
$command = "Invoke-RestMethod -Uri ' $uri ' -Method HEAD"
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
$result . Error . FullyQualifiedErrorId | Should -Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
2017-10-05 09:46:33 -07:00
2017-09-01 13:31:15 -05:00
# validate that no exception is thrown for URI with expired certificate when using -SkipCertificateCheck option
$command = "Invoke-RestMethod -Uri ' $uri ' -SkipCertificateCheck -Method HEAD"
$result = ExecuteWebCommand -command $command
2018-03-01 23:00:00 -06:00
$result . Error | Should -BeNullOrEmpty
2017-09-01 13:31:15 -05:00
}
2017-10-05 09:46:33 -07:00
2017-09-01 13:31:15 -05:00
It "Validate Invoke-RestMethod returns native HTTPS error message in exception" {
$uri = Get-WebListenerUrl -Https
$command = "Invoke-RestMethod -Uri ' $uri '"
$result = ExecuteWebCommand -command $command
2017-10-05 09:46:33 -07:00
2017-09-01 13:31:15 -05:00
# need to check against inner exception since Linux and Windows uses different HTTP client libraries so errors aren't the same
2018-03-01 23:00:00 -06:00
$result . Error . ErrorDetails . Message | Should -Match $result . Error . Exception . InnerException . Message
$result . Error . FullyQualifiedErrorId | Should -Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
2017-09-01 13:31:15 -05:00
}
2017-10-05 09:46:33 -07:00
2017-09-01 13:31:15 -05:00
It "Verifies Invoke-RestMethod Certificate Authentication Fails without -Certificate" {
$uri = Get-WebListenerUrl -Https -Test 'Cert'
$result = Invoke-RestMethod -Uri $uri -SkipCertificateCheck
2017-10-05 09:46:33 -07:00
2018-03-01 23:00:00 -06:00
$result . Status | Should -Be 'FAILED'
2017-09-01 13:31:15 -05:00
}
2017-10-05 09:46:33 -07:00
2018-05-09 06:35:52 -05:00
It "Verifies Invoke-RestMethod Certificate Authentication Successful with -Certificate" {
2017-09-01 13:31:15 -05:00
$uri = Get-WebListenerUrl -Https -Test 'Cert'
$certificate = Get-WebListenerClientCertificate
2020-05-07 13:00:30 +01:00
$result = Invoke-RestMethod -Uri $uri -Certificate $certificate -SkipCertificateCheck
2017-10-05 09:46:33 -07:00
2018-03-01 23:00:00 -06:00
$result . Status | Should -Be 'OK'
$result . Thumbprint | Should -Be $certificate . Thumbprint
2017-09-01 13:31:15 -05:00
}
2017-08-18 15:56:31 -05:00
}
2017-09-12 11:41:36 -05:00
Context "Multipart/form-data Tests" {
2018-01-24 23:17:55 -06:00
<#
Content-Type request headers for multipart/form-data appear as:
multipart/form-data; boundary="0ab0cb90-f01b-4c15-bd4d-53d073efcc1d"
MultipartFormDataContent sets a random GUID for the boundary before submitting the request
to the remote endpoint. Tests in this context for Content-Type match 'multipart/form-data'
as we do not have access to the random GUID.
#>
<#
Kestrel/ASP.NET inconsistently renders the new line for uploaded text files.
File content tests in this context use match as a workaround.
#>
BeforeAll {
$file1Name = "testfile1.txt"
$file1Path = Join-Path $testdrive $file1Name
$file1Contents = "Test123"
$file1Contents | Set-Content $file1Path -Force
$file2Name = "testfile2.txt"
$file2Path = Join-Path $testdrive $file2Name
$file2Contents = "Test456"
$file2Contents | Set-Content $file2Path -Force
2023-06-12 18:55:32 +02:00
$file3Name = "Kündigung_Mustermann_Max.TTA_2023_01_30.txt"
$file3Path = Join-Path $testdrive $file3Name
$file3Contents = "Test789"
$file3Contents | Set-Content $file3Path -Force
2018-01-24 23:17:55 -06:00
}
2017-09-12 11:41:36 -05:00
It "Verifies Invoke-RestMethod Supports Multipart String Values" {
$body = GetMultipartBody -String
$uri = Get-WebListenerUrl -Test 'Multipart'
$result = Invoke-RestMethod -Uri $uri -Body $body -Method 'POST'
2018-03-01 23:00:00 -06:00
$result . Headers . 'Content-Type' | Should -Match 'multipart/form-data'
$result . Items . TestString [ 0 ] | Should -Be 'TestValue'
2017-09-12 11:41:36 -05:00
}
2018-01-09 15:43:25 -06:00
2017-09-12 11:41:36 -05:00
It "Verifies Invoke-RestMethod Supports Multipart File Values" {
$body = GetMultipartBody -File
$uri = Get-WebListenerUrl -Test 'Multipart'
$result = Invoke-RestMethod -Uri $uri -Body $body -Method 'POST'
2018-03-01 23:00:00 -06:00
$result . Headers . 'Content-Type' | Should -Match 'multipart/form-data'
$result . Files [ 0 ]. FileName | Should -Be 'multipart.txt'
$result . Files [ 0 ]. ContentType | Should -Be 'text/plain'
$result . Files [ 0 ]. Content | Should -Match 'TestContent'
2017-09-12 11:41:36 -05:00
}
2018-01-09 15:43:25 -06:00
2017-09-12 11:41:36 -05:00
It "Verifies Invoke-RestMethod Supports Mixed Multipart String and File Values" {
$body = GetMultipartBody -String -File
$uri = Get-WebListenerUrl -Test 'Multipart'
$result = Invoke-RestMethod -Uri $uri -Body $body -Method 'POST'
2018-03-01 23:00:00 -06:00
$result . Headers . 'Content-Type' | Should -Match 'multipart/form-data'
$result . Items . TestString [ 0 ] | Should -Be 'TestValue'
$result . Files [ 0 ]. FileName | Should -Be 'multipart.txt'
$result . Files [ 0 ]. ContentType | Should -Be 'text/plain'
$result . Files [ 0 ]. Content | Should -Match 'TestContent'
2017-09-12 11:41:36 -05:00
}
2018-01-24 23:17:55 -06:00
It "Verifies Invoke-RestMethod -Form supports string values" {
$form = @ { TestString = "TestValue" }
$uri = Get-WebListenerUrl -Test 'Multipart'
$result = Invoke-RestMethod -Uri $uri -Form $form -Method 'POST'
2018-03-01 23:00:00 -06:00
$result . Headers . 'Content-Type' | Should -Match 'multipart/form-data'
$result . Items . TestString . Count | Should -Be 1
$result . Items . TestString [ 0 ] | Should -Be 'TestValue'
2018-01-24 23:17:55 -06:00
}
It "Verifies Invoke-RestMethod -Form supports a collection of string values" {
$form = @ { TestStrings = "TestValue" , "TestValue2" }
$uri = Get-WebListenerUrl -Test 'Multipart'
$result = Invoke-RestMethod -Uri $uri -Form $form -Method 'POST'
2018-03-01 23:00:00 -06:00
$result . Headers . 'Content-Type' | Should -Match 'multipart/form-data'
$result . Items . TestStrings . Count | Should -Be 2
$result . Items . TestStrings [ 0 ] | Should -Be 'TestValue'
$result . Items . TestStrings [ 1 ] | Should -Be 'TestValue2'
2018-01-24 23:17:55 -06:00
}
It "Verifies Invoke-RestMethod -Form supports file values" {
$form = @ { TestFile = [ System.IO.FileInfo ] $file1Path }
$uri = Get-WebListenerUrl -Test 'Multipart'
$result = Invoke-RestMethod -Uri $uri -Form $form -Method 'POST'
2018-03-01 23:00:00 -06:00
$result . Headers . 'Content-Type' | Should -Match 'multipart/form-data'
$result . Files . Count | Should -Be 1
2018-01-24 23:17:55 -06:00
2018-03-01 23:00:00 -06:00
$result . Files [ 0 ]. Name | Should -Be "TestFile"
$result . Files [ 0 ]. FileName | Should -Be $file1Name
$result . Files [ 0 ]. ContentType | Should -Be 'application/octet-stream'
$result . Files [ 0 ]. Content | Should -Match $file1Contents
2018-01-24 23:17:55 -06:00
}
2025-11-18 21:49:38 +09:00
It "Verifies Invoke-RestMethod -Form supports read-only file values" {
# Create a read-only test file
$readOnlyFile = Join-Path $TestDrive "readonly-test.txt"
"ReadOnly test content" | Out-File -FilePath $readOnlyFile -Encoding utf8
Set-ItemProperty -Path $readOnlyFile -Name IsReadOnly -Value $true
$form = @ { TestFile = [ System.IO.FileInfo ] $readOnlyFile }
$uri = Get-WebListenerUrl -Test 'Multipart'
$result = Invoke-RestMethod -Uri $uri -Form $form -Method 'POST'
$result . Headers . 'Content-Type' | Should -Match 'multipart/form-data'
$result . Files . Count | Should -Be 1
$result . Files [ 0 ]. Name | Should -Be "TestFile"
$result . Files [ 0 ]. FileName | Should -Be "readonly-test.txt"
$result . Files [ 0 ]. ContentType | Should -Be 'application/octet-stream'
$result . Files [ 0 ]. Content | Should -Match "ReadOnly test content"
}
2023-06-12 18:55:32 +02:00
It "Verifies Invoke-RestMethod -Form sets Content-Disposition FileName and FileNameStar." {
$ContentDisposition = [ System.Net.Http.Headers.ContentDispositionHeaderValue ]:: new ( "attachment" )
$ContentDisposition . FileName = $fileName
$ContentDisposition . FileNameStar = $fileName
$form = @ { TestFile = [ System.IO.FileInfo ] $file3Path }
$uri = Get-WebListenerUrl -Test 'Multipart'
$result = Invoke-RestMethod -Uri $uri -Form $form -Method 'POST'
$result . Headers . 'Content-Type' | Should -Match 'multipart/form-data'
$result . Files . Count | Should -Be 1
$result . Files [ 0 ]. ContentDisposition . FileName | Should -Be $ContentDisposition . FileName
$result . Files [ 0 ]. ContentDisposition . FileNameStar | Should -Be $ContentDisposition . FileNameStar
}
2018-01-24 23:17:55 -06:00
It "Verifies Invoke-RestMethod -Form supports a collection of file values" {
$form = @ { TestFiles = [ System.IO.FileInfo ] $file1Path , [ System.IO.FileInfo ] $file2Path }
$uri = Get-WebListenerUrl -Test 'Multipart'
$result = Invoke-RestMethod -Uri $uri -Form $form -Method 'POST'
2018-03-01 23:00:00 -06:00
$result . Headers . 'Content-Type' | Should -Match 'multipart/form-data'
$result . Files . Count | Should -Be 2
2018-01-24 23:17:55 -06:00
2018-03-01 23:00:00 -06:00
$result . Files [ 0 ]. Name | Should -Be "TestFiles"
$result . Files [ 0 ]. FileName | Should -Be $file1Name
$result . Files [ 0 ]. ContentType | Should -Be 'application/octet-stream'
$result . Files [ 0 ]. Content | Should -Match $file1Contents
2018-01-24 23:17:55 -06:00
2018-03-01 23:00:00 -06:00
$result . Files [ 1 ]. Name | Should -Be "TestFiles"
$result . Files [ 1 ]. FileName | Should -Be $file2Name
$result . Files [ 1 ]. ContentType | Should -Be 'application/octet-stream'
$result . Files [ 1 ]. Content | Should -Match $file2Contents
2018-01-24 23:17:55 -06:00
}
It "Verifies Invoke-RestMethod -Form supports combinations of strings and files" {
$form = @ {
TestStrings = "TestValue" , "TestValue2"
TestFiles = [ System.IO.FileInfo ] $file1Path , [ System.IO.FileInfo ] $file2Path
}
$uri = Get-WebListenerUrl -Test 'Multipart'
$result = Invoke-RestMethod -Uri $uri -Form $form -Method 'POST'
2018-03-01 23:00:00 -06:00
$result . Headers . 'Content-Type' | Should -Match 'multipart/form-data'
$result . Items . TestStrings . Count | Should -Be 2
$result . Files . Count | Should -Be 2
2018-01-24 23:17:55 -06:00
2018-03-01 23:00:00 -06:00
$result . Items . TestStrings [ 0 ] | Should -Be 'TestValue'
$result . Items . TestStrings [ 1 ] | Should -Be 'TestValue2'
2018-01-24 23:17:55 -06:00
2018-03-01 23:00:00 -06:00
$result . Files [ 0 ]. Name | Should -Be "TestFiles"
$result . Files [ 0 ]. FileName | Should -Be $file1Name
$result . Files [ 0 ]. ContentType | Should -Be 'application/octet-stream'
$result . Files [ 0 ]. Content | Should -Match $file1Contents
2018-01-24 23:17:55 -06:00
2018-03-01 23:00:00 -06:00
$result . Files [ 1 ]. Name | Should -Be "TestFiles"
$result . Files [ 1 ]. FileName | Should -Be $file2Name
$result . Files [ 1 ]. ContentType | Should -Be 'application/octet-stream'
$result . Files [ 1 ]. Content | Should -Match $file2Contents
2018-01-24 23:17:55 -06:00
}
It "Verifies Invoke-RestMethod -Form is mutually exclusive with -Body" {
$form = @ { TestString = "TestValue" }
$body = "test"
$uri = Get-WebListenerUrl -Test 'Multipart'
{ Invoke-RestMethod -Uri $uri -Form $form -Body $Body -ErrorAction 'Stop' } |
2018-05-17 14:42:04 -07:00
Should -Throw -ErrorId 'WebCmdletBodyFormConflictException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand'
2018-01-24 23:17:55 -06:00
}
It "Verifies Invoke-RestMethod -Form is mutually exclusive with -InFile" {
$form = @ { TestString = "TestValue" }
$uri = Get-WebListenerUrl -Test 'Multipart'
{ Invoke-RestMethod -Uri $uri -Form $form -InFile $file1Path -ErrorAction 'Stop' } |
2018-05-17 14:42:04 -07:00
Should -Throw -ErrorId 'WebCmdletFormInFileConflictException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand'
2018-01-24 23:17:55 -06:00
}
2017-09-12 11:41:36 -05:00
}
2019-01-18 22:16:18 -08:00
It "Verifies Invoke-RestMethod does not sent expect 100-continue headers by default" {
$uri = Get-WebListenerUrl -Test 'Get'
$result = Invoke-RestMethod -Uri $uri
$result . headers . Expect | Should -BeNullOrEmpty
$result . method | Should -BeExactly "GET"
$result . url | Should -BeExactly $uri . ToString ()
}
It "Verifies Invoke-RestMethod sends expect 100-continue header when defined in -Headers" {
$uri = Get-WebListenerUrl -Test 'Get'
$result = Invoke-RestMethod -Uri $uri -Headers @ { Expect = '100-continue' }
$result . headers . Expect | Should -BeExactly '100-continue'
$result . method | Should -BeExactly "GET"
$result . url | Should -BeExactly $uri . ToString ()
}
2017-08-31 10:47:54 -07:00
#region charset encoding tests
Context "Invoke-RestMethod Encoding tests with BasicHtmlWebResponseObject response" {
It "Verifies Invoke-RestMethod detects charset meta value when the ContentType header does not define it." {
2017-12-04 11:52:14 -06:00
$query = @ {
contenttype = 'text/html'
2018-01-09 15:43:25 -06:00
body = '<html><head><meta charset="Unicode"></head></html>'
2017-12-04 11:52:14 -06:00
}
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2017-08-31 10:47:54 -07:00
$expectedEncoding = [ System.Text.Encoding ]:: GetEncoding ( 'Unicode' )
2017-12-04 11:52:14 -06:00
$response = ExecuteRestMethod -Uri $uri -UseBasicParsing
2017-08-31 10:47:54 -07:00
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
$response . Encoding . EncodingName | Should -Be $expectedEncoding . EncodingName
2017-08-31 10:47:54 -07:00
}
It "Verifies Invoke-WebRequest detects charset meta value when newlines are encountered in the element." {
2017-12-04 11:52:14 -06:00
$query = @ {
contenttype = 'text/html'
2018-01-09 15:43:25 -06:00
body = "<html> `n <head> `n <meta `n charset= `" Unicode `"`n > `n </head> `n </html>"
2017-12-04 11:52:14 -06:00
}
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2017-08-31 10:47:54 -07:00
$expectedEncoding = [ System.Text.Encoding ]:: GetEncoding ( 'Unicode' )
2017-12-04 11:52:14 -06:00
$response = ExecuteRestMethod -Uri $uri -UseBasicParsing
2017-08-31 10:47:54 -07:00
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
$response . Encoding . EncodingName | Should -Be $expectedEncoding . EncodingName
2017-08-31 10:47:54 -07:00
}
It "Verifies Invoke-RestMethod detects charset meta value when the attribute value is unquoted." {
2017-12-04 11:52:14 -06:00
$query = @ {
contenttype = 'text/html'
2018-01-09 15:43:25 -06:00
body = '<html><head><meta charset = Unicode></head></html>'
2017-12-04 11:52:14 -06:00
}
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2017-08-31 10:47:54 -07:00
$expectedEncoding = [ System.Text.Encoding ]:: GetEncoding ( 'Unicode' )
2017-12-04 11:52:14 -06:00
$response = ExecuteRestMethod -Uri $uri -UseBasicParsing
2017-08-31 10:47:54 -07:00
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
$response . Encoding . EncodingName | Should -Be $expectedEncoding . EncodingName
2017-08-31 10:47:54 -07:00
}
It "Verifies Invoke-RestMethod detects http-equiv charset meta value when the ContentType header does not define it." {
2017-12-04 11:52:14 -06:00
$query = @ {
contenttype = 'text/html'
2018-01-09 15:43:25 -06:00
body = "<html><head> `n <meta http-equiv= `" content-type `" content= `" text/html; charset=Unicode `" > `n </head> `n </html>"
2017-12-04 11:52:14 -06:00
}
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2017-08-31 10:47:54 -07:00
$expectedEncoding = [ System.Text.Encoding ]:: GetEncoding ( 'Unicode' )
2017-12-04 11:52:14 -06:00
$response = ExecuteRestMethod -Uri $uri -UseBasicParsing
2017-08-31 10:47:54 -07:00
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
$response . Encoding . EncodingName | Should -Be $expectedEncoding . EncodingName
2017-08-31 10:47:54 -07:00
}
It "Verifies Invoke-RestMethod detects http-equiv charset meta value newlines are encountered in the element." {
2017-12-04 11:52:14 -06:00
$query = @ {
contenttype = 'text/html'
2018-01-09 15:43:25 -06:00
body = "<html><head> `n <meta `n http-equiv= `" content-type `"`n content= `" text/html; charset=Unicode `" > `n </head> `n </html> `n "
2017-12-04 11:52:14 -06:00
}
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2017-08-31 10:47:54 -07:00
$expectedEncoding = [ System.Text.Encoding ]:: GetEncoding ( 'Unicode' )
2017-12-04 11:52:14 -06:00
$response = ExecuteRestMethod -Uri $uri -UseBasicParsing
2017-08-31 10:47:54 -07:00
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
$response . Encoding . EncodingName | Should -Be $expectedEncoding . EncodingName
2017-08-31 10:47:54 -07:00
}
It "Verifies Invoke-RestMethod ignores meta charset value when Content-Type header defines it." {
2017-12-04 11:52:14 -06:00
$query = @ {
contenttype = 'text/html; charset=utf-8'
2018-01-09 15:43:25 -06:00
body = '<html><head><meta charset="utf-32"></head></html>'
2017-12-04 11:52:14 -06:00
}
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2017-08-31 10:47:54 -07:00
# NOTE: meta charset should be ignored
$expectedEncoding = [ System.Text.Encoding ]:: UTF8
2017-12-04 11:52:14 -06:00
$response = ExecuteRestMethod -Uri $uri -UseBasicParsing
2017-08-31 10:47:54 -07:00
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
$response . Encoding . EncodingName | Should -Be $expectedEncoding . EncodingName
2017-08-31 10:47:54 -07:00
}
It "Verifies Invoke-RestMethod honors non-utf8 charsets in the Content-Type header" {
2017-12-04 11:52:14 -06:00
$query = @ {
contenttype = 'text/html; charset=utf-16'
2018-01-09 15:43:25 -06:00
body = '<html><head><meta charset="utf-32"></head></html>'
2017-12-04 11:52:14 -06:00
}
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2017-08-31 10:47:54 -07:00
# NOTE: meta charset should be ignored
$expectedEncoding = [ System.Text.Encoding ]:: GetEncoding ( 'utf-16' )
2017-12-04 11:52:14 -06:00
$response = ExecuteRestMethod -Uri $uri -UseBasicParsing
2017-08-31 10:47:54 -07:00
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
$response . Encoding . EncodingName | Should -Be $expectedEncoding . EncodingName
2017-08-31 10:47:54 -07:00
}
2022-11-02 18:34:09 +01:00
It "Verifies Invoke-RestMethod defaults to UTF-8 when an unsupported/invalid charset is declared" {
2017-12-04 11:52:14 -06:00
$query = @ {
contenttype = 'text/html'
2018-01-09 15:43:25 -06:00
body = '<html><head><meta charset="invalid"></head></html>'
2017-12-04 11:52:14 -06:00
}
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2018-02-21 23:31:00 -06:00
$expectedEncoding = [ System.Text.Encoding ]:: UTF8
$response = ExecuteRestMethod -Uri $uri -UseBasicParsing
2018-03-01 23:00:00 -06:00
$response . Error | Should -BeNullOrEmpty
$response . Encoding . EncodingName | Should -Be $expectedEncoding . EncodingName
2022-11-02 18:34:09 +01:00
}
It "Verifies Invoke-RestMethod defaults to UTF-8 when an unsupported/invalid charset is declared using http-equiv" {
$query = @ {
contenttype = 'text/html'
body = "<html><head> `n <meta http-equiv= `" content-type `" content= `" text/html; charset=Invalid `" > `n </head> `n </html>"
}
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
$expectedEncoding = [ System.Text.Encoding ]:: UTF8
$response = ExecuteRestMethod -Uri $uri -UseBasicParsing
$response . Error | Should -BeNullOrEmpty
$response . Encoding . EncodingName | Should -Be $expectedEncoding . EncodingName
2018-02-21 23:31:00 -06:00
}
2017-08-31 10:47:54 -07:00
}
#endregion charset encoding tests
2017-09-25 12:11:12 -05:00
Context 'Invoke-RestMethod ResponseHeadersVariable Tests' {
It "Verifies Invoke-RestMethod supports -ResponseHeadersVariable" {
$uri = Get-WebListenerUrl -Test '/'
$response = Invoke-RestMethod -Uri $uri -ResponseHeadersVariable 'headers'
2018-03-01 23:00:00 -06:00
$headers . 'Content-Type' | Should -Be 'text/html; charset=utf-8'
$headers . Server | Should -Be 'Kestrel'
2017-09-25 12:11:12 -05:00
}
2017-10-05 09:46:33 -07:00
2017-09-25 12:11:12 -05:00
It "Verifies Invoke-RestMethod supports -ResponseHeadersVariable overwriting existing variable" {
$uri = Get-WebListenerUrl -Test '/'
$headers = 'prexisting'
$response = Invoke-RestMethod -Uri $uri -ResponseHeadersVariable 'headers'
2018-03-01 23:00:00 -06:00
$headers | Should -Not -Be 'prexisting'
$headers . 'Content-Type' | Should -Be 'text/html; charset=utf-8'
$headers . Server | Should -Be 'Kestrel'
2017-09-25 12:11:12 -05:00
}
}
2017-10-17 21:08:06 -05:00
Context "Invoke-RestMethod -Authentication tests" {
BeforeAll {
#[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Demo/doc/test secret.")]
$token = "testpassword" | ConvertTo-SecureString -AsPlainText -Force
2018-01-09 15:43:25 -06:00
$credential = [ pscredential ]:: new ( "testuser" , $token )
2017-10-17 21:08:06 -05:00
$httpUri = Get-WebListenerUrl -Test 'Get'
$httpsUri = Get-WebListenerUrl -Test 'Get' -Https
2017-11-10 10:11:57 -06:00
$httpBasicUri = Get-WebListenerUrl -Test 'Auth' -TestValue 'Basic'
$httpsBasicUri = Get-WebListenerUrl -Test 'Auth' -TestValue 'Basic' -Https
2017-10-17 21:08:06 -05:00
$testCases = @ (
@ { Authentication = "bearer" }
@ { Authentication = "OAuth" }
)
}
It "Verifies Invoke-RestMethod -Authentication Basic" {
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpsUri
Authentication = "Basic"
Credential = $credential
2017-10-17 21:08:06 -05:00
SkipCertificateCheck = $true
}
$result = Invoke-RestMethod @params
2018-03-01 23:00:00 -06:00
$result . Headers . Authorization | Should -BeExactly "Basic dGVzdHVzZXI6dGVzdHBhc3N3b3Jk"
2017-10-17 21:08:06 -05:00
}
2019-05-06 17:15:04 -07:00
It "Verifies Invoke-RestMethod -Authentication Basic with null username" {
$credential = [ pscredential ]:: new ([ PSCustomObject ] @ { UserName = $null ; Password = $token . psobject . BaseObject })
$params = @ {
Uri = $httpsUri
Authentication = "Basic"
Credential = $credential
SkipCertificateCheck = $true
}
$Response = Invoke-RestMethod @params
$Response . Headers . Authorization | Should -BeExactly "Basic OnRlc3RwYXNzd29yZA=="
}
2017-10-17 21:08:06 -05:00
It "Verifies Invoke-RestMethod -Authentication <Authentication>" -TestCases $testCases {
param ( $Authentication )
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpsUri
Authentication = $Authentication
Token = $token
2017-10-17 21:08:06 -05:00
SkipCertificateCheck = $true
}
$result = Invoke-RestMethod @params
2018-03-01 23:00:00 -06:00
$result . Headers . Authorization | Should -BeExactly "Bearer testpassword"
2017-10-17 21:08:06 -05:00
}
It "Verifies Invoke-RestMethod -Authentication does not support -UseDefaultCredentials" {
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpsUri
Token = $token
Authentication = "OAuth"
2017-10-17 21:08:06 -05:00
UseDefaultCredentials = $true
2018-01-09 15:43:25 -06:00
ErrorAction = 'Stop'
SkipCertificateCheck = $true
2017-10-17 21:08:06 -05:00
}
2018-05-17 14:42:04 -07:00
{ Invoke-RestMethod @params } | Should -Throw -ErrorId "WebCmdletAuthenticationConflictException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
2017-10-17 21:08:06 -05:00
}
It "Verifies Invoke-RestMethod -Authentication does not support Both -Credential and -Token" {
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpsUri
Token = $token
Credential = $credential
Authentication = "OAuth"
ErrorAction = 'Stop'
2017-10-17 21:08:06 -05:00
SkipCertificateCheck = $true
}
2018-05-17 14:42:04 -07:00
{ Invoke-RestMethod @params } | Should -Throw -ErrorId "WebCmdletAuthenticationTokenConflictException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
2017-10-17 21:08:06 -05:00
}
It "Verifies Invoke-RestMethod -Authentication <Authentication> requires -Token" -TestCases $testCases {
param ( $Authentication )
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpsUri
Authentication = $Authentication
ErrorAction = 'Stop'
2017-10-17 21:08:06 -05:00
SkipCertificateCheck = $true
}
2018-05-17 14:42:04 -07:00
{ Invoke-RestMethod @params } | Should -Throw -ErrorId "WebCmdletAuthenticationTokenNotSuppliedException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
2017-10-17 21:08:06 -05:00
}
It "Verifies Invoke-RestMethod -Authentication Basic requires -Credential" {
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpsUri
Authentication = "Basic"
ErrorAction = 'Stop'
2017-10-17 21:08:06 -05:00
SkipCertificateCheck = $true
}
2018-05-17 14:42:04 -07:00
{ Invoke-RestMethod @params } | Should -Throw -ErrorId "WebCmdletAuthenticationCredentialNotSuppliedException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
2017-10-17 21:08:06 -05:00
}
It "Verifies Invoke-RestMethod -Authentication Requires HTTPS" {
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpUri
Token = $token
2017-10-17 21:08:06 -05:00
Authentication = "OAuth"
2018-01-09 15:43:25 -06:00
ErrorAction = 'Stop'
2017-10-17 21:08:06 -05:00
}
2018-05-17 14:42:04 -07:00
{ Invoke-RestMethod @params } | Should -Throw -ErrorId "WebCmdletAllowUnencryptedAuthenticationRequiredException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
2017-10-17 21:08:06 -05:00
}
It "Verifies Invoke-RestMethod -Authentication Can use HTTP with -AllowUnencryptedAuthentication" {
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpUri
Token = $token
Authentication = "OAuth"
2017-10-17 21:08:06 -05:00
AllowUnencryptedAuthentication = $true
}
$result = Invoke-RestMethod @params
2018-03-01 23:00:00 -06:00
$result . Headers . Authorization | Should -BeExactly "Bearer testpassword"
2017-10-17 21:08:06 -05:00
}
2017-11-10 10:11:57 -06:00
It "Verifies Invoke-RestMethod Negotiated -Credential over HTTPS" {
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpsBasicUri
Credential = $credential
2017-11-10 10:11:57 -06:00
SkipCertificateCheck = $true
}
$result = Invoke-RestMethod @params
2018-03-01 23:00:00 -06:00
$result . Headers . Authorization | Should -BeExactly "Basic dGVzdHVzZXI6dGVzdHBhc3N3b3Jk"
2017-11-10 10:11:57 -06:00
}
It "Verifies Invoke-RestMethod Negotiated -Credential Requires HTTPS" {
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpBasicUri
Credential = $credential
2017-11-10 10:11:57 -06:00
ErrorAction = 'Stop'
}
2018-05-17 14:42:04 -07:00
{ Invoke-RestMethod @params } | Should -Throw -ErrorId "WebCmdletAllowUnencryptedAuthenticationRequiredException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
2017-11-10 10:11:57 -06:00
}
It "Verifies Invoke-RestMethod Negotiated -Credential Can use HTTP with -AllowUnencryptedAuthentication" {
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpBasicUri
Credential = $credential
2017-11-10 10:11:57 -06:00
AllowUnencryptedAuthentication = $true
}
$result = Invoke-RestMethod @params
2018-03-01 23:00:00 -06:00
$result . Headers . Authorization | Should -BeExactly "Basic dGVzdHVzZXI6dGVzdHBhc3N3b3Jk"
2017-11-10 10:11:57 -06:00
}
# UseDefaultCredentials is only reliably testable on Windows
It "Verifies Invoke-RestMethod Negotiated -UseDefaultCredentials with '<AuthType>' over HTTPS" -Skip: $ (! $IsWindows ) -TestCases @ (
@ { AuthType = 'NTLM' }
@ { AuthType = 'Negotiate' }
) {
param ( $AuthType )
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = Get-WebListenerUrl -Test 'Auth' -TestValue $AuthType -Https
2017-11-10 10:11:57 -06:00
UseDefaultCredentials = $true
2018-01-09 15:43:25 -06:00
SkipCertificateCheck = $true
2017-11-10 10:11:57 -06:00
}
$result = Invoke-RestMethod @params
2018-03-01 23:00:00 -06:00
$result . Headers . Authorization | Should -Match "^ $AuthType "
2017-11-10 10:11:57 -06:00
}
# The error condition can at least be tested on all platforms.
It "Verifies Invoke-RestMethod Negotiated -UseDefaultCredentials Requires HTTPS" {
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = $httpUri
2017-11-10 10:11:57 -06:00
UseDefaultCredentials = $true
2018-01-09 15:43:25 -06:00
ErrorAction = 'Stop'
2017-11-10 10:11:57 -06:00
}
2018-05-17 14:42:04 -07:00
{ Invoke-RestMethod @params } | Should -Throw -ErrorId "WebCmdletAllowUnencryptedAuthenticationRequiredException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
2017-11-10 10:11:57 -06:00
}
# UseDefaultCredentials is only reliably testable on Windows
It "Verifies Invoke-RestMethod Negotiated -UseDefaultCredentials with '<AuthType>' Can use HTTP with -AllowUnencryptedAuthentication" -Skip: $ (! $IsWindows ) -TestCases @ (
@ { AuthType = 'NTLM' }
@ { AuthType = 'Negotiate' }
) {
param ( $AuthType )
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = Get-WebListenerUrl -Test 'Auth' -TestValue $AuthType
UseDefaultCredentials = $true
2017-11-10 10:11:57 -06:00
AllowUnencryptedAuthentication = $true
}
$result = Invoke-RestMethod @params
2018-03-01 23:00:00 -06:00
$result . Headers . Authorization | Should -Match "^ $AuthType "
2017-11-10 10:11:57 -06:00
}
2017-10-17 21:08:06 -05:00
}
2017-11-13 12:45:46 -06:00
Context "Invoke-RestMethod -SslProtocol Test" {
2017-12-04 11:38:30 -08:00
BeforeAll {
2020-09-02 22:18:15 +05:00
# We put Tls13 tests at pending due to modern OS limitations.
# Tracking issue https://github.com/PowerShell/PowerShell/issues/13439
2022-03-25 16:15:16 -07:00
$skipForTls1 = $true
2020-09-23 14:04:01 -07:00
2017-12-04 11:38:30 -08:00
$testCases1 = @ (
@ { Test = @ { SslProtocol = 'Default' ; ActualProtocol = 'Default' }; Pending = $false }
2022-03-25 16:15:16 -07:00
@ { Test = @ { SslProtocol = 'Tls' ; ActualProtocol = 'Tls' }; Pending = $skipForTls1 }
@ { Test = @ { SslProtocol = 'Tls11' ; ActualProtocol = 'Tls11' }; Pending = $skipForTls1 }
2017-12-06 14:20:44 -06:00
@ { Test = @ { SslProtocol = 'Tls12' ; ActualProtocol = 'Tls12' }; Pending = $false }
2020-09-02 22:18:15 +05:00
@ { Test = @ { SslProtocol = 'Tls13' ; ActualProtocol = 'Tls13' }; Pending = $true }
2018-05-09 06:35:52 -05:00
@ { Test = @ { SslProtocol = 'Tls, Tls11, Tls12' ; ActualProtocol = 'Tls12' }; Pending = $false }
2020-09-02 22:18:15 +05:00
@ { Test = @ { SslProtocol = 'Tls, Tls11, Tls12, Tls13' ; ActualProtocol = 'Tls13' }; Pending = $true }
2018-05-09 06:35:52 -05:00
@ { Test = @ { SslProtocol = 'Tls11, Tls12' ; ActualProtocol = 'Tls12' }; Pending = $false }
2022-03-25 16:15:16 -07:00
@ { Test = @ { SslProtocol = 'Tls, Tls11, Tls12' ; ActualProtocol = 'Tls11' }; Pending = $skipForTls1 }
@ { Test = @ { SslProtocol = 'Tls, Tls11, Tls12, Tls13' ; ActualProtocol = 'Tls11' }; Pending = $skipForTls1 }
@ { Test = @ { SslProtocol = 'Tls11, Tls12' ; ActualProtocol = 'Tls11' }; Pending = $skipForTls1 }
@ { Test = @ { SslProtocol = 'Tls, Tls11' ; ActualProtocol = 'Tls11' }; Pending = $skipForTls1 }
@ { Test = @ { SslProtocol = 'Tls, Tls11, Tls12' ; ActualProtocol = 'Tls' }; Pending = $skipForTls1 }
2020-09-02 22:18:15 +05:00
@ { Test = @ { SslProtocol = 'Tls, Tls11, Tls13' ; ActualProtocol = 'Tls' }; Pending = $true }
2022-03-25 16:15:16 -07:00
@ { Test = @ { SslProtocol = 'Tls, Tls11' ; ActualProtocol = 'Tls' }; Pending = $skipForTls1 }
2018-05-09 06:35:52 -05:00
# Skipping intermediary protocols is not supported on all platforms
2022-03-25 16:15:16 -07:00
# Removed this as Tls now default to Tls12
# @{ Test = @{SslProtocol = 'Tls, Tls12'; ActualProtocol = 'Tls'}; Pending = -not $IsWindows }
2017-12-04 11:38:30 -08:00
@ { Test = @ { SslProtocol = 'Tls, Tls12' ; ActualProtocol = 'Tls12' }; Pending = -not $IsWindows }
)
2017-11-13 12:45:46 -06:00
2017-12-04 11:38:30 -08:00
$testCases2 = @ (
2020-09-02 22:18:15 +05:00
@ { Test = @ { IntendedProtocol = 'Tls' ; ActualProtocol = 'Tls13' }; Pending = $true }
@ { Test = @ { IntendedProtocol = 'Tls11' ; ActualProtocol = 'Tls13' }; Pending = $true }
@ { Test = @ { IntendedProtocol = 'Tls13' ; ActualProtocol = 'Tls' }; Pending = $true }
@ { Test = @ { IntendedProtocol = 'Tls, Tls12' ; ActualProtocol = 'Tls13' }; Pending = $true }
2017-12-04 11:38:30 -08:00
)
2017-11-13 12:45:46 -06:00
}
2017-12-04 11:38:30 -08:00
foreach ( $entry in $testCases1 ) {
It "Verifies Invoke-RestMethod -SslProtocol <SslProtocol> works on <ActualProtocol>" -TestCases ( $entry . Test ) -Pending: ( $entry . Pending ) {
param ( $SslProtocol , $ActualProtocol )
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = Get-WebListenerUrl -Test 'Get' -Https -SslProtocol $ActualProtocol
SslProtocol = $SslProtocol
2017-12-04 11:38:30 -08:00
SkipCertificateCheck = $true
}
$result = Invoke-RestMethod @params
2018-03-01 23:00:00 -06:00
$result . headers . Host | Should -Be $params . Uri . Authority
2017-11-13 12:45:46 -06:00
}
}
2017-12-04 11:38:30 -08:00
foreach ( $entry in $testCases2 ) {
It "Verifies Invoke-RestMethod -SslProtocol <IntendedProtocol> fails on a <ActualProtocol> only connection" -TestCases ( $entry . Test ) -Pending: ( $entry . Pending ) {
param ( $IntendedProtocol , $ActualProtocol )
$params = @ {
2018-01-09 15:43:25 -06:00
Uri = Get-WebListenerUrl -Test 'Get' -Https -SslProtocol $ActualProtocol
SslProtocol = $IntendedProtocol
2017-12-04 11:38:30 -08:00
SkipCertificateCheck = $true
2018-01-09 15:43:25 -06:00
ErrorAction = 'Stop'
2017-12-04 11:38:30 -08:00
}
2018-05-17 14:42:04 -07:00
{ Invoke-RestMethod @params } | Should -Throw -ErrorId 'WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand'
2017-12-04 11:38:30 -08:00
}
}
2017-11-13 12:45:46 -06:00
}
2017-11-13 21:53:43 -06:00
Context "Invoke-RestMethod Single Value JSON null support" {
It "Invoke-RestMethod Supports a Single Value JSON null" {
2017-12-04 11:52:14 -06:00
$query = @ {
contenttype = 'application/json'
2018-01-09 15:43:25 -06:00
body = 'null'
2017-12-04 11:52:14 -06:00
}
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2018-03-01 23:00:00 -06:00
Invoke-RestMethod -Uri $uri | Should -Be $null
2017-11-13 21:53:43 -06:00
}
2018-01-09 15:43:25 -06:00
2017-11-13 21:53:43 -06:00
It "Invoke-RestMethod Supports a Single Value JSON null and ignores whitespace" {
2017-12-04 11:52:14 -06:00
$query = @ {
contenttype = 'application/json'
2018-01-09 15:43:25 -06:00
body = " null "
2017-12-04 11:52:14 -06:00
}
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2018-03-01 23:00:00 -06:00
Invoke-RestMethod -Uri $uri | Should -Be $null
2017-12-04 11:52:14 -06:00
$query [ 'body' ] = " null `n "
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2018-03-01 23:00:00 -06:00
Invoke-RestMethod -Uri $uri | Should -Be $null
2017-11-13 21:53:43 -06:00
}
}
2018-03-26 12:23:24 -07:00
Context "Invoke-RestMethod File Resume Feature" {
BeforeAll {
$outFile = Join-Path $TestDrive "resume.txt"
# Download the entire file to reference in tests
$referenceFile = Join-Path $TestDrive "reference.txt"
$resumeUri = Get-WebListenerUrl -Test 'Resume'
2020-05-07 13:00:30 +01:00
Invoke-RestMethod -Uri $resumeUri -OutFile $referenceFile -ErrorAction Stop
2018-03-26 12:23:24 -07:00
$referenceFileHash = Get-FileHash -Algorithm SHA256 -Path $referenceFile
$referenceFileSize = Get-Item $referenceFile | Select-Object -ExpandProperty Length
}
AfterEach {
Remove-Item -Force -ErrorAction 'SilentlyContinue' -Path $outFile
}
It "Invoke-RestMethod -Resume requires -OutFile" {
{ Invoke-RestMethod -Resume -Uri $resumeUri -ErrorAction Stop } |
Should -Throw -ErrorId 'WebCmdletOutFileMissingException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand'
}
2023-03-21 09:06:50 +01:00
It "Invoke-RestMethod -Resume should fail if -OutFile folder" {
{ Invoke-RestMethod -Resume -Uri $resumeUri -OutFile $TestDrive -ErrorAction Stop } |
Should -Throw -ErrorId 'WebCmdletResumeNotFilePathException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand'
}
2018-03-26 12:23:24 -07:00
It "Invoke-RestMethod -Resume Downloads the whole file when the file does not exist" {
# ensure the file does not exist
Remove-Item -Force -ErrorAction 'SilentlyContinue' -Path $outFile
2020-05-07 13:00:30 +01:00
Invoke-RestMethod -Uri $resumeUri -OutFile $outFile -ResponseHeadersVariable 'Headers' -Resume
2018-03-26 12:23:24 -07:00
$outFileHash = Get-FileHash -Algorithm SHA256 -Path $outFile
$outFileHash . Hash | Should -BeExactly $referenceFileHash . Hash
Get-Item $outFile | Select-Object -ExpandProperty Length | Should -Be $referenceFileSize
$Headers . 'X-WebListener-Has-Range' [ 0 ] | Should -BeExactly 'true'
$Headers . 'X-WebListener-Request-Range' [ 0 ] | Should -BeExactly 'bytes=0-'
$Headers . 'Content-Range' [ 0 ] | Should -BeExactly "bytes 0- $( $referenceFileSize - 1 ) / $referenceFileSize "
}
It "Invoke-RestMethod -Resume overwrites an existing file that is larger than the remote file" {
# Create a file larger than the download file
$largerFileSize = $referenceFileSize + 20
1 .. $largerFileSize | ForEach-Object { [ Byte ] $_ } | Set-Content -AsByteStream $outFile
$largerFileSize = Get-Item $outFile | Select-Object -ExpandProperty Length
2020-05-07 13:00:30 +01:00
$response = Invoke-RestMethod -Uri $resumeUri -OutFile $outFile -ResponseHeadersVariable 'Headers' -Resume
2018-03-26 12:23:24 -07:00
$outFileHash = Get-FileHash -Algorithm SHA256 -Path $outFile
$outFileHash . Hash | Should -BeExactly $referenceFileHash . Hash
Get-Item $outFile | Select-Object -ExpandProperty Length | Should -Be $referenceFileSize
Get-Item $outFile | Select-Object -ExpandProperty Length | Should -BeLessThan $largerFileSize
$Headers . 'X-WebListener-Has-Range' [ 0 ] | Should -BeExactly 'false'
$Headers . ContainsKey ( 'Content-Range' ) | Should -BeFalse
}
It "Invoke-RestMethod -Resume overwrites existing file when remote server does not support resume" {
# Create a file larger than the download file
$largerFileSize = $referenceFileSize + 20
1 .. $largerFileSize | ForEach-Object { [ Byte ] $_ } | Set-Content -AsByteStream $outFile
$largerFileSize = Get-Item $outFile | Select-Object -ExpandProperty Length
$uri = Get-WebListenerUrl -Test 'Resume' -TestValue 'NoResume'
2020-05-07 13:00:30 +01:00
$response = Invoke-RestMethod -Uri $uri -OutFile $outFile -ResponseHeadersVariable 'Headers' -Resume
2018-03-26 12:23:24 -07:00
$outFileHash = Get-FileHash -Algorithm SHA256 -Path $outFile
$outFileHash . Hash | Should -BeExactly $referenceFileHash . Hash
Get-Item $outFile | Select-Object -ExpandProperty Length | Should -Be $referenceFileSize
Get-Item $outFile | Select-Object -ExpandProperty Length | Should -BeLessThan $largerFileSize
$Headers . 'X-WebListener-Has-Range' [ 0 ] | Should -BeExactly 'true'
$Headers . 'X-WebListener-Request-Range' [ 0 ] | Should -BeExactly "bytes= $largerFileSize -"
$Headers . ContainsKey ( 'Content-Range' ) | Should -BeFalse
}
It "Invoke-RestMethod -Resume resumes downloading from <bytes> bytes" -TestCases @ (
@ { bytes = 4 }
@ { bytes = 8 }
@ { bytes = 12 }
@ { bytes = 16 }
) {
param ( $bytes )
# Simulate partial download
$uri = Get-WebListenerUrl -Test 'Resume' -TestValue "Bytes/ $bytes "
2020-05-07 13:00:30 +01:00
$null = Invoke-RestMethod -Uri $uri -OutFile $outFile
2018-03-26 12:23:24 -07:00
Get-Item $outFile | Select-Object -ExpandProperty Length | Should -Be $bytes
2020-05-07 13:00:30 +01:00
$response = Invoke-RestMethod -Uri $resumeUri -OutFile $outFile -ResponseHeadersVariable 'Headers' -Resume
2018-03-26 12:23:24 -07:00
$outFileHash = Get-FileHash -Algorithm SHA256 -Path $outFile
2020-01-11 15:41:59 +00:00
$outFileHash . Hash | Should -BeExactly $referenceFileHash . Hash
2018-03-26 12:23:24 -07:00
Get-Item $outFile | Select-Object -ExpandProperty Length | Should -Be $referenceFileSize
$Headers . 'X-WebListener-Has-Range' [ 0 ] | Should -BeExactly 'true'
$Headers . 'X-WebListener-Request-Range' [ 0 ] | Should -BeExactly "bytes= $bytes -"
$Headers . 'Content-Range' [ 0 ] | Should -BeExactly "bytes $bytes - $( $referenceFileSize - 1 ) / $referenceFileSize "
}
It "Invoke-RestMethod -Resume assumes the file was successfully completed when the local and remote file are the same size." {
# Download the entire file
$uri = Get-WebListenerUrl -Test 'Resume' -TestValue 'NoResume'
2020-05-07 13:00:30 +01:00
$null = Invoke-RestMethod -Uri $uri -OutFile $outFile
2018-03-26 12:23:24 -07:00
$fileSize = Get-Item $outFile | Select-Object -ExpandProperty Length
2020-05-07 13:00:30 +01:00
$response = Invoke-RestMethod -Uri $resumeUri -OutFile $outFile -ResponseHeadersVariable 'Headers' -Resume
2018-03-26 12:23:24 -07:00
$outFileHash = Get-FileHash -Algorithm SHA256 -Path $outFile
$outFileHash . Hash | Should -BeExactly $referenceFileHash . Hash
Get-Item $outFile | Select-Object -ExpandProperty Length | Should -Be $referenceFileSize
$Headers . 'X-WebListener-Has-Range' [ 0 ] | Should -BeExactly 'true'
$Headers . 'X-WebListener-Request-Range' [ 0 ] | Should -BeExactly "bytes= $fileSize -"
$Headers . 'Content-Range' [ 0 ] | Should -BeExactly "bytes */ $referenceFileSize "
}
}
2018-06-28 21:06:53 -07:00
Context "Invoke-RestMethod retry tests" {
It "Invoke-RestMethod can retry - specified number of times - error 304" {
$uri = Get-WebListenerUrl -Test 'Retry'
$sessionId = ( New-Guid ). Guid
$body = @ { sessionid = $sessionId ; failureCode = 304 ; failureCount = 2 }
$commandStr = "Invoke-RestMethod -Uri ' $uri ' -MaximumRetryCount 2 -RetryIntervalSec 1 -Method POST -Body `$ body"
$result = ExecuteWebCommand -command $commandStr
$result . output . failureResponsesSent | Should -Be 2
$result . output . sessionId | Should -BeExactly $sessionId
}
It "Invoke-RestMethod can retry with POST" {
$uri = Get-WebListenerUrl -Test 'Retry'
$sessionId = ( New-Guid ). Guid
$body = @ { sessionid = $sessionId ; failureCode = 404 ; failureCount = 1 }
$commandStr = "Invoke-RestMethod -Uri ' $uri ' -MaximumRetryCount 2 -RetryIntervalSec 1 -Method POST -Body `$ body"
$result = ExecuteWebCommand -command $commandStr
$result . output . failureResponsesSent | Should -Be 1
$result . output . sessionId | Should -BeExactly $sessionId
}
2023-05-09 07:57:27 +09:00
It "Invoke-RestMethod respects the Retry-After header value in 429 status" {
$Query = @ {
statusCode = 429
reposnsephrase = 'Too Many Requests'
contenttype = 'application/json'
body = '{"message":"oops"}'
headers = '{"Retry-After":"1"}'
}
$uri = Get-WebListenerUrl -Test 'Response' -Query $Query
$verboseFile = Join-Path $TestDrive -ChildPath verbose . txt
$result = Invoke-RestMethod -Uri $uri -MaximumRetryCount 1 -RetryIntervalSec 3 -SkipHttpErrorCheck -Verbose 4 > $verbosefile
$verboseFile | Should -FileContentMatch 'Retrying after interval of 1 seconds. Status code for previous attempt: TooManyRequests'
}
It "Invoke-RestMethod ignores the Retry-After header value NOT in 429 status" {
$Query = @ {
statusCode = 409
reposnsephrase = 'Conflict'
contenttype = 'application/json'
body = '{"message":"oops"}'
headers = '{"Retry-After":"1"}'
}
$uri = Get-WebListenerUrl -Test 'Response' -Query $Query
$verboseFile = Join-Path $TestDrive -ChildPath verbose . txt
$result = Invoke-RestMethod -Uri $uri -MaximumRetryCount 1 -RetryIntervalSec 3 -SkipHttpErrorCheck -Verbose 4 > $verbosefile
$verboseFile | Should -FileContentMatch 'Retrying after interval of 3 seconds. Status code for previous attempt: Conflict'
}
2018-06-28 21:06:53 -07:00
}
2016-07-22 15:09:03 -07:00
}
2017-02-01 10:14:24 -08:00
2018-12-11 14:15:33 -08:00
Describe "Validate Invoke-WebRequest and Invoke-RestMethod -InFile" -Tags "Feature" , "RequireAdminOnWindows" {
2018-04-09 23:12:45 -07:00
BeforeAll {
2022-01-03 11:20:33 -08:00
$oldProgress = $ProgressPreference
$ProgressPreference = 'SilentlyContinue'
2018-04-09 23:12:45 -07:00
$WebListener = Start-WebListener
}
2022-01-03 11:20:33 -08:00
AfterAll {
$ProgressPreference = $oldProgress
}
2017-02-01 10:14:24 -08:00
Context "InFile parameter negative tests" {
2017-12-13 09:28:05 -06:00
BeforeAll {
$uri = Get-WebListenerUrl -Test 'Post'
$testCases = @ (
2018-01-09 15:43:25 -06:00
#region INVOKE-WEBREQUEST
2023-02-01 17:45:09 +01:00
@ {
Name = 'Validate error for Invoke-WebRequest -InFile null'
ScriptBlock = { Invoke-WebRequest -Uri $uri -Method Post -InFile $null }
ExpectedFullyQualifiedErrorId = 'ParameterArgumentValidationError,Microsoft.PowerShell.Commands.InvokeWebRequestCommand'
}
2017-12-13 09:28:05 -06:00
@ {
2018-01-09 15:43:25 -06:00
Name = 'Validate error for Invoke-WebRequest -InFile ""'
ScriptBlock = { Invoke-WebRequest -Uri $uri -Method Post -InFile "" }
2023-02-01 17:45:09 +01:00
ExpectedFullyQualifiedErrorId = 'ParameterArgumentValidationError,Microsoft.PowerShell.Commands.InvokeWebRequestCommand'
2017-12-13 09:28:05 -06:00
}
2017-02-01 10:14:24 -08:00
2017-12-13 09:28:05 -06:00
@ {
2018-01-09 15:43:25 -06:00
Name = 'Validate error for Invoke-WebRequest -InFile'
ScriptBlock = { Invoke-WebRequest -Uri $uri -Method Post -InFile }
2017-12-13 09:28:05 -06:00
ExpectedFullyQualifiedErrorId = 'MissingArgument,Microsoft.PowerShell.Commands.InvokeWebRequestCommand'
}
2017-02-01 10:14:24 -08:00
2017-12-13 09:28:05 -06:00
@ {
2023-02-01 17:45:09 +01:00
Name = "Validate error for Invoke-WebRequest -InFile $TestDrive \content.txt"
ScriptBlock = { Invoke-WebRequest -Uri $uri -Method Post -InFile $TestDrive \ content . txt }
2017-12-13 09:28:05 -06:00
ExpectedFullyQualifiedErrorId = 'PathNotFound,Microsoft.PowerShell.Commands.InvokeWebRequestCommand'
}
2023-02-01 17:45:09 +01:00
@ {
Name = "Validate error for Invoke-WebRequest -InFile $TestDrive "
ScriptBlock = { Invoke-WebRequest -Uri $uri -Method Post -InFile $TestDrive }
ExpectedFullyQualifiedErrorId = 'WebCmdletInFileNotFilePathException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand'
}
2018-01-09 15:43:25 -06:00
#endregion
2017-02-01 10:14:24 -08:00
2018-01-09 15:43:25 -06:00
#region INVOKE-RESTMETHOD
2017-12-13 09:28:05 -06:00
@ {
2023-02-01 17:45:09 +01:00
Name = "Validate error for Invoke-RestMethod -InFile null"
ScriptBlock = { Invoke-RestMethod -Uri $uri -Method Post -InFile $null }
ExpectedFullyQualifiedErrorId = 'ParameterArgumentValidationError,Microsoft.PowerShell.Commands.InvokeRestMethodCommand'
2017-12-13 09:28:05 -06:00
}
2017-02-01 10:14:24 -08:00
2017-12-13 09:28:05 -06:00
@ {
2023-02-01 17:45:09 +01:00
Name = "Validate error for Invoke-RestMethod -InFile ''"
ScriptBlock = { Invoke-RestMethod -Uri $uri -Method Post -InFile '' }
ExpectedFullyQualifiedErrorId = 'ParameterArgumentValidationError,Microsoft.PowerShell.Commands.InvokeRestMethodCommand'
}
@ {
Name = "Validate error for Invoke-RestMethod -InFile"
2018-01-09 15:43:25 -06:00
ScriptBlock = { Invoke-RestMethod -Uri $uri -Method Post -InFile }
2017-12-13 09:28:05 -06:00
ExpectedFullyQualifiedErrorId = 'MissingArgument,Microsoft.PowerShell.Commands.InvokeRestMethodCommand'
}
2017-02-01 10:14:24 -08:00
2017-12-13 09:28:05 -06:00
@ {
2023-02-01 17:45:09 +01:00
Name = "Validate error for Invoke-RestMethod -InFile $TestDrive \content.txt"
2018-01-09 15:43:25 -06:00
ScriptBlock = { Invoke-RestMethod -Uri $uri -Method Post -InFile $TestDrive \ content . txt }
2017-12-13 09:28:05 -06:00
ExpectedFullyQualifiedErrorId = 'PathNotFound,Microsoft.PowerShell.Commands.InvokeRestMethodCommand'
}
2023-02-01 17:45:09 +01:00
@ {
Name = "Validate error for Invoke-RestMethod -InFile $TestDrive "
ScriptBlock = { Invoke-RestMethod -Uri $uri -Method Post -InFile $TestDrive }
ExpectedFullyQualifiedErrorId = 'WebCmdletInFileNotFilePathException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand'
}
2018-01-09 15:43:25 -06:00
#endregion
2017-12-13 09:28:05 -06:00
)
}
2017-02-01 10:14:24 -08:00
It "<Name>" -TestCases $testCases {
param ( $scriptblock , $expectedFullyQualifiedErrorId )
2018-05-17 14:42:04 -07:00
{ & $scriptblock } | Should -Throw -ErrorId $ExpectedFullyQualifiedErrorId
2017-02-01 10:14:24 -08:00
}
}
Context "InFile parameter positive tests" {
BeforeAll {
$filePath = Join-Path $TestDrive test . txt
2017-12-13 09:28:05 -06:00
New-Item -Path $filePath -Value "hello=world" -ItemType File -Force
$uri = Get-WebListenerUrl -Test 'Post'
2017-02-01 10:14:24 -08:00
}
It "Invoke-WebRequest -InFile" {
2017-12-13 09:28:05 -06:00
$result = Invoke-WebRequest -InFile $filePath -Uri $uri -Method Post
2017-02-01 10:14:24 -08:00
$content = $result . Content | ConvertFrom-Json
2018-03-01 23:00:00 -06:00
$content . form . hello . Count | Should -Be 1
$content . form . hello [ 0 ] | Should -Match "world"
2017-02-01 10:14:24 -08:00
}
It "Invoke-RestMethod -InFile" {
2017-12-13 09:28:05 -06:00
$result = Invoke-RestMethod -InFile $filePath -Uri $uri -Method Post
2018-03-01 23:00:00 -06:00
$result . form . hello . Count | Should -Be 1
$result . form . hello [ 0 ] | Should -Match "world"
2017-02-01 10:14:24 -08:00
}
}
}
2018-12-11 14:15:33 -08:00
Describe "Web cmdlets tests using the cmdlet's aliases" -Tags "CI" , "RequireAdminOnWindows" {
2017-07-18 12:33:40 -07:00
BeforeAll {
2017-12-04 11:52:14 -06:00
$WebListener = Start-WebListener
2017-02-01 10:14:24 -08:00
}
2017-07-18 12:33:40 -07:00
It "Execute Invoke-WebRequest" {
2017-12-04 11:52:14 -06:00
$query = @ {
2018-01-09 15:43:25 -06:00
body = "hello"
contenttype = 'text/plain'
2017-12-04 11:52:14 -06:00
}
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2018-12-28 08:48:23 +00:00
$result = Invoke-WebRequest $uri
2018-03-01 23:00:00 -06:00
$result . StatusCode | Should -Be "200"
$result . Content | Should -Be "hello"
2017-02-01 10:14:24 -08:00
}
2017-07-18 12:33:40 -07:00
It "Execute Invoke-RestMethod" {
2017-12-04 11:52:14 -06:00
$query = @ {
contenttype = 'application/json'
2018-01-09 15:43:25 -06:00
body = @ { Hello = "world" } | ConvertTo-Json -Compress
2017-12-04 11:52:14 -06:00
}
2018-01-09 15:43:25 -06:00
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
2018-12-28 08:48:23 +00:00
$result = Invoke-RestMethod $uri
2018-03-01 23:00:00 -06:00
$result . Hello | Should -Be "world"
2017-02-01 10:14:24 -08:00
}
2020-01-08 01:25:30 +05:00
It "Web cmdlets ignore headers with null value" {
$query = @ {
body = "hello"
contenttype = 'text/plain'
}
$uri = Get-WebListenerUrl -Test 'Response' -Query $query
# Core throws if a header has null value.
# We ignore such headers so no exception is expected.
{ Invoke-WebRequest -Uri $uri -Headers @ { "Location" = $null } } | Should -Not -Throw
{ Invoke-WebRequest -Uri $uri -ContentType $null } | Should -Not -Throw
{ Invoke-RestMethod -Uri $uri -Headers @ { "Location" = $null } } | Should -Not -Throw
{ Invoke-RestMethod -Uri $uri -ContentType $null } | Should -Not -Throw
}
2017-02-01 10:14:24 -08:00
}
2023-04-04 09:08:35 +10:00
Describe 'Invoke-WebRequest and Invoke-RestMethod support Cancellation through CTRL-C' -Tags "CI" , "RequireAdminOnWindows" {
BeforeAll {
$oldProgress = $ProgressPreference
$ProgressPreference = 'SilentlyContinue'
$WebListener = Start-WebListener
}
AfterAll {
$ProgressPreference = $oldProgress
}
function RunWithCancellation {
param (
[ string ] $Command = 'Invoke-WebRequest' ,
[ string ] $Arguments = '' ,
[ uri ] $Uri ,
2023-04-21 02:40:01 +10:00
[ int ] $DelayBeforeStopSimulationMs = 5000 ,
2023-04-04 09:08:35 +10:00
[ switch ] $WillComplete
)
$pwsh = [ PowerShell ]:: Create ()
$invoke = " `$ result = $Command -Uri `" $Uri `" $Arguments "
$task = $pwsh . AddScript ( $invoke ). InvokeAsync ()
2023-04-21 02:40:01 +10:00
$delay = [ System.Threading.Tasks.Task ]:: Delay ( $DelayBeforeStopSimulationMs )
# Simulate CTRL-C as soon as the timeout expires or the main task ends
$null = [ System.Threading.Tasks.Task ]:: WaitAny ( $task , $delay )
2023-04-04 09:08:35 +10:00
$task . IsCompleted | Should -Be $WillComplete . ToBool ()
$pwsh . Stop ()
2023-04-21 02:40:01 +10:00
# The download stall is normally 30 seconds from the web listener based
# on the first slash separated parameter in the -TestValue provided to
# Get-WebListenerUrl -test Stall -TestValue duration/content-type.
2023-04-04 09:08:35 +10:00
Wait-UntilTrue { [ bool ]( $Task . IsCompleted ) } | Should -BeTrue
$result = $pwsh . Runspace . SessionStateProxy . GetVariable ( 'result' )
$pwsh . Dispose ()
return $result
}
It 'Invoke-WebRequest: CTRL-C Cancels request before request headers received' {
$uri = Get-WebListenerUrl -test Delay -TestValue 30
2023-04-21 02:40:01 +10:00
RunWithCancellation -Uri $uri -DelayBeforeStopSimulationMs 1000
2023-04-04 09:08:35 +10:00
}
It 'Invoke-WebRequest: CTRL-C Cancels request after request headers received' {
$uri = Get-WebListenerUrl -test Stall -TestValue '30/application%2fjson'
RunWithCancellation -Uri $uri
}
It 'Invoke-WebRequest: HTTPS CTRL-C Cancels request after request headers' {
$uri = Get-WebListenerUrl -Https -Test Stall -TestValue '30/application%2fjson'
RunWithCancellation -Uri $uri -Arguments "-SkipCertificateCheck"
}
2023-04-21 02:40:01 +10:00
It 'Invoke-WebRequest: Brotli Compression CTRL-C Cancels request after request headers' {
2023-04-04 09:08:35 +10:00
$uri = Get-WebListenerUrl -Test StallBrotli -TestValue '30/application%2fjson'
RunWithCancellation -Uri $uri
2023-04-21 02:40:01 +10:00
}
It 'Invoke-WebRequest: Gzip Compression CTRL-C Cancels request after request headers' {
2023-04-04 09:08:35 +10:00
$uri = Get-WebListenerUrl -Test StallGzip -TestValue '30/application%2fjson'
RunWithCancellation -Uri $uri
2023-04-21 02:40:01 +10:00
}
2023-06-20 08:07:16 +10:00
It 'Invoke-WebRequest: Gzip Compression CTRL-C Cancels request after request headers with Content-Length' {
$uri = Get-WebListenerUrl -Test StallGzip -TestValue '30/application%2fjson' -Query @ { contentLength = $true }
RunWithCancellation -Uri $uri
}
It 'Invoke-WebRequest: Deflate Compression CTRL-C Cancels request after request headers' {
2023-04-04 09:08:35 +10:00
$uri = Get-WebListenerUrl -Test StallDeflate -TestValue '30/application%2fjson'
RunWithCancellation -Uri $uri
}
2023-04-21 02:40:01 +10:00
It 'Invoke-WebRequest: HTTPS with Brotli compression CTRL-C Cancels request after request headers' {
2023-04-04 09:08:35 +10:00
$uri = Get-WebListenerUrl -Https -Test StallBrotli -TestValue '30/application%2fjson'
RunWithCancellation -Uri $uri -Arguments '-SkipCertificateCheck'
2023-04-21 02:40:01 +10:00
}
It 'Invoke-WebRequest: HTTPS with Gzip compression CTRL-C Cancels request after request headers' {
2023-04-04 09:08:35 +10:00
$uri = Get-WebListenerUrl -Https -Test StallGzip -TestValue '30/application%2fjson'
RunWithCancellation -Uri $uri -Arguments '-SkipCertificateCheck'
2023-04-21 02:40:01 +10:00
}
2023-06-20 08:07:16 +10:00
It 'Invoke-WebRequest: HTTPS with Deflate compression CTRL-C Cancels request after request headers' {
2023-04-04 09:08:35 +10:00
$uri = Get-WebListenerUrl -Https -Test StallDeflate -TestValue '30/application%2fjson'
RunWithCancellation -Uri $uri -Arguments '-SkipCertificateCheck'
}
It 'Invoke-WebRequest: CTRL-C Cancels file download request after request headers received' {
$uri = Get-WebListenerUrl -Test Stall -TestValue '30'
$outFile = Join-Path $TestDrive "output.txt"
2023-04-21 02:40:01 +10:00
RunWithCancellation -Uri $uri -Arguments "-OutFile $outFile "
2023-04-04 09:08:35 +10:00
# No guarantee the file will be present since the D/L is interrupted
if ( Test-Path -Path $outFile ) {
Remove-Item -Path $outFile
}
}
It 'Invoke-WebRequest: CTRL-C after stalled file download completes gives entire file' {
$uri = Get-WebListenerUrl -test Stall -TestValue '1'
$outFile = Join-Path $TestDrive "output.txt"
2023-04-21 02:40:01 +10:00
RunWithCancellation -Uri $uri -Arguments "-OutFile $outFile " -WillComplete
2023-04-04 09:08:35 +10:00
Get-content -Path $outFile | should -be 'Hello worldHello world'
Remove-Item -Path $outFile
}
It 'Invoke-RestMethod: CTRL-C Cancels request before request headers received' {
$uri = Get-WebListenerUrl -test Delay -TestValue 30
2023-04-21 02:40:01 +10:00
RunWithCancellation -Command 'Invoke-RestMethod' -Uri $uri -DelayBeforeStopSimulationMs 1000
2023-04-04 09:08:35 +10:00
}
It 'Invoke-RestMethod: CTRL-C Cancels request after JSON request headers received' {
$uri = Get-WebListenerUrl -test Stall -TestValue '30/application%2fjson'
RunWithCancellation -Command 'Invoke-RestMethod' -Uri $uri
}
It 'Invoke-RestMethod: CTRL-C after stalled JSON download processes JSON response' {
$uri = Get-WebListenerUrl -test Stall -TestValue '1/application%2fjson'
2023-04-21 02:40:01 +10:00
$result = RunWithCancellation -Command 'Invoke-RestMethod' -Uri $uri -WillComplete
2023-04-04 09:08:35 +10:00
$result . name3 | should -be 'value3'
}
It 'Invoke-RestMethod: CTRL-C Cancels request after plain request headers received' {
$uri = Get-WebListenerUrl -test Stall -TestValue '30'
RunWithCancellation -Command 'Invoke-RestMethod' -Uri $uri
}
It 'Invoke-RestMethod: CTRL-C after stalled atom feed download processes atom response' {
$uri = Get-WebListenerUrl -test Stall -TestValue '1/application%2fxml'
2023-04-21 02:40:01 +10:00
$result = RunWithCancellation -Command 'Invoke-RestMethod' -Uri $uri -WillComplete
2023-04-04 09:08:35 +10:00
$result . title | should -be 'Atom-Powered Robots Run Amok'
}
It 'Invoke-RestMethod: CTRL-C Cancels request in XML atom processing' {
$uri = Get-WebListenerUrl -test Stall -TestValue '30/application%2fxml'
RunWithCancellation -Command 'Invoke-RestMethod' -Uri $uri
}
}
2023-06-20 08:07:16 +10:00
2023-07-25 01:44:32 +02:00
Describe "Web cmdlets Unix Sockets tests" -Tags "CI" , "RequireAdminOnWindows" {
BeforeAll {
2023-08-16 11:28:59 -07:00
$isWin2016 = Test-IsWindows2016
$isWin2012 = Test-IsWinServer2012R2
$skipTests = $isWin2016 -or $isWin2012
Write-Verbose -Verbose -Message "IsWin2016: $isWin2016 - IsWin2012: $isWin2012 - SkipTests: $skipTests "
if ( $skipTests ){
return
}
try {
$unixSocket = Get-UnixSocketName -ErrorAction Stop
$WebListener = Start-UnixSocket $unixSocket -ErrorAction Stop
}
catch {
Write-Verbose -Verbose -Message "Exception: $_ "
$WebListener = $null
$skipTests = $true
}
2023-07-25 01:44:32 +02:00
}
It "Execute Invoke-WebRequest with -UnixSocket" {
2023-08-16 11:28:59 -07:00
if ( $skipTests ) {
Set-ItResult -Skipped -Because "Unix sockets are not supported on this platform."
return
}
2023-07-25 01:44:32 +02:00
$uri = Get-UnixSocketUri
$result = Invoke-WebRequest $uri -UnixSocket $unixSocket
$result . StatusCode | Should -Be "200"
$result . Content | Should -Be "Hello World Unix Socket."
}
It "Execute Invoke-RestMethod with -UnixSocket" {
2023-08-16 11:28:59 -07:00
if ( $skipTests ) {
Set-ItResult -Skipped -Because "Unix sockets are not supported on this platform."
return
}
2023-07-25 01:44:32 +02:00
$uri = Get-UnixSocketUri
$result = Invoke-RestMethod $uri -UnixSocket $unixSocket
$result | Should -Be "Hello World Unix Socket."
}
}
2023-06-20 08:07:16 +10:00
Describe 'Invoke-WebRequest and Invoke-RestMethod support OperationTimeoutSeconds' -Tags "CI" , "RequireAdminOnWindows" {
BeforeAll {
$oldProgress = $ProgressPreference
$ProgressPreference = 'SilentlyContinue'
$WebListener = Start-WebListener
}
AfterAll {
$ProgressPreference = $oldProgress
}
function RunWithNetworkTimeout {
param (
[ ValidateSet ( 'Invoke-WebRequest' , 'Invoke-RestMethod' )]
[ string ] $Command = 'Invoke-WebRequest' ,
[ string ] $Arguments = '' ,
[ uri ] $Uri ,
[ int ] $OperationTimeoutSeconds ,
[ switch ] $WillTimeout
)
$invoke = " $Command -Uri `" $Uri `" $Arguments "
if ( $PSBoundParameters . ContainsKey ( 'OperationTimeoutSeconds' )) {
$invoke = " $invoke -OperationTimeoutSeconds $OperationTimeoutSeconds "
}
$result = ExecuteWebCommand -command $invoke
if ( $WillTimeout ) {
$result . Error | Should -Not -BeNullOrEmpty
$fqErrorClass = if ( $Command -eq 'Invoke-WebRequest' ) { 'InvokeWebRequestCommand' } else { 'InvokeRestMethodCommand' }
$result . Error . FullyQualifiedErrorId | Should -Be "OperationTimeoutReached,Microsoft.PowerShell.Commands. $fqErrorClass "
$result . Output | Should -BeNullOrEmpty
} else {
$result . Error | Should -BeNullOrEmpty
$result . Output | Should -Not -BeNullOrEmpty
}
}
It 'Invoke-WebRequest: OperationTimeoutSeconds does not cancel if stalls shorter than timeout but download takes longer than timeout' {
$uri = Get-WebListenerUrl -Test Stall -TestValue '2' -Query @ { chunks = 5 }
RunWithNetworkTimeout -Uri $uri -OperationTimeoutSeconds 4
}
It 'Invoke-WebRequest: OperationTimeoutSeconds cancels if stall lasts longer than OperationTimeoutSeconds value' {
$uri = Get-WebListenerUrl -Test Stall -TestValue 30
RunWithNetworkTimeout -Uri $uri -OperationTimeoutSeconds 3 -WillTimeout
}
It 'Invoke-WebRequest: OperationTimeoutSeconds cancels if stall lasts longer than OperationTimeoutSeconds value for HTTPS/gzip compression' {
$uri = Get-WebListenerUrl -Https -Test StallGzip -TestValue 30
RunWithNetworkTimeout -Uri $uri -OperationTimeoutSeconds 3 -WillTimeout -Arguments '-SkipCertificateCheck'
}
It 'Invoke-RestMethod: OperationTimeoutSeconds does not cancel if stalls shorter than timeout but download takes longer than timeout' {
$uri = Get-WebListenerUrl -Test Stall -TestValue '2' -Query @ { chunks = 5 }
RunWithNetworkTimeout -Command Invoke-RestMethod -Uri $uri -OperationTimeoutSeconds 4
}
It 'Invoke-RestMethod: OperationTimeoutSeconds cancels if stall lasts longer than OperationTimeoutSeconds value' {
$uri = Get-WebListenerUrl -Test Stall -TestValue 30
RunWithNetworkTimeout -Command Invoke-RestMethod -Uri $uri -OperationTimeoutSeconds 2 -WillTimeout
}
It 'Invoke-RestMethod: OperationTimeoutSeconds cancels when doing XML atom processing' {
$uri = Get-WebListenerUrl -Test Stall -TestValue '30/application%2fxml'
RunWithNetworkTimeout -Command Invoke-RestMethod -Uri $uri -OperationTimeoutSeconds 2 -WillTimeout
}
It 'Invoke-RestMethod: OperationTimeoutSeconds cancels when doing JSON processing' {
$uri = Get-WebListenerUrl -Test Stall -TestValue '30/application%2fjson'
RunWithNetworkTimeout -Command Invoke-RestMethod -Uri $uri -OperationTimeoutSeconds 2 -WillTimeout
}
It 'Invoke-RestMethod: OperationTimeoutSeconds cancels when doing XML atom processing for HTTPS/gzip compression' {
$uri = Get-WebListenerUrl -Https -Test StallGzip -TestValue 30 / application % 2fXML
RunWithNetworkTimeout -Command Invoke-RestMethod -Uri $uri -OperationTimeoutSeconds 2 -WillTimeout -Arguments '-SkipCertificateCheck'
}
}
2023-11-01 15:42:28 -04:00
Describe "Invoke-RestMethod should run in the default synchronization context (threadpool)" -Tag "CI" {
BeforeAll {
$oldProgress = $ProgressPreference
$ProgressPreference = 'SilentlyContinue'
$WebListener = Start-WebListener
}
AfterAll {
$ProgressPreference = $oldProgress
}
It "Invoke-RestMethod works after constructing a WindowsForm object" -Skip: (! $IsWindows ) {
$env:URI_TO_TEST = Get-WebListenerUrl -Test 'Get'
$irmResult = $null
try {
$pwsh = Join-Path $PSHOME "pwsh"
$irmResult = & $pwsh -NoProfile {
Add-Type -AssemblyName System . Windows . Forms
$null = New-Object System . Windows . Forms . Form
Invoke-RestMethod $env:URI_TO_TEST
}
} finally {
$env:URI_TO_TEST = $null
}
# Simply making it this far is good enough to ensure we didn't hit a deadlock
$irmResult | Should -Not -BeNullOrEmpty
}
}