Skip to content

Commit 89a5c17

Browse files
Francisco-Gaminodaxian-dbw
authored andcommitted
Fixing 'InFile parameter of Invoke-WebRequest doesn't work' and adding aliases (iwr for invoke-webrequest and irm for invoke-restmethod) to the web cmdlets. (PowerShell#2848)
* Fixing Invoke-WebRequest InFile parameter * Adding aliases for Invoke-RestMethod and Invoke-WebRequest * Adding test cases for Web cmdlets -InFile parameter * Adding tests for Invoke-WebRequest (iwr) and Invoke-RestMethod (irm) using the cmdlet aliases. * Remove the extra leading space
1 parent 1431105 commit 89a5c17

File tree

3 files changed

+175
-51
lines changed

3 files changed

+175
-51
lines changed

src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/CoreCLR/WebRequestPSCmdlet.CoreClr.cs

+46-47
Original file line numberDiff line numberDiff line change
@@ -280,10 +280,7 @@ internal virtual void FillRequestStream(HttpRequestMessage request)
280280
try
281281
{
282282
// open the input file
283-
using (FileStream fs = new FileStream(InFile, FileMode.Open))
284-
{
285-
SetRequestContent(request, fs);
286-
}
283+
SetRequestContent(request, new FileStream(InFile, FileMode.Open));
287284
}
288285
catch (UnauthorizedAccessException)
289286
{
@@ -331,55 +328,57 @@ protected override void ProcessRecord()
331328
// Set cmdlet context for write progress
332329
ValidateParameters();
333330
PrepareSession();
334-
HttpClient client = GetHttpClient();
335-
HttpRequestMessage request = GetRequest(Uri);
336-
FillRequestStream(request);
337331

338-
try
332+
using (HttpClient client = GetHttpClient())
333+
using (HttpRequestMessage request = GetRequest(Uri))
339334
{
340-
long requestContentLength = 0;
341-
if (request.Content != null)
342-
requestContentLength = request.Content.Headers.ContentLength.Value;
343-
344-
string reqVerboseMsg = String.Format(CultureInfo.CurrentCulture,
345-
"{0} {1} with {2}-byte payload",
346-
request.Method,
347-
request.RequestUri,
348-
requestContentLength);
349-
WriteVerbose(reqVerboseMsg);
350-
351-
HttpResponseMessage response = GetResponse(client, request);
352-
response.EnsureSuccessStatusCode();
353-
354-
string contentType = ContentHelper.GetContentType(response);
355-
string respVerboseMsg = string.Format(CultureInfo.CurrentCulture,
356-
"received {0}-byte response of content type {1}",
357-
response.Content.Headers.ContentLength,
358-
contentType);
359-
WriteVerbose(respVerboseMsg);
360-
ProcessResponse(response);
361-
UpdateSession(response);
362-
363-
// If we hit our maximum redirection count, generate an error.
364-
// Errors with redirection counts of greater than 0 are handled automatically by .NET, but are
365-
// impossible to detect programmatically when we hit this limit. By handling this ourselves
366-
// (and still writing out the result), users can debug actual HTTP redirect problems.
367-
if (WebSession.MaximumRedirection == 0) // Indicate "HttpClientHandler.AllowAutoRedirect == false"
335+
FillRequestStream(request);
336+
try
368337
{
369-
if (response.StatusCode == HttpStatusCode.Found ||
370-
response.StatusCode == HttpStatusCode.Moved ||
371-
response.StatusCode == HttpStatusCode.MovedPermanently)
338+
long requestContentLength = 0;
339+
if (request.Content != null)
340+
requestContentLength = request.Content.Headers.ContentLength.Value;
341+
342+
string reqVerboseMsg = String.Format(CultureInfo.CurrentCulture,
343+
"{0} {1} with {2}-byte payload",
344+
request.Method,
345+
request.RequestUri,
346+
requestContentLength);
347+
WriteVerbose(reqVerboseMsg);
348+
349+
HttpResponseMessage response = GetResponse(client, request);
350+
response.EnsureSuccessStatusCode();
351+
352+
string contentType = ContentHelper.GetContentType(response);
353+
string respVerboseMsg = string.Format(CultureInfo.CurrentCulture,
354+
"received {0}-byte response of content type {1}",
355+
response.Content.Headers.ContentLength,
356+
contentType);
357+
WriteVerbose(respVerboseMsg);
358+
ProcessResponse(response);
359+
UpdateSession(response);
360+
361+
// If we hit our maximum redirection count, generate an error.
362+
// Errors with redirection counts of greater than 0 are handled automatically by .NET, but are
363+
// impossible to detect programmatically when we hit this limit. By handling this ourselves
364+
// (and still writing out the result), users can debug actual HTTP redirect problems.
365+
if (WebSession.MaximumRedirection == 0) // Indicate "HttpClientHandler.AllowAutoRedirect == false"
372366
{
373-
ErrorRecord er = new ErrorRecord(new InvalidOperationException(), "MaximumRedirectExceeded", ErrorCategory.InvalidOperation, request);
374-
er.ErrorDetails = new ErrorDetails(WebCmdletStrings.MaximumRedirectionCountExceeded);
375-
WriteError(er);
367+
if (response.StatusCode == HttpStatusCode.Found ||
368+
response.StatusCode == HttpStatusCode.Moved ||
369+
response.StatusCode == HttpStatusCode.MovedPermanently)
370+
{
371+
ErrorRecord er = new ErrorRecord(new InvalidOperationException(), "MaximumRedirectExceeded", ErrorCategory.InvalidOperation, request);
372+
er.ErrorDetails = new ErrorDetails(WebCmdletStrings.MaximumRedirectionCountExceeded);
373+
WriteError(er);
374+
}
376375
}
377376
}
378-
}
379-
catch (HttpRequestException ex)
380-
{
381-
ErrorRecord er = new ErrorRecord(ex, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, request);
382-
ThrowTerminatingError(er);
377+
catch (HttpRequestException ex)
378+
{
379+
ErrorRecord er = new ErrorRecord(ex, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, request);
380+
ThrowTerminatingError(er);
381+
}
383382
}
384383
}
385384
catch (CryptographicException ex)

