From 88077bd98560d9bd98291a6b9a8e9a29ced9b970 Mon Sep 17 00:00:00 2001
From: CarloToso <105941898+CarloToso@users.noreply.github.com>
Date: Wed, 14 Dec 2022 05:48:13 +0100
Subject: [PATCH] InvokeRestMethodCommand.Common cleanup and merge partials
(#18736)
---
.../Common/InvokeRestMethodCommand.Common.cs | 286 ++++++++----------
1 file changed, 133 insertions(+), 153 deletions(-)
diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs
index 3847fd9bab..9876d0a2ca 100644
--- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs
+++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs
@@ -13,7 +13,15 @@ using Newtonsoft.Json.Linq;
namespace Microsoft.PowerShell.Commands
{
- public partial class InvokeRestMethodCommand
+ ///
+ /// The Invoke-RestMethod command
+ /// This command makes an HTTP or HTTPS request to a web service,
+ /// and returns the response in an appropriate way.
+ /// Intended to work against the wide spectrum of "RESTful" web services
+ /// currently deployed across the web.
+ ///
+ [Cmdlet(VerbsLifecycle.Invoke, "RestMethod", HelpUri = "https://go.microsoft.com/fwlink/?LinkID=2096706", DefaultParameterSetName = "StandardMethod")]
+ public class InvokeRestMethodCommand : WebRequestPSCmdlet
{
#region Parameters
@@ -83,8 +91,124 @@ namespace Microsoft.PowerShell.Commands
#endregion Parameters
+ #region Virtual Method Overrides
+
+ ///
+ /// Process the web response and output corresponding objects.
+ ///
+ ///
+ internal override void ProcessResponse(HttpResponseMessage response)
+ {
+ if (response == null) { throw new ArgumentNullException(nameof(response)); }
+
+ var baseResponseStream = StreamHelper.GetResponseStream(response);
+
+ if (ShouldWriteToPipeline)
+ {
+ using var responseStream = new BufferingStreamReader(baseResponseStream);
+
+ // First see if it is an RSS / ATOM feed, in which case we can
+ // stream it - unless the user has overridden it with a return type of "XML"
+ if (TryProcessFeedStream(responseStream))
+ {
+ // Do nothing, content has been processed.
+ }
+ else
+ {
+ // determine the response type
+ RestReturnType returnType = CheckReturnType(response);
+
+ // Try to get the response encoding from the ContentType header.
+ Encoding encoding = null;
+ string charSet = response.Content.Headers.ContentType?.CharSet;
+ if (!string.IsNullOrEmpty(charSet))
+ {
+ StreamHelper.TryGetEncoding(charSet, out encoding);
+ }
+
+ object obj = null;
+ Exception ex = null;
+
+ string str = StreamHelper.DecodeStream(responseStream, ref encoding);
+
+ string encodingVerboseName;
+ try
+ {
+ encodingVerboseName = string.IsNullOrEmpty(encoding.HeaderName) ? encoding.EncodingName : encoding.HeaderName;
+ }
+ catch (NotSupportedException)
+ {
+ encodingVerboseName = encoding.EncodingName;
+ }
+
+ // NOTE: Tests use this verbose output to verify the encoding.
+ WriteVerbose(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Content encoding: {0}", encodingVerboseName));
+
+ bool convertSuccess = false;
+
+ if (returnType == RestReturnType.Json)
+ {
+ convertSuccess = TryConvertToJson(str, out obj, ref ex) || TryConvertToXml(str, out obj, ref ex);
+ }
+ // default to try xml first since it's more common
+ else
+ {
+ convertSuccess = TryConvertToXml(str, out obj, ref ex) || TryConvertToJson(str, out obj, ref ex);
+ }
+
+ if (!convertSuccess)
+ {
+ // fallback to string
+ obj = str;
+ }
+
+ WriteObject(obj);
+ }
+ }
+ else if (ShouldSaveToOutFile)
+ {
+ StreamHelper.SaveStreamToFile(baseResponseStream, QualifiedOutFile, this, response.Content.Headers.ContentLength.GetValueOrDefault(), _cancelToken.Token);
+ }
+
+ if (!string.IsNullOrEmpty(StatusCodeVariable))
+ {
+ PSVariableIntrinsics vi = SessionState.PSVariable;
+ vi.Set(StatusCodeVariable, (int)response.StatusCode);
+ }
+
+ if (!string.IsNullOrEmpty(ResponseHeadersVariable))
+ {
+ PSVariableIntrinsics vi = SessionState.PSVariable;
+ vi.Set(ResponseHeadersVariable, WebResponseHelper.GetHeadersDictionary(response));
+ }
+ }
+
+ #endregion Virtual Method Overrides
+
#region Helper Methods
+ private static RestReturnType CheckReturnType(HttpResponseMessage response)
+ {
+ if (response == null) { throw new ArgumentNullException(nameof(response)); }
+
+ RestReturnType rt = RestReturnType.Detect;
+ string contentType = ContentHelper.GetContentType(response);
+ if (string.IsNullOrEmpty(contentType))
+ {
+ rt = RestReturnType.Detect;
+ }
+ else if (ContentHelper.IsJson(contentType))
+ {
+ rt = RestReturnType.Json;
+ }
+ else if (ContentHelper.IsXml(contentType))
+ {
+ rt = RestReturnType.Xml;
+ }
+
+ return rt;
+ }
+
private bool TryProcessFeedStream(Stream responseStream)
{
bool isRssOrFeed = false;
@@ -111,7 +235,8 @@ namespace Microsoft.PowerShell.Commands
if (isRssOrFeed)
{
XmlDocument workingDocument = new();
- // performing a Read() here to avoid rrechecking
+
+ // Performing a Read() here to avoid rechecking
// "rss" or "feed" items
reader.Read();
while (!reader.EOF)
@@ -122,7 +247,7 @@ namespace Microsoft.PowerShell.Commands
string.Equals("Entry", reader.Name, StringComparison.OrdinalIgnoreCase))
)
{
- // this one will do reader.Read() internally
+ // This one will do reader.Read() internally
XmlNode result = workingDocument.ReadNode(reader);
WriteObject(result);
}
@@ -178,7 +303,7 @@ namespace Microsoft.PowerShell.Commands
doc = null;
}
- return (doc != null);
+ return doc != null;
}
private static bool TryConvertToJson(string json, out object obj, ref Exception exRef)
@@ -226,7 +351,7 @@ namespace Microsoft.PowerShell.Commands
return converted;
}
- #endregion
+ #endregion Helper Methods
///
/// Enum for rest return type.
@@ -265,20 +390,11 @@ namespace Microsoft.PowerShell.Commands
private readonly MemoryStream _streamBuffer;
private readonly byte[] _copyBuffer;
- public override bool CanRead
- {
- get { return true; }
- }
+ public override bool CanRead => true;
- public override bool CanSeek
- {
- get { return true; }
- }
+ public override bool CanSeek => true;
- public override bool CanWrite
- {
- get { return false; }
- }
+ public override bool CanWrite => false;
public override void Flush()
{
@@ -359,140 +475,4 @@ namespace Microsoft.PowerShell.Commands
}
}
}
-
- // TODO: Merge Partials
-
- ///
- /// The Invoke-RestMethod command
- /// This command makes an HTTP or HTTPS request to a web service,
- /// and returns the response in an appropriate way.
- /// Intended to work against the wide spectrum of "RESTful" web services
- /// currently deployed across the web.
- ///
- [Cmdlet(VerbsLifecycle.Invoke, "RestMethod", HelpUri = "https://go.microsoft.com/fwlink/?LinkID=2096706", DefaultParameterSetName = "StandardMethod")]
- public partial class InvokeRestMethodCommand : WebRequestPSCmdlet
- {
- #region Virtual Method Overrides
-
- ///
- /// Process the web response and output corresponding objects.
- ///
- ///
- internal override void ProcessResponse(HttpResponseMessage response)
- {
- if (response == null) { throw new ArgumentNullException(nameof(response)); }
-
- var baseResponseStream = StreamHelper.GetResponseStream(response);
-
- if (ShouldWriteToPipeline)
- {
- using var responseStream = new BufferingStreamReader(baseResponseStream);
-
- // First see if it is an RSS / ATOM feed, in which case we can
- // stream it - unless the user has overridden it with a return type of "XML"
- if (TryProcessFeedStream(responseStream))
- {
- // Do nothing, content has been processed.
- }
- else
- {
- // determine the response type
- RestReturnType returnType = CheckReturnType(response);
-
- // Try to get the response encoding from the ContentType header.
- Encoding encoding = null;
- string charSet = response.Content.Headers.ContentType?.CharSet;
- if (!string.IsNullOrEmpty(charSet))
- {
- StreamHelper.TryGetEncoding(charSet, out encoding);
- }
-
- object obj = null;
- Exception ex = null;
-
- string str = StreamHelper.DecodeStream(responseStream, ref encoding);
-
- string encodingVerboseName;
- try
- {
- encodingVerboseName = string.IsNullOrEmpty(encoding.HeaderName) ? encoding.EncodingName : encoding.HeaderName;
- }
- catch (NotSupportedException)
- {
- encodingVerboseName = encoding.EncodingName;
- }
- // NOTE: Tests use this verbose output to verify the encoding.
- WriteVerbose(string.Format
- (
- System.Globalization.CultureInfo.InvariantCulture,
- "Content encoding: {0}",
- encodingVerboseName)
- );
- bool convertSuccess = false;
-
- if (returnType == RestReturnType.Json)
- {
- convertSuccess = TryConvertToJson(str, out obj, ref ex) || TryConvertToXml(str, out obj, ref ex);
- }
- // default to try xml first since it's more common
- else
- {
- convertSuccess = TryConvertToXml(str, out obj, ref ex) || TryConvertToJson(str, out obj, ref ex);
- }
-
- if (!convertSuccess)
- {
- // fallback to string
- obj = str;
- }
-
- WriteObject(obj);
- }
- }
- else if (ShouldSaveToOutFile)
- {
- StreamHelper.SaveStreamToFile(baseResponseStream, QualifiedOutFile, this, response.Content.Headers.ContentLength.GetValueOrDefault(), _cancelToken.Token);
- }
-
- if (!string.IsNullOrEmpty(StatusCodeVariable))
- {
- PSVariableIntrinsics vi = SessionState.PSVariable;
- vi.Set(StatusCodeVariable, (int)response.StatusCode);
- }
-
- if (!string.IsNullOrEmpty(ResponseHeadersVariable))
- {
- PSVariableIntrinsics vi = SessionState.PSVariable;
- vi.Set(ResponseHeadersVariable, WebResponseHelper.GetHeadersDictionary(response));
- }
- }
-
- #endregion Virtual Method Overrides
-
- #region Helper Methods
-
- private static RestReturnType CheckReturnType(HttpResponseMessage response)
- {
- if (response == null) { throw new ArgumentNullException(nameof(response)); }
-
- RestReturnType rt = RestReturnType.Detect;
- string contentType = ContentHelper.GetContentType(response);
- if (string.IsNullOrEmpty(contentType))
- {
- rt = RestReturnType.Detect;
- }
- else if (ContentHelper.IsJson(contentType))
- {
- rt = RestReturnType.Json;
- }
- else if (ContentHelper.IsXml(contentType))
- {
- rt = RestReturnType.Xml;
- }
-
- return (rt);
- }
-
- #endregion Helper Methods
- }
}