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 @@ -15,11 +15,8 @@ internal static class ContentHelper
{
#region Internal Methods

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

internal static Encoding GetDefaultEncoding() => Encoding.UTF8;

Expand All @@ -32,8 +29,7 @@ internal static StringBuilder GetRawContentHeader(HttpResponseMessage response)
{
int statusCode = WebResponseHelper.GetStatusCode(response);
string statusDescription = WebResponseHelper.GetStatusDescription(response);
raw.Append($"{protocol} {statusCode} {statusDescription}");
raw.AppendLine();
raw.AppendLine($"{protocol} {statusCode} {statusDescription}");
}

HttpHeaders[] headerCollections =
Expand All @@ -52,12 +48,9 @@ internal static StringBuilder GetRawContentHeader(HttpResponseMessage response)
foreach (var header in headerCollection)
{
// Headers may have multiple entries with different values
foreach (var headerValue in header.Value)
foreach (string headerValue in header.Value)
{
raw.Append(header.Key);
raw.Append(": ");
raw.Append(headerValue);
raw.AppendLine();
raw.AppendLine($"{header.Key}: {headerValue}");
}
}
}
Expand Down Expand Up @@ -101,10 +94,10 @@ private static bool CheckIsJson(string contentType)
// Add in these other "javascript" related types that
// sometimes get sent down as the mime type for JSON content
isJson |= contentType.Equals("text/json", StringComparison.OrdinalIgnoreCase)
|| contentType.Equals("application/x-javascript", StringComparison.OrdinalIgnoreCase)
|| contentType.Equals("text/x-javascript", StringComparison.OrdinalIgnoreCase)
|| contentType.Equals("application/javascript", StringComparison.OrdinalIgnoreCase)
|| contentType.Equals("text/javascript", StringComparison.OrdinalIgnoreCase);
|| contentType.Equals("application/x-javascript", StringComparison.OrdinalIgnoreCase)
|| contentType.Equals("text/x-javascript", StringComparison.OrdinalIgnoreCase)
|| contentType.Equals("application/javascript", StringComparison.OrdinalIgnoreCase)
|| contentType.Equals("text/javascript", StringComparison.OrdinalIgnoreCase);

return isJson;
}
Expand All @@ -118,8 +111,8 @@ private static bool CheckIsText(string contentType)

// Any text, xml or json types are text
bool isText = contentType.StartsWith("text/", StringComparison.OrdinalIgnoreCase)
|| CheckIsXml(contentType)
|| CheckIsJson(contentType);
|| CheckIsXml(contentType)
|| CheckIsJson(contentType);

// Further content type analysis is available on Windows
if (Platform.IsWindows && !isText)
Expand Down Expand Up @@ -156,11 +149,11 @@ private static bool CheckIsXml(string contentType)
}

// RFC 3023: Media types with the suffix "+xml" are XML
bool isXml = (contentType.Equals("application/xml", StringComparison.OrdinalIgnoreCase)
|| contentType.Equals("application/xml-external-parsed-entity", StringComparison.OrdinalIgnoreCase)
|| contentType.Equals("application/xml-dtd", StringComparison.OrdinalIgnoreCase));

isXml |= contentType.EndsWith("+xml", StringComparison.OrdinalIgnoreCase);
bool isXml = contentType.Equals("application/xml", StringComparison.OrdinalIgnoreCase)
|| contentType.Equals("application/xml-external-parsed-entity", StringComparison.OrdinalIgnoreCase)
|| contentType.Equals("application/xml-dtd", StringComparison.OrdinalIgnoreCase)
|| contentType.EndsWith("+xml", StringComparison.OrdinalIgnoreCase);

return isXml;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public abstract partial class WebRequestPSCmdlet : PSCmdlet
[ValidateNotNullOrEmpty]
public virtual Uri Uri { get; set; }

#endregion
#endregion URI

#region HTTP Version

Expand All @@ -117,7 +117,7 @@ public abstract partial class WebRequestPSCmdlet : PSCmdlet
[HttpVersionCompletions]
public virtual Version HttpVersion { get; set; }

#endregion
#endregion HTTP Version

#region Session
/// <summary>
Expand All @@ -133,7 +133,7 @@ public abstract partial class WebRequestPSCmdlet : PSCmdlet
[Alias("SV")]
public virtual string SessionVariable { get; set; }

#endregion
#endregion Session

#region Authorization and Credentials

Expand Down Expand Up @@ -198,13 +198,7 @@ public abstract partial class WebRequestPSCmdlet : PSCmdlet
[Parameter]
public virtual SecureString Token { get; set; }

/// <summary>
/// Gets or sets the AllowInsecureRedirect property used to follow HTTP redirects from HTTPS.
/// </summary>
[Parameter]
public virtual SwitchParameter AllowInsecureRedirect { get; set; }

#endregion
#endregion Authorization and Credentials

#region Headers

Expand Down Expand Up @@ -234,10 +228,25 @@ public abstract partial class WebRequestPSCmdlet : PSCmdlet
[Parameter]
public virtual IDictionary Headers { get; set; }

