ConfigureClient, plus lots of comments and some more tests
This commit is contained in:
parent
03445902c1
commit
b2b3fa73d1
@ -4,6 +4,7 @@ using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using Flurl.Http.Configuration;
|
||||
using Flurl.Util;
|
||||
|
||||
namespace Flurl.Http
|
||||
@ -41,6 +42,34 @@ namespace Flurl.Http
|
||||
return client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Change FlurlHttpSettings for this client instance.
|
||||
/// </summary>
|
||||
/// <param name="action">Action defining the settings changes.</param>
|
||||
/// <returns>The FlurlClient with the modified HttpClient</returns>
|
||||
public static FlurlClient ConfigureClient(this FlurlClient client, Action<FlurlHttpSettings> action) {
|
||||
action(client.Settings);
|
||||
return client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and allows changing the FlurlHttpSettings associated with the instance.
|
||||
/// </summary>
|
||||
/// <param name="action">Action defining the settings changes.</param>
|
||||
/// <returns>The FlurlClient with the modified HttpClient</returns>
|
||||
public static FlurlClient ConfigureClient(this Url url, Action<FlurlHttpSettings> action) {
|
||||
return new FlurlClient(url, true).ConfigureClient(action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and allows changing the FlurlHttpSettings associated with the instance.
|
||||
/// </summary>
|
||||
/// <param name="action">Action defining the settings changes.</param>
|
||||
/// <returns>The FlurlClient with the modified HttpClient</returns>
|
||||
public static FlurlClient ConfigureClient(this string url, Action<FlurlHttpSettings> action) {
|
||||
return new FlurlClient(url, true).ConfigureClient(action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides access to modifying the underlying HttpClient.
|
||||
/// </summary>
|
||||
|
@ -6,7 +6,11 @@ using Flurl.Util;
|
||||
|
||||
namespace Flurl.Http.Configuration
|
||||
{
|
||||
public class DefaultUrlEncodedSerializer : ISerializer
|
||||
/// <summary>
|
||||
/// ISerializer implementation that converts an object representing name/value pairs to a URL-encoded string.
|
||||
/// Default serializer used in calls to PostUrlEncodedAsync, etc.
|
||||
/// </summary>
|
||||
public class DefaultUrlEncodedSerializer : ISerializer
|
||||
{
|
||||
public string Serialize(object obj) {
|
||||
var sb = new StringBuilder();
|
||||
|
@ -5,10 +5,22 @@ using System.Text;
|
||||
|
||||
namespace Flurl.Http.Configuration
|
||||
{
|
||||
/// <summary>
|
||||
/// Contract for serializing and deserializing objects.
|
||||
/// </summary>
|
||||
public interface ISerializer
|
||||
{
|
||||
/// <summary>
|
||||
/// Serializes an object to a string representation.
|
||||
/// </summary>
|
||||
string Serialize(object obj);
|
||||
/// <summary>
|
||||
/// Deserializes an object from a string representation.
|
||||
/// </summary>
|
||||
T Deserialize<T>(string s);
|
||||
/// <summary>
|
||||
/// Deserializes an object from a stream representation.
|
||||
/// </summary>
|
||||
T Deserialize<T>(Stream stream);
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,8 @@ using Newtonsoft.Json;
|
||||
namespace Flurl.Http.Configuration
|
||||
{
|
||||
/// <summary>
|
||||
/// ISerializer implementation that uses Newtonsoft Json.NET. Used as Flurl.Http's default JSON serializer.
|
||||
/// ISerializer implementation that uses Newtonsoft Json.NET.
|
||||
/// Default serializer used in calls to GetJsonAsync, PostJsonAsync, etc.
|
||||
/// </summary>
|
||||
public class NewtonsoftJsonSerializer : ISerializer
|
||||
{
|
||||
|
@ -8,13 +8,18 @@ namespace Flurl.Http
|
||||
{
|
||||
public static class HttpRequestMessageExtensions
|
||||
{
|
||||
public static void SetFlurlSettings(this HttpRequestMessage request, FlurlHttpSettings settings) {
|
||||
request.Properties["FlurlSettings"] = settings;
|
||||
private const string SETTINGS_KEY = "FlurlSettings";
|
||||
|
||||
internal static void SetFlurlSettings(this HttpRequestMessage request, FlurlHttpSettings settings) {
|
||||
request.Properties[SETTINGS_KEY] = settings;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the FlurlSettings object associated with this HttpRequestMessage.
|
||||
/// </summary>
|
||||
public static FlurlHttpSettings GetFlurlSettings(this HttpRequestMessage request) {
|
||||
object settings;
|
||||
return request.Properties.TryGetValue("FlurlSettings", out settings) ? (FlurlHttpSettings)settings : FlurlHttp.GlobalSettings;
|
||||
return request.Properties.TryGetValue(SETTINGS_KEY, out settings) ? (FlurlHttpSettings)settings : FlurlHttp.GlobalSettings;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Http\RealHttpTests.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Http\FlurlClientTests.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Http\GetTests.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Http\SettingsTests.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Http\GlobalConfigTests.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Http\HeadTests.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Http\HttpTestFixtureBase.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Http\PostTests.cs" />
|
||||
|
@ -4,14 +4,19 @@ using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Flurl.Http;
|
||||
using Flurl.Http.Configuration;
|
||||
using Flurl.Http.Testing;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Flurl.Test.Http
|
||||
{
|
||||
[TestFixture]
|
||||
public class ClientConfigTests
|
||||
public class ClientConfigTestsBase : ConfigTestsBase
|
||||
{
|
||||
protected override FlurlHttpSettings GetSettings() {
|
||||
return GetClient().Settings;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void can_set_timeout() {
|
||||
var client = "http://www.api.com".WithTimeout(TimeSpan.FromSeconds(15));
|
||||
@ -77,16 +82,25 @@ namespace Flurl.Test.Http
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task can_allow_non_success_status() {
|
||||
public async Task can_allow_specific_http_status() {
|
||||
using (var test = new HttpTest()) {
|
||||
test.RespondWith(404, "Nothing to see here");
|
||||
// no exception = pass
|
||||
await "http://www.api.com"
|
||||
.AllowHttpStatus(HttpStatusCode.Conflict, HttpStatusCode.NotFound)
|
||||
.DeleteAsync();
|
||||
}
|
||||
}
|
||||
|
||||
[Test, ExpectedException(typeof(FlurlHttpException))]
|
||||
public async Task can_clear_non_success_status() {
|
||||
using (var test = new HttpTest()) {
|
||||
test.RespondWith(418, "I'm a teapot");
|
||||
try {
|
||||
var result = await "http://www.api.com".AllowHttpStatus("1xx,300-500").GetAsync();
|
||||
Assert.IsFalse(result.IsSuccessStatusCode);
|
||||
}
|
||||
catch (Exception) {
|
||||
Assert.Fail("Exception should not have been thrown.");
|
||||
}
|
||||
// allow 4xx
|
||||
var client = "http://www.api.com".AllowHttpStatus("4xx");
|
||||
// but then disallow it
|
||||
client.Settings.AllowedHttpStatusRange = null;
|
||||
await client.GetAsync();
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,24 +119,11 @@ namespace Flurl.Test.Http
|
||||
}
|
||||
|
||||
[Test, ExpectedException(typeof(FlurlHttpException))]
|
||||
public async Task can_clear_non_success_status() {
|
||||
public async Task can_override_settings_fluently() {
|
||||
using (var test = new HttpTest()) {
|
||||
test.RespondWith(418, "I'm a teapot");
|
||||
// allow 4xx
|
||||
var client = "http://www.api.com".AllowHttpStatus("4xx");
|
||||
// but then disallow it
|
||||
client.Settings.AllowedHttpStatusRange = null;
|
||||
await client.GetAsync();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task can_allow_specific_http_status() {
|
||||
using (var test = new HttpTest()) {
|
||||
test.RespondWith(404, "Nothing to see here");
|
||||
// allow 404
|
||||
var client = "http://www.api.com".AllowHttpStatus(HttpStatusCode.Conflict, HttpStatusCode.NotFound);
|
||||
await client.DeleteAsync();
|
||||
FlurlHttp.GlobalSettings.AllowedHttpStatusRange = "*";
|
||||
test.RespondWith(500, "epic fail");
|
||||
await "http://www.api.com".ConfigureClient(c => c.AllowedHttpStatusRange = "2xx").GetAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Flurl.Http;
|
||||
@ -8,30 +9,41 @@ using NUnit.Framework;
|
||||
|
||||
namespace Flurl.Test.Http
|
||||
{
|
||||
[TestFixture]
|
||||
public class GlobalConfigTests
|
||||
/// <summary>
|
||||
/// All global settings can also be set at the client level, so this base class allows ClientConfigTests to
|
||||
/// inherit all the same tests.
|
||||
/// </summary>
|
||||
public abstract class ConfigTestsBase
|
||||
{
|
||||
protected abstract FlurlHttpSettings GetSettings();
|
||||
|
||||
private FlurlClient _client;
|
||||
protected FlurlClient GetClient() {
|
||||
if (_client == null)
|
||||
_client = new FlurlClient("http://www.api.com");
|
||||
return _client;
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void ResetDefaults() {
|
||||
FlurlHttp.GlobalSettings.ResetDefaults();
|
||||
GetSettings().ResetDefaults();
|
||||
_client = null;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void can_provide_custom_httpclient_factory() {
|
||||
FlurlHttp.GlobalSettings.HttpClientFactory = new SomeCustomHttpClientFactory();
|
||||
var client = new FlurlClient("http://www.api.com");
|
||||
|
||||
Assert.IsInstanceOf<SomeCustomHttpClient>(client.HttpClient);
|
||||
Assert.IsInstanceOf<SomeCustomMessageHandler>(client.HttpMessageHandler);
|
||||
GetSettings().HttpClientFactory = new SomeCustomHttpClientFactory();
|
||||
Assert.IsInstanceOf<SomeCustomHttpClient>(GetClient().HttpClient);
|
||||
Assert.IsInstanceOf<SomeCustomMessageHandler>(GetClient().HttpMessageHandler);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task can_allow_non_success_status() {
|
||||
using (var test = new HttpTest()) {
|
||||
FlurlHttp.GlobalSettings.AllowedHttpStatusRange = "4xx";
|
||||
GetSettings().AllowedHttpStatusRange = "4xx";
|
||||
test.RespondWith(418, "I'm a teapot");
|
||||
try {
|
||||
var result = await "http://www.api.com".GetAsync();
|
||||
var result = await GetClient().GetAsync();
|
||||
Assert.IsFalse(result.IsSuccessStatusCode);
|
||||
}
|
||||
catch (Exception) {
|
||||
@ -45,12 +57,12 @@ namespace Flurl.Test.Http
|
||||
var callbackCalled = false;
|
||||
using (var test = new HttpTest()) {
|
||||
test.RespondWith("ok");
|
||||
FlurlHttp.GlobalSettings.BeforeCall = req => {
|
||||
GetSettings().BeforeCall = req => {
|
||||
CollectionAssert.IsNotEmpty(test.ResponseQueue); // verifies that callback is running before HTTP call is made
|
||||
callbackCalled = true;
|
||||
};
|
||||
Assert.IsFalse(callbackCalled);
|
||||
await "http://www.api.com".GetAsync();
|
||||
await GetClient().GetAsync();
|
||||
Assert.IsTrue(callbackCalled);
|
||||
}
|
||||
}
|
||||
@ -60,12 +72,12 @@ namespace Flurl.Test.Http
|
||||
var callbackCalled = false;
|
||||
using (var test = new HttpTest()) {
|
||||
test.RespondWith("ok");
|
||||
FlurlHttp.GlobalSettings.AfterCall = call => {
|
||||
GetSettings().AfterCall = call => {
|
||||
CollectionAssert.IsEmpty(test.ResponseQueue); // verifies that callback is running after HTTP call is made
|
||||
callbackCalled = true;
|
||||
};
|
||||
Assert.IsFalse(callbackCalled);
|
||||
await "http://www.api.com".GetAsync();
|
||||
await GetClient().GetAsync();
|
||||
Assert.IsTrue(callbackCalled);
|
||||
}
|
||||
}
|
||||
@ -76,14 +88,14 @@ namespace Flurl.Test.Http
|
||||
var callbackCalled = false;
|
||||
using (var test = new HttpTest()) {
|
||||
test.RespondWith(500, "server error");
|
||||
FlurlHttp.GlobalSettings.OnError = call => {
|
||||
GetSettings().OnError = call => {
|
||||
CollectionAssert.IsEmpty(test.ResponseQueue); // verifies that callback is running after HTTP call is made
|
||||
callbackCalled = true;
|
||||
call.ExceptionHandled = markExceptionHandled;
|
||||
};
|
||||
Assert.IsFalse(callbackCalled);
|
||||
try {
|
||||
await "http://www.api.com".GetAsync();
|
||||
await GetClient().GetAsync();
|
||||
Assert.IsTrue(callbackCalled, "OnError was never called");
|
||||
Assert.IsTrue(markExceptionHandled, "ExceptionHandled was marked false in callback, but exception was not propagated.");
|
||||
}
|
||||
@ -97,12 +109,12 @@ namespace Flurl.Test.Http
|
||||
[Test]
|
||||
public async Task can_disable_exception_behavior() {
|
||||
using (var test = new HttpTest()) {
|
||||
FlurlHttp.GlobalSettings.OnError = call => {
|
||||
GetSettings().OnError = call => {
|
||||
call.ExceptionHandled = true;
|
||||
};
|
||||
test.RespondWith(500, "server error");
|
||||
try {
|
||||
var result = await "http://www.api.com".GetAsync();
|
||||
var result = await GetClient().GetAsync();
|
||||
Assert.IsFalse(result.IsSuccessStatusCode);
|
||||
}
|
||||
catch (FlurlHttpException) {
|
||||
@ -111,18 +123,6 @@ namespace Flurl.Test.Http
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task client_can_override_global_settings() {
|
||||
var overridden = false;
|
||||
using (new HttpTest()) {
|
||||
FlurlHttp.GlobalSettings.AfterCall = _ => overridden = false;
|
||||
var fc = new FlurlClient("http://www.api.com");
|
||||
fc.Settings.AfterCall = _ => overridden = true;
|
||||
await fc.GetAsync();
|
||||
Assert.True(overridden);
|
||||
}
|
||||
}
|
||||
|
||||
private class SomeCustomHttpClientFactory : IHttpClientFactory
|
||||
{
|
||||
public HttpClient CreateClient(Url url, HttpMessageHandler handler) {
|
||||
@ -137,4 +137,12 @@ namespace Flurl.Test.Http
|
||||
private class SomeCustomHttpClient : HttpClient { }
|
||||
private class SomeCustomMessageHandler : HttpClientHandler { }
|
||||
}
|
||||
|
||||
[TestFixture]
|
||||
public class GlobalConfigTestsBase : ConfigTestsBase
|
||||
{
|
||||
protected override FlurlHttpSettings GetSettings() {
|
||||
return FlurlHttp.GlobalSettings;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user