Issue #65, solved by creating a copy of FlurlClient from WithUrl to get thread safety, rather than making Dispose virtual
This commit is contained in:
parent
fc231312e0
commit
ea9c5ddf8d
@ -1,373 +1,378 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
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
|
||||
{
|
||||
public static class ClientConfigExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Fluently specify that an existing FlurlClient should be used to call the Url, rather than creating a new one.
|
||||
/// Enables re-using the underlying HttpClient.
|
||||
/// </summary>
|
||||
/// <param name="fc">The FlurlClient to use in calling the Url</param>
|
||||
/// <returns></returns>
|
||||
public static FlurlClient WithClient(this Url url, FlurlClient fc) {
|
||||
fc.Url = url;
|
||||
return fc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fluently specify that an existing FlurlClient should be used to call the Url, rather than creating a new one.
|
||||
/// Enables re-using the underlying HttpClient.
|
||||
/// </summary>
|
||||
/// <param name="fc">The FlurlClient to use in calling the Url</param>
|
||||
/// <returns></returns>
|
||||
public static FlurlClient WithClient(this string url, FlurlClient fc) {
|
||||
return new Url(url).WithClient(fc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fluently specify the URL to be called with the current FlurlClient instance.
|
||||
/// </summary>
|
||||
/// <param name="url">The Url to call.</param>
|
||||
/// <returns></returns>
|
||||
public static FlurlClient WithUrl(this FlurlClient client, Url url) {
|
||||
client.Url = url;
|
||||
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>
|
||||
/// <param name="action">Action to perform on the HttpClient.</param>
|
||||
/// <returns>The FlurlClient with the modified HttpClient</returns>
|
||||
public static FlurlClient ConfigureHttpClient(this FlurlClient client, Action<HttpClient> action) {
|
||||
action(client.HttpClient);
|
||||
return client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and provides access to modifying the underlying HttpClient.
|
||||
/// </summary>
|
||||
/// <param name="action">Action to perform on the HttpClient.</param>
|
||||
/// <returns>The FlurlClient with the modified HttpClient</returns>
|
||||
public static FlurlClient ConfigureHttpClient(this Url url, Action<HttpClient> action) {
|
||||
return new FlurlClient(url, true).ConfigureHttpClient(action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and provides access to modifying the underlying HttpClient.
|
||||
/// </summary>
|
||||
/// <param name="action">Action to perform on the HttpClient.</param>
|
||||
/// <returns>The FlurlClient with the modified HttpClient</returns>
|
||||
public static FlurlClient ConfigureHttpClient(this string url, Action<HttpClient> action) {
|
||||
return new FlurlClient(url, true).ConfigureHttpClient(action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the client timout to the specified timespan.
|
||||
/// </summary>
|
||||
/// <param name="timespan">Time to wait before the request times out.</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient WithTimeout(this FlurlClient client, TimeSpan timespan) {
|
||||
client.HttpClient.Timeout = timespan;
|
||||
return client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets the client timout to the specified timespan.
|
||||
/// </summary>
|
||||
/// <param name="timespan">Time to wait before the request times out.</param>
|
||||
/// <returns>The created FlurlClient.</returns>
|
||||
public static FlurlClient WithTimeout(this Url url, TimeSpan timespan) {
|
||||
return new FlurlClient(url, true).WithTimeout(timespan);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets the client timout to the specified timespan.
|
||||
/// </summary>
|
||||
/// <param name="timespan">Time to wait before the request times out.</param>
|
||||
/// <returns>The created FlurlClient.</returns>
|
||||
public static FlurlClient WithTimeout(this string url, TimeSpan timespan) {
|
||||
return new FlurlClient(url, true).WithTimeout(timespan);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the client timout to the specified number of seconds.
|
||||
/// </summary>
|
||||
/// <param name="seconds">Number of seconds to wait before the request times out.</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient WithTimeout(this FlurlClient client, int seconds) {
|
||||
return client.WithTimeout(TimeSpan.FromSeconds(seconds));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets the client timout to the specified number of seconds.
|
||||
/// </summary>
|
||||
/// <param name="seconds">Number of seconds to wait before the request times out.</param>
|
||||
/// <returns>The created FlurlClient.</returns>
|
||||
public static FlurlClient WithTimeout(this Url url, int seconds) {
|
||||
return new FlurlClient(url, true).WithTimeout(seconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets the client timout to the specified number of seconds.
|
||||
/// </summary>
|
||||
/// <param name="seconds">Number of seconds to wait before the request times out.</param>
|
||||
/// <returns>The created FlurlClient.</returns>
|
||||
public static FlurlClient WithTimeout(this string url, int seconds) {
|
||||
return new FlurlClient(url, true).WithTimeout(seconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets an HTTP header to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="name">HTTP header name.</param>
|
||||
/// <param name="value">HTTP header value.</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient WithHeader(this FlurlClient client, string name, object value) {
|
||||
var values = new[] { (value == null) ? null : value.ToString() };
|
||||
client.HttpClient.DefaultRequestHeaders.Add(name, values);
|
||||
return client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets an HTTP header to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="name">HTTP header name.</param>
|
||||
/// <param name="value">HTTP header value.</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient WithHeader(this Url url, string name, object value) {
|
||||
return new FlurlClient(url, true).WithHeader(name, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets an HTTP header to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="name">HTTP header name.</param>
|
||||
/// <param name="value">HTTP header value.</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient WithHeader(this string url, string name, object value) {
|
||||
return new FlurlClient(url, true).WithHeader(name, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets HTTP headers based on property names/values of the provided object, or keys/values if object is a dictionary, to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="headers">Names/values of HTTP headers to set. Typically an anonymous object or IDictionary.</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient WithHeaders(this FlurlClient client, object headers) {
|
||||
if (headers == null)
|
||||
return client;
|
||||
|
||||
foreach (var kv in headers.ToKeyValuePairs()) {
|
||||
if (kv.Value == null)
|
||||
continue;
|
||||
|
||||
client.HttpClient.DefaultRequestHeaders.Add(kv.Key, new[] { kv.Value.ToString() });
|
||||
}
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets HTTP headers based on property names/values of the provided object, or keys/values if object is a dictionary, to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="headers">Names/values of HTTP headers to set. Typically an anonymous object or IDictionary.</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient WithHeaders(this Url url, object headers) {
|
||||
return new FlurlClient(url, true).WithHeaders(headers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets HTTP headers based on property names/values of the provided object, or keys/values if object is a dictionary, to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="headers">Names/values of HTTP headers to set. Typically an anonymous object or IDictionary.</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient WithHeaders(this string url, object headers) {
|
||||
return new FlurlClient(url, true).WithHeaders(headers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets HTTP authorization header according to Basic Authentication protocol to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="username">Username of authenticating user.</param>
|
||||
/// <param name="password">Password of authenticating user.</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient WithBasicAuth(this FlurlClient client, string username, string password) {
|
||||
// http://stackoverflow.com/questions/14627399/setting-authorization-header-of-httpclient
|
||||
var value = Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format("{0}:{1}", username, password)));
|
||||
client.HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", value);
|
||||
return client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets HTTP authorization header according to Basic Authentication protocol to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="username">Username of authenticating user.</param>
|
||||
/// <param name="password">Password of authenticating user.</param>
|
||||
/// <returns>The new FlurlClient.</returns>
|
||||
public static FlurlClient WithBasicAuth(this Url url, string username, string password) {
|
||||
return new FlurlClient(url, true).WithBasicAuth(username, password);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets HTTP authorization header according to Basic Authentication protocol to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="username">Username of authenticating user.</param>
|
||||
/// <param name="password">Password of authenticating user.</param>
|
||||
/// <returns>The new FlurlClient.</returns>
|
||||
public static FlurlClient WithBasicAuth(this string url, string username, string password) {
|
||||
return new FlurlClient(url, true).WithBasicAuth(username, password);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets HTTP authorization header with acquired bearer token according to OAuth 2.0 specification to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="token">The acquired bearer token to pass.</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient WithOAuthBearerToken(this FlurlClient client, string token) {
|
||||
client.HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
|
||||
return client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets HTTP authorization header with acquired bearer token according to OAuth 2.0 specification to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="token">The acquired bearer token to pass.</param>
|
||||
/// <returns>The new FlurlClient.</returns>
|
||||
public static FlurlClient WithOAuthBearerToken(this Url url, string token) {
|
||||
return new FlurlClient(url, true).WithOAuthBearerToken(token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets HTTP authorization header with acquired bearer token according to OAuth 2.0 specification to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="token">The acquired bearer token to pass.</param>
|
||||
/// <returns>The new FlurlClient.</returns>
|
||||
public static FlurlClient WithOAuthBearerToken(this string url, string token) {
|
||||
return new FlurlClient(url, true).WithOAuthBearerToken(token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a pattern representing an HTTP status code or range of codes which (in addtion to 2xx) will NOT result in a FlurlHttpException being thrown.
|
||||
/// </summary>
|
||||
/// <param name="pattern">Examples: "3xx", "100,300,600", "100-299,6xx"</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient AllowHttpStatus(this FlurlClient client, string pattern) {
|
||||
if (!string.IsNullOrWhiteSpace(pattern)) {
|
||||
var current = client.Settings.AllowedHttpStatusRange;
|
||||
if (string.IsNullOrWhiteSpace(current))
|
||||
client.Settings.AllowedHttpStatusRange = pattern;
|
||||
else
|
||||
client.Settings.AllowedHttpStatusRange += "," + pattern;
|
||||
}
|
||||
return client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and adds a pattern representing an HTTP status code or range of codes which (in addtion to 2xx) will NOT result in a FlurlHttpException being thrown.
|
||||
/// </summary>
|
||||
/// <param name="pattern">Examples: "3xx", "100,300,600", "100-299,6xx"</param>
|
||||
/// <returns>The new FlurlClient.</returns>
|
||||
public static FlurlClient AllowHttpStatus(this Url url, string pattern) {
|
||||
return new FlurlClient(url, true).AllowHttpStatus(pattern);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and adds a pattern representing an HTTP status code or range of codes which (in addtion to 2xx) will NOT result in a FlurlHttpException being thrown.
|
||||
/// </summary>
|
||||
/// <param name="pattern">Examples: "3xx", "100,300,600", "100-299,6xx"</param>
|
||||
/// <returns>The new FlurlClient.</returns>
|
||||
public static FlurlClient AllowHttpStatus(this string url, string pattern) {
|
||||
return new FlurlClient(url, true).AllowHttpStatus(pattern);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an <see cref="HttpStatusCode"/> which (in addtion to 2xx) will NOT result in a FlurlHttpException being thrown.
|
||||
/// </summary>
|
||||
/// <param name="statusCodes">Examples: HttpStatusCode.NotFound</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient AllowHttpStatus(this FlurlClient client, params HttpStatusCode[] statusCodes) {
|
||||
var pattern = string.Join(",", statusCodes.Select(c => (int)c));
|
||||
return AllowHttpStatus(client, pattern);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an <see cref="HttpStatusCode"/> which (in addtion to 2xx) will NOT result in a FlurlHttpException being thrown.
|
||||
/// </summary>
|
||||
/// <param name="statusCodes">Examples: HttpStatusCode.NotFound</param>
|
||||
/// <returns>The new FlurlClient.</returns>
|
||||
public static FlurlClient AllowHttpStatus(this Url url, params HttpStatusCode[] statusCodes) {
|
||||
return new FlurlClient(url, true).AllowHttpStatus(statusCodes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an <see cref="HttpStatusCode"/> which (in addtion to 2xx) will NOT result in a FlurlHttpException being thrown.
|
||||
/// </summary>
|
||||
/// <param name="statusCodes">Examples: HttpStatusCode.NotFound</param>
|
||||
/// <returns>The new FlurlClient.</returns>
|
||||
public static FlurlClient AllowHttpStatus(this string url, params HttpStatusCode[] statusCodes) {
|
||||
return new FlurlClient(url, true).AllowHttpStatus(statusCodes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prevents a FlurlHttpException from being thrown on any completed response, regardless of the HTTP status code.
|
||||
/// </summary>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient AllowAnyHttpStatus(this FlurlClient client) {
|
||||
client.Settings.AllowedHttpStatusRange = "*";
|
||||
return client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and prevents a FlurlHttpException from being thrown on any completed response, regardless of the HTTP status code.
|
||||
/// </summary>
|
||||
/// <returns>The new FlurlClient.</returns>
|
||||
public static FlurlClient AllowAnyHttpStatus(this Url url) {
|
||||
return new FlurlClient(url, true).AllowAnyHttpStatus();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and prevents a FlurlHttpException from being thrown on any completed response, regardless of the HTTP status code.
|
||||
/// </summary>
|
||||
/// <returns>The new FlurlClient.</returns>
|
||||
public static FlurlClient AllowAnyHttpStatus(this string url) {
|
||||
return new FlurlClient(url, true).AllowAnyHttpStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Linq;
|
||||
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
|
||||
{
|
||||
public static class ClientConfigExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Fluently specify that an existing FlurlClient should be used to call the Url, rather than creating a new one.
|
||||
/// Enables re-using the underlying HttpClient.
|
||||
/// </summary>
|
||||
/// <param name="fc">The FlurlClient to use in calling the Url</param>
|
||||
/// <returns></returns>
|
||||
public static FlurlClient WithClient(this Url url, FlurlClient fc) {
|
||||
fc.Url = url;
|
||||
return fc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fluently specify that an existing FlurlClient should be used to call the Url, rather than creating a new one.
|
||||
/// Enables re-using the underlying HttpClient.
|
||||
/// </summary>
|
||||
/// <param name="fc">The FlurlClient to use in calling the Url</param>
|
||||
/// <returns></returns>
|
||||
public static FlurlClient WithClient(this string url, FlurlClient fc) {
|
||||
return new Url(url).WithClient(fc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new FlurlClient where all state (HttpClient, etc) is shared but with a different URL.
|
||||
/// Allows you to re-use the underlying HttpClient instance (such as to share cookies, etc) with
|
||||
/// different URLs in a thread-safe way.
|
||||
/// </summary>
|
||||
/// <param name="url">The Url to call.</param>
|
||||
/// <returns></returns>
|
||||
public static FlurlClient WithUrl(this FlurlClient client, Url url) {
|
||||
var fc = client.Clone();
|
||||
fc.Url = url;
|
||||
// prevent the new client from automatically disposing the parent's HttpClient
|
||||
fc.AutoDispose = false;
|
||||
return fc;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// <param name="action">Action to perform on the HttpClient.</param>
|
||||
/// <returns>The FlurlClient with the modified HttpClient</returns>
|
||||
public static FlurlClient ConfigureHttpClient(this FlurlClient client, Action<HttpClient> action) {
|
||||
action(client.HttpClient);
|
||||
return client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and provides access to modifying the underlying HttpClient.
|
||||
/// </summary>
|
||||
/// <param name="action">Action to perform on the HttpClient.</param>
|
||||
/// <returns>The FlurlClient with the modified HttpClient</returns>
|
||||
public static FlurlClient ConfigureHttpClient(this Url url, Action<HttpClient> action) {
|
||||
return new FlurlClient(url, true).ConfigureHttpClient(action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and provides access to modifying the underlying HttpClient.
|
||||
/// </summary>
|
||||
/// <param name="action">Action to perform on the HttpClient.</param>
|
||||
/// <returns>The FlurlClient with the modified HttpClient</returns>
|
||||
public static FlurlClient ConfigureHttpClient(this string url, Action<HttpClient> action) {
|
||||
return new FlurlClient(url, true).ConfigureHttpClient(action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the client timout to the specified timespan.
|
||||
/// </summary>
|
||||
/// <param name="timespan">Time to wait before the request times out.</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient WithTimeout(this FlurlClient client, TimeSpan timespan) {
|
||||
client.HttpClient.Timeout = timespan;
|
||||
return client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets the client timout to the specified timespan.
|
||||
/// </summary>
|
||||
/// <param name="timespan">Time to wait before the request times out.</param>
|
||||
/// <returns>The created FlurlClient.</returns>
|
||||
public static FlurlClient WithTimeout(this Url url, TimeSpan timespan) {
|
||||
return new FlurlClient(url, true).WithTimeout(timespan);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets the client timout to the specified timespan.
|
||||
/// </summary>
|
||||
/// <param name="timespan">Time to wait before the request times out.</param>
|
||||
/// <returns>The created FlurlClient.</returns>
|
||||
public static FlurlClient WithTimeout(this string url, TimeSpan timespan) {
|
||||
return new FlurlClient(url, true).WithTimeout(timespan);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the client timout to the specified number of seconds.
|
||||
/// </summary>
|
||||
/// <param name="seconds">Number of seconds to wait before the request times out.</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient WithTimeout(this FlurlClient client, int seconds) {
|
||||
return client.WithTimeout(TimeSpan.FromSeconds(seconds));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets the client timout to the specified number of seconds.
|
||||
/// </summary>
|
||||
/// <param name="seconds">Number of seconds to wait before the request times out.</param>
|
||||
/// <returns>The created FlurlClient.</returns>
|
||||
public static FlurlClient WithTimeout(this Url url, int seconds) {
|
||||
return new FlurlClient(url, true).WithTimeout(seconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets the client timout to the specified number of seconds.
|
||||
/// </summary>
|
||||
/// <param name="seconds">Number of seconds to wait before the request times out.</param>
|
||||
/// <returns>The created FlurlClient.</returns>
|
||||
public static FlurlClient WithTimeout(this string url, int seconds) {
|
||||
return new FlurlClient(url, true).WithTimeout(seconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets an HTTP header to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="name">HTTP header name.</param>
|
||||
/// <param name="value">HTTP header value.</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient WithHeader(this FlurlClient client, string name, object value) {
|
||||
var values = new[] { (value == null) ? null : value.ToString() };
|
||||
client.HttpClient.DefaultRequestHeaders.Add(name, values);
|
||||
return client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets an HTTP header to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="name">HTTP header name.</param>
|
||||
/// <param name="value">HTTP header value.</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient WithHeader(this Url url, string name, object value) {
|
||||
return new FlurlClient(url, true).WithHeader(name, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets an HTTP header to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="name">HTTP header name.</param>
|
||||
/// <param name="value">HTTP header value.</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient WithHeader(this string url, string name, object value) {
|
||||
return new FlurlClient(url, true).WithHeader(name, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets HTTP headers based on property names/values of the provided object, or keys/values if object is a dictionary, to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="headers">Names/values of HTTP headers to set. Typically an anonymous object or IDictionary.</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient WithHeaders(this FlurlClient client, object headers) {
|
||||
if (headers == null)
|
||||
return client;
|
||||
|
||||
foreach (var kv in headers.ToKeyValuePairs()) {
|
||||
if (kv.Value == null)
|
||||
continue;
|
||||
|
||||
client.HttpClient.DefaultRequestHeaders.Add(kv.Key, new[] { kv.Value.ToString() });
|
||||
}
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets HTTP headers based on property names/values of the provided object, or keys/values if object is a dictionary, to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="headers">Names/values of HTTP headers to set. Typically an anonymous object or IDictionary.</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient WithHeaders(this Url url, object headers) {
|
||||
return new FlurlClient(url, true).WithHeaders(headers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets HTTP headers based on property names/values of the provided object, or keys/values if object is a dictionary, to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="headers">Names/values of HTTP headers to set. Typically an anonymous object or IDictionary.</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient WithHeaders(this string url, object headers) {
|
||||
return new FlurlClient(url, true).WithHeaders(headers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets HTTP authorization header according to Basic Authentication protocol to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="username">Username of authenticating user.</param>
|
||||
/// <param name="password">Password of authenticating user.</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient WithBasicAuth(this FlurlClient client, string username, string password) {
|
||||
// http://stackoverflow.com/questions/14627399/setting-authorization-header-of-httpclient
|
||||
var value = Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format("{0}:{1}", username, password)));
|
||||
client.HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", value);
|
||||
return client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets HTTP authorization header according to Basic Authentication protocol to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="username">Username of authenticating user.</param>
|
||||
/// <param name="password">Password of authenticating user.</param>
|
||||
/// <returns>The new FlurlClient.</returns>
|
||||
public static FlurlClient WithBasicAuth(this Url url, string username, string password) {
|
||||
return new FlurlClient(url, true).WithBasicAuth(username, password);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets HTTP authorization header according to Basic Authentication protocol to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="username">Username of authenticating user.</param>
|
||||
/// <param name="password">Password of authenticating user.</param>
|
||||
/// <returns>The new FlurlClient.</returns>
|
||||
public static FlurlClient WithBasicAuth(this string url, string username, string password) {
|
||||
return new FlurlClient(url, true).WithBasicAuth(username, password);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets HTTP authorization header with acquired bearer token according to OAuth 2.0 specification to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="token">The acquired bearer token to pass.</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient WithOAuthBearerToken(this FlurlClient client, string token) {
|
||||
client.HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
|
||||
return client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets HTTP authorization header with acquired bearer token according to OAuth 2.0 specification to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="token">The acquired bearer token to pass.</param>
|
||||
/// <returns>The new FlurlClient.</returns>
|
||||
public static FlurlClient WithOAuthBearerToken(this Url url, string token) {
|
||||
return new FlurlClient(url, true).WithOAuthBearerToken(token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and sets HTTP authorization header with acquired bearer token according to OAuth 2.0 specification to be sent with all requests made with this FlurlClient.
|
||||
/// </summary>
|
||||
/// <param name="token">The acquired bearer token to pass.</param>
|
||||
/// <returns>The new FlurlClient.</returns>
|
||||
public static FlurlClient WithOAuthBearerToken(this string url, string token) {
|
||||
return new FlurlClient(url, true).WithOAuthBearerToken(token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a pattern representing an HTTP status code or range of codes which (in addtion to 2xx) will NOT result in a FlurlHttpException being thrown.
|
||||
/// </summary>
|
||||
/// <param name="pattern">Examples: "3xx", "100,300,600", "100-299,6xx"</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient AllowHttpStatus(this FlurlClient client, string pattern) {
|
||||
if (!string.IsNullOrWhiteSpace(pattern)) {
|
||||
var current = client.Settings.AllowedHttpStatusRange;
|
||||
if (string.IsNullOrWhiteSpace(current))
|
||||
client.Settings.AllowedHttpStatusRange = pattern;
|
||||
else
|
||||
client.Settings.AllowedHttpStatusRange += "," + pattern;
|
||||
}
|
||||
return client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and adds a pattern representing an HTTP status code or range of codes which (in addtion to 2xx) will NOT result in a FlurlHttpException being thrown.
|
||||
/// </summary>
|
||||
/// <param name="pattern">Examples: "3xx", "100,300,600", "100-299,6xx"</param>
|
||||
/// <returns>The new FlurlClient.</returns>
|
||||
public static FlurlClient AllowHttpStatus(this Url url, string pattern) {
|
||||
return new FlurlClient(url, true).AllowHttpStatus(pattern);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and adds a pattern representing an HTTP status code or range of codes which (in addtion to 2xx) will NOT result in a FlurlHttpException being thrown.
|
||||
/// </summary>
|
||||
/// <param name="pattern">Examples: "3xx", "100,300,600", "100-299,6xx"</param>
|
||||
/// <returns>The new FlurlClient.</returns>
|
||||
public static FlurlClient AllowHttpStatus(this string url, string pattern) {
|
||||
return new FlurlClient(url, true).AllowHttpStatus(pattern);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an <see cref="HttpStatusCode"/> which (in addtion to 2xx) will NOT result in a FlurlHttpException being thrown.
|
||||
/// </summary>
|
||||
/// <param name="statusCodes">Examples: HttpStatusCode.NotFound</param>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient AllowHttpStatus(this FlurlClient client, params HttpStatusCode[] statusCodes) {
|
||||
var pattern = string.Join(",", statusCodes.Select(c => (int)c));
|
||||
return AllowHttpStatus(client, pattern);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an <see cref="HttpStatusCode"/> which (in addtion to 2xx) will NOT result in a FlurlHttpException being thrown.
|
||||
/// </summary>
|
||||
/// <param name="statusCodes">Examples: HttpStatusCode.NotFound</param>
|
||||
/// <returns>The new FlurlClient.</returns>
|
||||
public static FlurlClient AllowHttpStatus(this Url url, params HttpStatusCode[] statusCodes) {
|
||||
return new FlurlClient(url, true).AllowHttpStatus(statusCodes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an <see cref="HttpStatusCode"/> which (in addtion to 2xx) will NOT result in a FlurlHttpException being thrown.
|
||||
/// </summary>
|
||||
/// <param name="statusCodes">Examples: HttpStatusCode.NotFound</param>
|
||||
/// <returns>The new FlurlClient.</returns>
|
||||
public static FlurlClient AllowHttpStatus(this string url, params HttpStatusCode[] statusCodes) {
|
||||
return new FlurlClient(url, true).AllowHttpStatus(statusCodes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prevents a FlurlHttpException from being thrown on any completed response, regardless of the HTTP status code.
|
||||
/// </summary>
|
||||
/// <returns>The modified FlurlClient.</returns>
|
||||
public static FlurlClient AllowAnyHttpStatus(this FlurlClient client) {
|
||||
client.Settings.AllowedHttpStatusRange = "*";
|
||||
return client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and prevents a FlurlHttpException from being thrown on any completed response, regardless of the HTTP status code.
|
||||
/// </summary>
|
||||
/// <returns>The new FlurlClient.</returns>
|
||||
public static FlurlClient AllowAnyHttpStatus(this Url url) {
|
||||
return new FlurlClient(url, true).AllowAnyHttpStatus();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a FlurlClient from the URL and prevents a FlurlHttpException from being thrown on any completed response, regardless of the HTTP status code.
|
||||
/// </summary>
|
||||
/// <returns>The new FlurlClient.</returns>
|
||||
public static FlurlClient AllowAnyHttpStatus(this string url) {
|
||||
return new FlurlClient(url, true).AllowAnyHttpStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,20 @@ namespace Flurl.Http
|
||||
public FlurlClient(string url) : this(new Url(url), false) { }
|
||||
public FlurlClient() : this((Url)null, false) { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a copy of this FlurlClient with a shared instance of HttpClient and HttpMessageHandler
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public FlurlClient Clone() {
|
||||
return new FlurlClient {
|
||||
_httpClient = _httpClient,
|
||||
_httpMessageHandler = _httpMessageHandler,
|
||||
Settings = Settings,
|
||||
Url = Url,
|
||||
AutoDispose = AutoDispose
|
||||
};
|
||||
}
|
||||
|
||||
private HttpClient _httpClient;
|
||||
private HttpMessageHandler _httpMessageHandler;
|
||||
|
||||
@ -92,12 +106,8 @@ namespace Flurl.Http
|
||||
/// This FlurlClient can still be reused, but those underlying objects will be re-created as needed. Previously set headers, etc, will be lost.
|
||||
/// </summary>
|
||||
public void Dispose() {
|
||||
if (_httpMessageHandler != null)
|
||||
_httpMessageHandler.Dispose();
|
||||
|
||||
if (_httpClient != null)
|
||||
_httpClient.Dispose();
|
||||
|
||||
_httpMessageHandler?.Dispose();
|
||||
_httpClient?.Dispose();
|
||||
_httpMessageHandler = null;
|
||||
_httpClient = null;
|
||||
}
|
||||
|
@ -1,130 +1,161 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
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 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));
|
||||
Assert.AreEqual(client.HttpClient.Timeout, TimeSpan.FromSeconds(15));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void can_set_timeout_in_seconds() {
|
||||
var client = "http://www.api.com".WithTimeout(15);
|
||||
Assert.AreEqual(client.HttpClient.Timeout, TimeSpan.FromSeconds(15));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void can_set_header() {
|
||||
var client = "http://www.api.com".WithHeader("a", 1);
|
||||
|
||||
var headers = client.HttpClient.DefaultRequestHeaders.ToList();
|
||||
Assert.AreEqual(1, headers.Count);
|
||||
Assert.AreEqual("a", headers[0].Key);
|
||||
CollectionAssert.AreEqual(headers[0].Value, new[] { "1" });
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void can_set_headers_from_anon_object() {
|
||||
var client = "http://www.api.com".WithHeaders(new { a = "b", one = 2 });
|
||||
|
||||
var headers = client.HttpClient.DefaultRequestHeaders.ToList();
|
||||
Assert.AreEqual(2, headers.Count);
|
||||
Assert.AreEqual("a", headers[0].Key);
|
||||
CollectionAssert.AreEqual(headers[0].Value, new[] { "b" });
|
||||
Assert.AreEqual("one", headers[1].Key);
|
||||
CollectionAssert.AreEqual(headers[1].Value, new[] { "2" });
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void can_set_headers_from_dictionary() {
|
||||
var client = "http://www.api.com".WithHeaders(new Dictionary<string, object> { { "a", "b" }, { "one", 2 } });
|
||||
|
||||
var headers = client.HttpClient.DefaultRequestHeaders.ToList();
|
||||
Assert.AreEqual(2, headers.Count);
|
||||
Assert.AreEqual("a", headers[0].Key);
|
||||
CollectionAssert.AreEqual(headers[0].Value, new[] { "b" });
|
||||
Assert.AreEqual("one", headers[1].Key);
|
||||
CollectionAssert.AreEqual(headers[1].Value, new[] { "2" });
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void can_setup_basic_auth() {
|
||||
var client = "http://www.api.com".WithBasicAuth("user", "pass");
|
||||
|
||||
var header = client.HttpClient.DefaultRequestHeaders.First();
|
||||
Assert.AreEqual("Authorization", header.Key);
|
||||
Assert.AreEqual("Basic dXNlcjpwYXNz", header.Value.First());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void can_setup_oauth_bearer_token() {
|
||||
var client = "http://www.api.com".WithOAuthBearerToken("mytoken");
|
||||
|
||||
var header = client.HttpClient.DefaultRequestHeaders.First();
|
||||
Assert.AreEqual("Authorization", header.Key);
|
||||
Assert.AreEqual("Bearer mytoken", header.Value.First());
|
||||
}
|
||||
|
||||
[Test]
|
||||
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");
|
||||
// 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_any_http_status() {
|
||||
using (var test = new HttpTest()) {
|
||||
test.RespondWith(500, "epic fail");
|
||||
try {
|
||||
var result = await "http://www.api.com".AllowAnyHttpStatus().GetAsync();
|
||||
Assert.IsFalse(result.IsSuccessStatusCode);
|
||||
}
|
||||
catch (Exception) {
|
||||
Assert.Fail("Exception should not have been thrown.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test, ExpectedException(typeof(FlurlHttpException))]
|
||||
public async Task can_override_settings_fluently() {
|
||||
using (var test = new HttpTest()) {
|
||||
FlurlHttp.GlobalSettings.AllowedHttpStatusRange = "*";
|
||||
test.RespondWith(500, "epic fail");
|
||||
await "http://www.api.com".ConfigureClient(c => c.AllowedHttpStatusRange = "2xx").GetAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
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 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));
|
||||
Assert.AreEqual(client.HttpClient.Timeout, TimeSpan.FromSeconds(15));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void can_set_timeout_in_seconds() {
|
||||
var client = "http://www.api.com".WithTimeout(15);
|
||||
Assert.AreEqual(client.HttpClient.Timeout, TimeSpan.FromSeconds(15));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void can_set_header() {
|
||||
var client = "http://www.api.com".WithHeader("a", 1);
|
||||
|
||||
var headers = client.HttpClient.DefaultRequestHeaders.ToList();
|
||||
Assert.AreEqual(1, headers.Count);
|
||||
Assert.AreEqual("a", headers[0].Key);
|
||||
CollectionAssert.AreEqual(headers[0].Value, new[] { "1" });
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void can_set_headers_from_anon_object() {
|
||||
var client = "http://www.api.com".WithHeaders(new { a = "b", one = 2 });
|
||||
|
||||
var headers = client.HttpClient.DefaultRequestHeaders.ToList();
|
||||
Assert.AreEqual(2, headers.Count);
|
||||
Assert.AreEqual("a", headers[0].Key);
|
||||
CollectionAssert.AreEqual(headers[0].Value, new[] { "b" });
|
||||
Assert.AreEqual("one", headers[1].Key);
|
||||
CollectionAssert.AreEqual(headers[1].Value, new[] { "2" });
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void can_set_headers_from_dictionary() {
|
||||
var client = "http://www.api.com".WithHeaders(new Dictionary<string, object> { { "a", "b" }, { "one", 2 } });
|
||||
|
||||
var headers = client.HttpClient.DefaultRequestHeaders.ToList();
|
||||
Assert.AreEqual(2, headers.Count);
|
||||
Assert.AreEqual("a", headers[0].Key);
|
||||
CollectionAssert.AreEqual(headers[0].Value, new[] { "b" });
|
||||
Assert.AreEqual("one", headers[1].Key);
|
||||
CollectionAssert.AreEqual(headers[1].Value, new[] { "2" });
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void can_setup_basic_auth() {
|
||||
var client = "http://www.api.com".WithBasicAuth("user", "pass");
|
||||
|
||||
var header = client.HttpClient.DefaultRequestHeaders.First();
|
||||
Assert.AreEqual("Authorization", header.Key);
|
||||
Assert.AreEqual("Basic dXNlcjpwYXNz", header.Value.First());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void can_setup_oauth_bearer_token() {
|
||||
var client = "http://www.api.com".WithOAuthBearerToken("mytoken");
|
||||
|
||||
var header = client.HttpClient.DefaultRequestHeaders.First();
|
||||
Assert.AreEqual("Authorization", header.Key);
|
||||
Assert.AreEqual("Bearer mytoken", header.Value.First());
|
||||
}
|
||||
|
||||
[Test]
|
||||
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");
|
||||
// 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_any_http_status() {
|
||||
using (var test = new HttpTest()) {
|
||||
test.RespondWith(500, "epic fail");
|
||||
try {
|
||||
var result = await "http://www.api.com".AllowAnyHttpStatus().GetAsync();
|
||||
Assert.IsFalse(result.IsSuccessStatusCode);
|
||||
}
|
||||
catch (Exception) {
|
||||
Assert.Fail("Exception should not have been thrown.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test, ExpectedException(typeof(FlurlHttpException))]
|
||||
public async Task can_override_settings_fluently() {
|
||||
using (var test = new HttpTest()) {
|
||||
FlurlHttp.GlobalSettings.AllowedHttpStatusRange = "*";
|
||||
test.RespondWith(500, "epic fail");
|
||||
await "http://www.api.com".ConfigureClient(c => c.AllowedHttpStatusRange = "2xx").GetAsync();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task can_share_HttpClient_with_different_urls() {
|
||||
var client1 = new FlurlClient("http://www.api.com/for-client1").WithCookie("mycookie", "123");
|
||||
var client2 = client1.WithUrl("http://www.api.com/for-client2");
|
||||
var client3 = client1.WithUrl("http://www.api.com/for-client3");
|
||||
var client4 = client2.WithUrl("http://www.api.com/for-client4");
|
||||
|
||||
CollectionAssert.AreEquivalent(client1.GetCookies(), client2.GetCookies());
|
||||
CollectionAssert.AreEquivalent(client1.GetCookies(), client3.GetCookies());
|
||||
CollectionAssert.AreEquivalent(client1.GetCookies(), client4.GetCookies());
|
||||
var urls = new[] { client1, client2, client3, client4 }.Select(c => c.Url.ToString());
|
||||
CollectionAssert.AllItemsAreUnique(urls);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task disposing_FlurlClient_doesnt_dispose_shared_HttpClient() {
|
||||
var client1 = new FlurlClient("http://www.api.com/for-client1").WithCookie("mycookie", "123");
|
||||
var client2 = client1.WithUrl("http://www.api.com/for-client2");
|
||||
var client3 = client1.WithUrl("http://www.api.com/for-client3");
|
||||
var client4 = client2.WithUrl("http://www.api.com/for-client4");
|
||||
|
||||
client2.Dispose();
|
||||
client3.Dispose();
|
||||
|
||||
CollectionAssert.IsEmpty(client2.GetCookies());
|
||||
CollectionAssert.IsEmpty(client3.GetCookies());
|
||||
|
||||
CollectionAssert.IsNotEmpty(client1.GetCookies());
|
||||
CollectionAssert.IsNotEmpty(client4.GetCookies());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user