Skip to content

Commit

Permalink
#553 drop GetHeaderValue, move some code around
Browse files Browse the repository at this point in the history
  • Loading branch information
tmenier committed Sep 25, 2020
1 parent 41b1bc8 commit 77b29c4
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 174 deletions.
10 changes: 9 additions & 1 deletion src/Flurl.Http/FlurlResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Threading;
using System.Threading.Tasks;
using Flurl.Http.Configuration;
using Flurl.Util;

namespace Flurl.Http
{
Expand Down Expand Up @@ -194,7 +195,14 @@ public async Task<string> GetStringAsync() {
// https://stackoverflow.com/questions/46119872/encoding-issues-with-net-core-2 (#86)
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
#endif
_capturedBody = await ResponseMessage.Content.StripCharsetQuotes().ReadAsStringAsync();
// strip quotes from charset so .NET doesn't choke on them
// https://github.com/dotnet/corefx/issues/5014
// https://github.com/tmenier/Flurl/pull/76
var ct = ResponseMessage.Content.Headers?.ContentType;
if (ct?.CharSet != null)
ct.CharSet = ct.CharSet.StripQuotes();

_capturedBody = await ResponseMessage.Content.ReadAsStringAsync();
_streamRead = true;
return (string)_capturedBody;
}
Expand Down
81 changes: 0 additions & 81 deletions src/Flurl.Http/HttpMessage.cs

This file was deleted.

122 changes: 122 additions & 0 deletions src/Flurl.Http/HttpMessageExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using Flurl.Http.Content;
using Flurl.Util;

namespace Flurl.Http
{
/// <summary>
/// Extension methods off HttpRequestMessage and HttpResponseMessage.
/// </summary>
public static class HttpMessageExtensions
{
/// <summary>
/// Set a header on this HttpRequestMessage (default), or its Content property if it's a known content-level header.
/// No validation. Overwrites any existing value(s) for the header.
/// </summary>
/// <param name="request">The HttpRequestMessage.</param>
/// <param name="name">The header name.</param>
/// <param name="value">The header value.</param>
/// <param name="createContentIfNecessary">If it's a content-level header and there is no content, this determines whether to create an empty HttpContent or just ignore the header.</param>
public static void SetHeader(this HttpRequestMessage request, string name, object value, bool createContentIfNecessary = true) {
new HttpMessage(request).SetHeader(name, value, createContentIfNecessary);
}

/// <summary>
/// Set a header on this HttpResponseMessage (default), or its Content property if it's a known content-level header.
/// No validation. Overwrites any existing value(s) for the header.
/// </summary>
/// <param name="response">The HttpResponseMessage.</param>
/// <param name="name">The header name.</param>
/// <param name="value">The header value.</param>
/// <param name="createContentIfNecessary">If it's a content-level header and there is no content, this determines whether to create an empty HttpContent or just ignore the header.</param>
public static void SetHeader(this HttpResponseMessage response, string name, object value, bool createContentIfNecessary = true) {
new HttpMessage(response).SetHeader(name, value, createContentIfNecessary);
}

/// <summary>
/// Associate a FlurlCall object with this request
/// </summary>
internal static void SetHttpCall(this HttpRequestMessage request, FlurlCall call) {
if (request?.Properties != null)
request.Properties["FlurlHttpCall"] = call;
}

/// <summary>
/// Get the FlurlCall associated with this request, if any.
/// </summary>
internal static FlurlCall GetHttpCall(this HttpRequestMessage request) {
if (request?.Properties != null && request.Properties.TryGetValue("FlurlHttpCall", out var obj) && obj is FlurlCall call)
return call;
return null;
}

private static void SetHeader(this HttpMessage msg, string name, object value, bool createContentIfNecessary) {
switch (name.ToLower()) {
// https://docs.microsoft.com/en-us/dotnet/api/system.net.http.headers.httpcontentheaders
case "allow":
case "content-disposition":
case "content-encoding":
case "content-language":
case "content-length":
case "content-location":
case "content-md5":
case "content-range":
case "content-type":
case "expires":
case "last-modified":
// it's a content-level header
if (msg.Content == null && (!createContentIfNecessary || value == null))
break;

if (msg.Content == null) {
msg.Content = new CapturedStringContent("");
msg.Content.Headers.Clear();
}
else {
msg.Content.Headers.Remove(name);
}

if (value != null)
msg.Content.Headers.TryAddWithoutValidation(name, new[] { value.ToInvariantString() });
break;
default:
// it's a request/response-level header
if (!name.Equals("Set-Cookie", StringComparison.OrdinalIgnoreCase)) // multiple set-cookie headers are allowed
msg.Headers.Remove(name);
if (value != null)
msg.Headers.TryAddWithoutValidation(name, new[] { value.ToInvariantString() });
break;
}
}


/// <summary>
/// Wrapper class for treating HttpRequestMessage and HttpResponseMessage uniformly. (Unfortunately they don't have a common interface.)
/// </summary>
private class HttpMessage
{
private readonly HttpRequestMessage _request;
private readonly HttpResponseMessage _response;

public HttpHeaders Headers => _request?.Headers as HttpHeaders ?? _response?.Headers;

public HttpContent Content {
get => _request?.Content ?? _response?.Content;
set {
if (_request != null) _request.Content = value;
else _response.Content = value;
}
}

public HttpMessage(HttpRequestMessage request) {
_request = request;
}

public HttpMessage(HttpResponseMessage response) {
_response = response;
}
}
}
}
55 changes: 0 additions & 55 deletions src/Flurl.Http/HttpRequestMessageExtensions.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.IO;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Flurl.Util;

namespace Flurl.Http
{
/// <summary>
/// Extension methods off HttpResponseMessage, and async extension methods off Task&lt;IFlurlResponse&gt;
/// that allow chaining off methods like SendAsync without the need for nested awaits.
/// ReceiveXXX extension methods off Task&lt;IFlurlResponse&gt; that allow chaining off methods like SendAsync
/// without the need for nested awaits.
/// </summary>
public static class HttpResponseMessageExtensions
public static class ResponseExtensions
{
/// <summary>
/// Deserializes JSON-formatted HTTP response body to object of type T. Intended to chain off an async HTTP.
Expand Down Expand Up @@ -97,36 +95,5 @@ public static async Task<byte[]> ReceiveBytes(this Task<IFlurlResponse> response
return await resp.GetBytesAsync().ConfigureAwait(false);
}
}

/// <summary>
/// Set a header on this HttpResponseMessage (default), or its Content property if it's a known content-level header.
/// No validation. Overwrites any existing value(s) for the header.
/// </summary>
/// <param name="response">The HttpResponseMessage.</param>
/// <param name="name">The header name.</param>
/// <param name="value">The header value.</param>
/// <param name="createContentIfNecessary">If it's a content-level header and there is no content, this determines whether to create an empty HttpContent or just ignore the header.</param>
public static void SetHeader(this HttpResponseMessage response, string name, object value, bool createContentIfNecessary = true) {
new HttpMessage(response).SetHeader(name, value, createContentIfNecessary);
}

/// <summary>
/// Gets the value of a header on this HttpResponseMessage (default), or its Content property.
/// Returns null if the header doesn't exist.
/// </summary>
/// <param name="response">The HttpResponseMessage.</param>
/// <param name="name">The header name.</param>
/// <returns>The header value.</returns>
public static string GetHeaderValue(this HttpResponseMessage response, string name) {
return new HttpMessage(response).GetHeaderValue(name);
}

// https://github.com/tmenier/Flurl/pull/76, https://github.com/dotnet/corefx/issues/5014
internal static HttpContent StripCharsetQuotes(this HttpContent content) {
var header = content?.Headers?.ContentType;
if (header?.CharSet != null)
header.CharSet = header.CharSet.StripQuotes();
return content;
}
}
}
2 changes: 1 addition & 1 deletion src/Flurl.Http/Testing/HttpCallAssertion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ public HttpCallAssertion WithOAuthBearerToken(string token = "*") {
/// </summary>
public HttpCallAssertion WithBasicAuth(string username = "*", string password = "*") {
return With(call => {
var val = call.HttpRequestMessage.GetHeaderValue("Authorization");
var val = call.Request.Headers.FirstOrDefault("Authorization");
if (val == null) return false;
if (!val.StartsWith("Basic ")) return false;
if ((username ?? "*") == "*" && (password ?? "*") == "*") return true;
Expand Down

0 comments on commit 77b29c4

Please sign in to comment.