Add -SkipHeaderValidation Support to ContentType on Web Cmdlets (#6018)

* Add SkipHeaderValidation Support to ContentType on Web Cmdlets

* Move -SkipHeaderValidation Tests to Contexts

* Add ContentType -SkipHeaderValidation Tests

* Improve ContentType Exception

* Improve error message on invalid -ContentType
This commit is contained in:
Mark Kraus 2018-02-22 13:15:05 -06:00 committed by Aditya Patwardhan
parent 93a5fed375
commit 11d2e2dfd4
3 changed files with 286 additions and 122 deletions

View file

@ -1172,9 +1172,25 @@ namespace Microsoft.PowerShell.Commands
if (request.Content != null)
{
foreach (var entry in WebSession.ContentHeaders)
{
if (SkipHeaderValidation)
{
request.Content.Headers.TryAddWithoutValidation(entry.Key, entry.Value);
}
else
{
try
{
request.Content.Headers.Add(entry.Key, entry.Value);
}
catch (FormatException ex)
{
var outerEx = new ValidationMetadataException(WebCmdletStrings.ContentTypeException, ex);
ErrorRecord er = new ErrorRecord(outerEx, "WebCmdletContentTypeException", ErrorCategory.InvalidArgument, ContentType);
ThrowTerminatingError(er);
}
}
}
}
}
@ -1473,16 +1489,29 @@ namespace Microsoft.PowerShell.Commands
// If Content-Type contains the encoding format (as CharSet), use this encoding format
// to encode the Body of the WebRequest sent to the server. Default Encoding format
// would be used if Charset is not supplied in the Content-Type property.
try
{
var mediaTypeHeaderValue = new MediaTypeHeaderValue(ContentType);
if (!string.IsNullOrEmpty(mediaTypeHeaderValue.CharSet))
{
try
{
encoding = Encoding.GetEncoding(mediaTypeHeaderValue.CharSet);
}
}
catch (FormatException ex)
{
if (!SkipHeaderValidation)
{
var outerEx = new ValidationMetadataException(WebCmdletStrings.ContentTypeException, ex);
ErrorRecord er = new ErrorRecord(outerEx, "WebCmdletContentTypeException", ErrorCategory.InvalidArgument, ContentType);
ThrowTerminatingError(er);
}
}
catch (ArgumentException ex)
{
ErrorRecord er = new ErrorRecord(ex, "WebCmdletEncodingException", ErrorCategory.InvalidArgument, ContentType);
if (!SkipHeaderValidation)
{
var outerEx = new ValidationMetadataException(WebCmdletStrings.ContentTypeException, ex);
ErrorRecord er = new ErrorRecord(outerEx, "WebCmdletContentTypeException", ErrorCategory.InvalidArgument, ContentType);
ThrowTerminatingError(er);
}
}

View file

@ -144,6 +144,9 @@
<data name="FormInFileConflict" xml:space="preserve">
<value>The cmdlet cannot run because the following conflicting parameters are specified: InFile and Form. Specify either InFile or Form, then retry. </value>
</data>
<data name="ContentTypeException" xml:space="preserve">
<value>The cmdlet cannot run because the -ContentType parameter is not a valid Content-Type header. Specify a valid Content-Type for -ContentType, then retry. To suppress header validation, supply the -SkipHeaderValidation parameter.</value>
</data>
<data name="CredentialConflict" xml:space="preserve">
<value>The cmdlet cannot run because the following conflicting parameters are specified: Credential and UseDefaultCredentials. Specify either Credential or UseDefaultCredentials, then retry.</value>
</data>

View file

@ -800,7 +800,11 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" {
#endregion Redirect tests
#region SkipHeaderVerification Tests
Context "Invoke-WebRequest SkipHeaderVerification Tests" {
BeforeAll {
$Testfile = Join-Path $testdrive 'SkipHeaderVerification.txt'
'bar' | Set-Content $Testfile
}
It "Verifies Invoke-WebRequest default header handling with no errors" {
$uri = Get-WebListenerUrl -Test 'Get'
@ -860,7 +864,71 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" {
$response.Content.Headers."User-Agent" | Should Match $Pattern
}
#endregion SkipHeaderVerification Tests
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
$result.data | Should BeExactly $body
$result.headers.'Content-Type' | Should BeExactly $contentType
}
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' } |
ShouldBeErrorId "WebCmdletContentTypeException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
}
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
$result.data | Should BeExactly 'bar'
$result.headers.'Content-Type' | Should BeExactly $contentType
}
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
$result.data | Should Match 'bar'
$result.headers.'Content-Type' | Should BeExactly $contentType
}
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' } |
ShouldBeErrorId "WebCmdletContentTypeException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
}
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
$result.data | Should Match 'bar'
$result.headers.'Content-Type' | Should BeExactly $contentType
}
}
#region charset encoding tests
@ -1937,7 +2005,11 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" {
#endregion Redirect tests
#region SkipHeaderVerification tests
Context "Invoke-RestMethod SkipHeaderVerification Tests" {
BeforeAll {
$Testfile = Join-Path $testdrive 'SkipHeaderVerification.txt'
'bar' | Set-Content $Testfile
}
It "Verifies Invoke-RestMethod default header handling with no errors" {
$uri = Get-WebListenerUrl -Test 'Get'
@ -1997,7 +2069,67 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" {
$response.Content.Headers."User-Agent" | Should Match $Pattern
}
#endregion SkipHeaderVerification tests
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
$result.data | Should BeExactly $body
$result.headers.'Content-Type' | Should BeExactly $contentType
}
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' } |
ShouldBeErrorId "WebCmdletContentTypeException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
}
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
$result.data | Should BeExactly $body
$result.headers.'Content-Type' | Should BeExactly $contentType
}
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
$result.data | Should Match 'bar'
$result.headers.'Content-Type' | Should BeExactly $contentType
}
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' } |
ShouldBeErrorId "WebCmdletContentTypeException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
}
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
$result.data | Should Match 'bar'
$result.headers.'Content-Type' | Should BeExactly $contentType
}
}
Context "HTTPS Tests" {
It "Validate Invoke-RestMethod -SkipCertificateCheck" {