Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Http;

namespace Microsoft.PowerShell.Commands
{
Expand Down Expand Up @@ -244,4 +245,48 @@ protected void InitializeContent()

#endregion Methods
}

// TODO: Merge Partials

// <summary>
/// Response object for html content without DOM parsing
/// </summary>
public partial class BasicHtmlWebResponseObject : WebResponseObject
{
#region Constructors

/// <summary>
/// Constructor for BasicHtmlWebResponseObject
/// </summary>
/// <param name="response"></param>
public BasicHtmlWebResponseObject(HttpResponseMessage response)
: this(response, null)
{ }

/// <summary>
/// Constructor for HtmlWebResponseObject with memory stream
/// </summary>
/// <param name="response"></param>
/// <param name="contentStream"></param>
public BasicHtmlWebResponseObject(HttpResponseMessage response, Stream contentStream)
: base(response, contentStream)
{
EnsureHtmlParser();
InitializeContent();
InitializeRawContent(response);
}

#endregion Constructors

#region Methods

private void InitializeRawContent(HttpResponseMessage baseResponse)
{
StringBuilder raw = ContentHelper.GetRawContentHeader(baseResponse);
raw.Append(Content);
this.RawContent = raw.ToString();
}

#endregion Methods
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
using System.Management.Automation;
using System.Text;
using Microsoft.Win32;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;

namespace Microsoft.PowerShell.Commands
{
Expand Down Expand Up @@ -150,4 +153,64 @@ private static bool CheckIsJson(string contentType)

#endregion Internal Helper Methods
}

// TODO: merge Partials

internal static partial class ContentHelper
{
internal static Encoding GetEncoding(HttpResponseMessage response)
{
// ContentType may not exist in response header.
string charSet = response.Content.Headers.ContentType?.CharSet;
return GetEncodingOrDefault(charSet);
}

internal static string GetContentType(HttpResponseMessage response)
{
// ContentType may not exist in response header. Return null if not.
return response.Content.Headers.ContentType?.MediaType;
}

internal static StringBuilder GetRawContentHeader(HttpResponseMessage response)
{
StringBuilder raw = new StringBuilder();

string protocol = WebResponseHelper.GetProtocol(response);
if (!string.IsNullOrEmpty(protocol))
{
int statusCode = WebResponseHelper.GetStatusCode(response);
string statusDescription = WebResponseHelper.GetStatusDescription(response);
raw.AppendFormat("{0} {1} {2}", protocol, statusCode, statusDescription);
raw.AppendLine();
}

HttpHeaders[] headerCollections =
{
response.Headers,
response.Content == null ? null : response.Content.Headers
};

foreach (var headerCollection in headerCollections)
{
if (headerCollection == null)
{
continue;
}
foreach (var header in headerCollection)
{
// Headers may have multiple entries with different values
foreach (var headerValue in header.Value)
{
raw.Append(header.Key);
raw.Append(": ");
raw.Append(headerValue);
raw.AppendLine();
}
}
}

raw.AppendLine();
return raw;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
using System.Xml;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Net.Http;
using System.Text;

namespace Microsoft.PowerShell.Commands
{
Expand Down Expand Up @@ -343,4 +345,126 @@ public override void Write(byte[] buffer, int offset, int count)
}
}
}
}

// TODO: Merge Partials

/// <summary>
/// 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.
/// </summary>
[Cmdlet(VerbsLifecycle.Invoke, "RestMethod", HelpUri = "https://go.microsoft.com/fwlink/?LinkID=217034", DefaultParameterSetName = "StandardMethod")]
public partial class InvokeRestMethodCommand : WebRequestPSCmdlet
{
#region Virtual Method Overrides

/// <summary>
/// Process the web response and output corresponding objects.
/// </summary>
/// <param name="response"></param>
internal override void ProcessResponse(HttpResponseMessage response)
{
if (null == response) { throw new ArgumentNullException("response"); }

using (BufferingStreamReader responseStream = new BufferingStreamReader(StreamHelper.GetResponseStream(response)))
{
if (ShouldWriteToPipeline)
{
// 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))
{
// NOTE: Don't use ContentHelper.GetEncoding; it returns a
// default which bypasses checking for a meta charset value.
StreamHelper.TryGetEncoding(charSet, out encoding);
}

object obj = null;
Exception ex = null;

string str = StreamHelper.DecodeStream(responseStream, ref encoding);
// NOTE: Tests use this verbose output to verify the encoding.
WriteVerbose(string.Format
(
System.Globalization.CultureInfo.InvariantCulture,
"Content encoding: {0}",
string.IsNullOrEmpty(encoding.HeaderName) ? encoding.EncodingName : encoding.HeaderName)
);
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);
}
}

if (ShouldSaveToOutFile)
{
StreamHelper.SaveStreamToFile(responseStream, QualifiedOutFile, this);
}

if (!String.IsNullOrEmpty(ResponseHeadersVariable))
{
PSVariableIntrinsics vi = SessionState.PSVariable;
vi.Set(ResponseHeadersVariable, WebResponseHelper.GetHeadersDictionary(response));
}
}
}

#endregion Virtual Method Overrides

#region Helper Methods

private RestReturnType CheckReturnType(HttpResponseMessage response)
{
if (null == response) { throw new ArgumentNullException("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
}
}
Loading