#endregion
/// <summary>
/// Gets or sets the SkipHeaderValidation property.
/// </summary>
/// <remarks>
/// This property adds headers to the request's header collection without validation.
/// </remarks>
[Parameter]
public virtual SwitchParameter SkipHeaderValidation { get; set; }

#endregion Headers

#region Redirect

/// <summary>
/// Gets or sets the AllowInsecureRedirect property used to follow HTTP redirects from HTTPS.
/// </summary>
[Parameter]
public virtual SwitchParameter AllowInsecureRedirect { get; set; }

/// <summary>
/// Gets or sets the RedirectMax property.
/// </summary>
Expand All @@ -252,14 +261,29 @@ public abstract partial class WebRequestPSCmdlet : PSCmdlet
[ValidateRange(0, int.MaxValue)]
public virtual int MaximumRetryCount { get; set; }

/// <summary>
/// Gets or sets the PreserveAuthorizationOnRedirect property.
/// </summary>
/// <remarks>
/// This property overrides compatibility with web requests on Windows.
/// On FullCLR (WebRequest), authorization headers are stripped during redirect.
/// CoreCLR (HTTPClient) does not have this behavior so web requests that work on
/// PowerShell/FullCLR can fail with PowerShell/CoreCLR. To provide compatibility,
/// we'll detect requests with an Authorization header and automatically strip
/// the header when the first redirect occurs. This switch turns off this logic for
/// edge cases where the authorization header needs to be preserved across redirects.
/// </remarks>
[Parameter]
public virtual SwitchParameter PreserveAuthorizationOnRedirect { get; set; }

/// <summary>
/// Gets or sets the RetryIntervalSec property, which determines the number seconds between retries.
/// </summary>
[Parameter]
[ValidateRange(1, int.MaxValue)]
public virtual int RetryIntervalSec { get; set; } = 5;

#endregion
#endregion Redirect

#region Method

Expand All @@ -286,7 +310,7 @@ public virtual string CustomMethod

private string _custommethod;

#endregion
#endregion Method

#region NoProxy

Expand All @@ -297,7 +321,7 @@ public virtual string CustomMethod
[Parameter(Mandatory = true, ParameterSetName = "StandardMethodNoProxy")]
public virtual SwitchParameter NoProxy { get; set; }

#endregion
#endregion NoProxy

#region Proxy

Expand All @@ -323,7 +347,7 @@ public virtual string CustomMethod
[Parameter(ParameterSetName = "CustomMethod")]
public virtual SwitchParameter ProxyUseDefaultCredentials { get; set; }

#endregion
#endregion Proxy

#region Input

Expand Down Expand Up @@ -365,7 +389,7 @@ public virtual string CustomMethod
/// </summary>
private string _originalFilePath;

#endregion
#endregion Input

#region Output

Expand Down Expand Up @@ -393,7 +417,7 @@ public virtual string CustomMethod
[Parameter]
public virtual SwitchParameter SkipHttpErrorCheck { get; set; }

#endregion
#endregion Output

#endregion Virtual Properties

Expand Down Expand Up @@ -825,30 +849,6 @@ public HttpResponseException(string message, HttpResponseMessage response) : bas
/// </summary>
public abstract partial class WebRequestPSCmdlet : PSCmdlet
{
/// <summary>
/// Gets or sets the PreserveAuthorizationOnRedirect property.
/// </summary>
/// <remarks>
/// This property overrides compatibility with web requests on Windows.
/// On FullCLR (WebRequest), authorization headers are stripped during redirect.
/// CoreCLR (HTTPClient) does not have this behavior so web requests that work on
/// PowerShell/FullCLR can fail with PowerShell/CoreCLR. To provide compatibility,
/// we'll detect requests with an Authorization header and automatically strip
/// the header when the first redirect occurs. This switch turns off this logic for
/// edge cases where the authorization header needs to be preserved across redirects.
/// </remarks>
[Parameter]
public virtual SwitchParameter PreserveAuthorizationOnRedirect { get; set; }

/// <summary>
/// Gets or sets the SkipHeaderValidation property.
/// </summary>
/// <remarks>
/// This property adds headers to the request's header collection without validation.
/// </remarks>
[Parameter]
public virtual SwitchParameter SkipHeaderValidation { get; set; }

#region Abstract Methods

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ internal static Dictionary<string, IEnumerable<string>> GetHeadersDictionary(Htt
internal static bool IsText(HttpResponseMessage response)
{
// ContentType may not exist in response header.
string contentType = response.Content.Headers.ContentType?.MediaType;
string contentType = ContentHelper.GetContentType(response);
return ContentHelper.IsText(contentType);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,7 @@ internal static class WebResponseObjectFactory
{
internal static WebResponseObject GetResponseObject(HttpResponseMessage response, Stream responseStream, ExecutionContext executionContext)
{
WebResponseObject output;
if (WebResponseHelper.IsText(response))
{
output = new BasicHtmlWebResponseObject(response, responseStream);
}
else
{
output = new WebResponseObject(response, responseStream);
}
WebResponseObject output = WebResponseHelper.IsText(response) ? new BasicHtmlWebResponseObject(response, responseStream) : new WebResponseObject(response, responseStream);

return output;
}
Expand Down