src/System.Management.Automation/engine/InitialSessionState.cs

+5-4
Original file line numberDiff line numberDiff line change
@@ -5108,6 +5108,11 @@ internal static SessionStateAliasEntry[] BuiltInAliases
51085108
"Stop-Service", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope),
51095109
new SessionStateAliasEntry("sv",
51105110
"Set-Variable", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope),
5111+
// Web cmdlets aliases
5112+
new SessionStateAliasEntry("irm",
5113+
"Invoke-RestMethod", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope),
5114+
new SessionStateAliasEntry("iwr",
5115+
"Invoke-WebRequest", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope),
51115116
// Porting note: #if !UNIX is used to disable aliases for cmdlets which conflict with Linux / OS X
51125117
#if !UNIX
51135118
// ac is a native command on OS X
@@ -5175,10 +5180,6 @@ internal static SessionStateAliasEntry[] BuiltInAliases
51755180
"Get-PSSnapIn", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope),
51765181
new SessionStateAliasEntry("gwmi",
51775182
"Get-WmiObject", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope),
5178-
new SessionStateAliasEntry("irm",
5179-
"Invoke-RestMethod", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope),
5180-
new SessionStateAliasEntry("iwr",
5181-
"Invoke-WebRequest", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope),
51825183
new SessionStateAliasEntry("iwmi",
51835184
"Invoke-WMIMethod", "", ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope),
51845185
new SessionStateAliasEntry("ogv",

test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1

+124
Original file line numberDiff line numberDiff line change
@@ -643,3 +643,127 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" {
643643
$result.Error | Should BeNullOrEmpty
644644
}
645645
}
646+
647+
Describe "Validate Invoke-WebRequest and Invoke-RestMethod -InFile" -Tags "Feature" {
648+
649+
Context "InFile parameter negative tests" {
650+
651+
$testCases = @(
652+
#region INVOKE-WEBREQUEST
653+
@{
654+
Name = 'Validate error for Invoke-WebRequest -InFile ""'
655+
ScriptBlock = {Invoke-WebRequest -Uri http://httpbin.org/post -Method Post -InFile ""}
656+
ExpectedFullyQualifiedErrorId = 'WebCmdletInFileNotFilePathException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand'
657+
}
658+
659+
@{
660+
Name = 'Validate error for Invoke-WebRequest -InFile'
661+
ScriptBlock = {Invoke-WebRequest -Uri http://httpbin.org/post -Method Post -InFile}
662+
ExpectedFullyQualifiedErrorId = 'MissingArgument,Microsoft.PowerShell.Commands.InvokeWebRequestCommand'
663+
}
664+
665+
@{
666+
Name = "Validate error for Invoke-WebRequest -InFile $TestDrive\content.txt"
667+
ScriptBlock = {Invoke-WebRequest -Uri http://httpbin.org/post -Method Post -InFile $TestDrive\content.txt}
668+
ExpectedFullyQualifiedErrorId = 'PathNotFound,Microsoft.PowerShell.Commands.InvokeWebRequestCommand'
669+
}
670+
#endregion
671+
672+
#region INVOKE-RESTMETHOD
673+
@{
674+
Name = "Validate error for Invoke-RestMethod -InFile ''"
675+
ScriptBlock = {Invoke-RestMethod -Uri http://httpbin.org/post -Method Post -InFile ''}
676+
ExpectedFullyQualifiedErrorId = 'WebCmdletInFileNotFilePathException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand'
677+
}
678+
679+
@{
680+
Name = "Validate error for Invoke-RestMethod -InFile <null>"
681+
ScriptBlock = {Invoke-RestMethod -Uri http://httpbin.org/post -Method Post -InFile}
682+
ExpectedFullyQualifiedErrorId = 'MissingArgument,Microsoft.PowerShell.Commands.InvokeRestMethodCommand'
683+
}
684+
685+
@{
686+
Name = "Validate error for Invoke-RestMethod -InFile $TestDrive\content.txt"
687+
ScriptBlock = {Invoke-RestMethod -Uri http://httpbin.org/post -Method Post -InFile $TestDrive\content.txt}
688+
ExpectedFullyQualifiedErrorId = 'PathNotFound,Microsoft.PowerShell.Commands.InvokeRestMethodCommand'
689+
}
690+
#endregion
691+
)
692+
693+
It "<Name>" -TestCases $testCases {
694+
param ($scriptblock, $expectedFullyQualifiedErrorId)
695+
696+
try
697+
{
698+
& $scriptblock
699+
throw "No Exception!"
700+
}
701+
catch
702+
{
703+
$_.FullyQualifiedErrorId | should be $ExpectedFullyQualifiedErrorId
704+
}
705+
}
706+
}
707+
708+
Context "InFile parameter positive tests" {
709+
710+
BeforeAll {
711+
$filePath = Join-Path $TestDrive test.txt
712+
New-Item -Path $filePath -Value "hello" -ItemType File -Force
713+
}
714+
715+
It "Invoke-WebRequest -InFile" {
716+
$result = Invoke-WebRequest -InFile $filePath -Uri http://httpbin.org/post -Method Post
717+
$content = $result.Content | ConvertFrom-Json
718+
$content.form | Should Match "hello"
719+
}
720+
721+
It "Invoke-RestMethod -InFile" {
722+
$result = Invoke-RestMethod -InFile $filePath -Uri http://httpbin.org/post -Method Post
723+
$result.form | Should Match "hello"
724+
}
725+
}
726+
}
727+
728+
Describe "Web cmdlets tests using the cmdlet's aliases" -Tags "CI" {
729+
730+
function SearchEngineIsOnline
731+
{
732+
param (
733+
[ValidateNotNullOrEmpty()]
734+
$webAddress
735+
)
736+
$ping = new-object System.Net.NetworkInformation.Ping
737+
$sendPing = $ping.SendPingAsync($webAddress)
738+
return ($sendPing.Result.Status -eq "Success")
739+
}
740+
741+
# Make sure either www.bing.com or www.google.com are online to send a request.
742+
$endPointToUse = $null
743+
foreach ($uri in @("www.bing.com", "www.google.com"))
744+
{
745+
if (SearchEngineIsOnline $uri)
746+
{
747+
$endPointToUse = $uri
748+
break
749+
}
750+
}
751+
752+
# If neither www.bing.com nor www.google.com are online, then skip the tests.
753+
$skipTests = ($endPointToUse -eq $null)
754+
$finalUri = $endPointToUse + "?q=how+many+feet+in+a+mile"
755+
756+
It "Execute Invoke-WebRequest --> 'iwr -URI $finalUri'" -Skip:$skipTests {
757+
$result = iwr -URI $finalUri -TimeoutSec 5
758+
$result.StatusCode | Should Be "200"
759+
$result.Links | Should Not Be $null
760+
}
761+
762+
It "Execute Invoke-RestMethod --> 'irm -URI $finalUri'" -Skip:$skipTests {
763+
$result = irm -URI $finalUri -TimeoutSec 5
764+
foreach ($word in @("200", "how", "many", "feet", "in", "mile"))
765+
{
766+
$result | Should Match $word
767+
}
768+
}
769+
}

0 commit comments

Comments
 (0)