Skip to content

Remaining patches all in one commit #1827

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
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
36 changes: 31 additions & 5 deletions src/RestSharp/Request/RestRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
// limitations under the License.

using System.Net;
using System.Net.Http.Headers;
using RestSharp.Authenticators;
using RestSharp.Extensions;
// ReSharper disable UnusedAutoPropertyAccessor.Global

Expand All @@ -22,8 +24,8 @@ namespace RestSharp;
/// Container for data used to make requests
/// </summary>
public class RestRequest {
readonly Func<HttpResponseMessage, RestResponse>? _advancedResponseHandler;
readonly Func<Stream, Stream?>? _responseWriter;
Func<HttpResponseMessage, RestResponse>? _advancedResponseHandler;
Func<Stream, Stream?>? _responseWriter;

/// <summary>
/// Default constructor
Expand Down Expand Up @@ -111,7 +113,11 @@ public RestRequest(Uri resource, Method method = Method.Get)
public Method Method { get; set; }

/// <summary>
/// Custom request timeout
/// Sets the timeout in milliseconds for this requests using this client. Note that there is also a timeout
/// set on the base client, and the the shorter of the two values is what will end up being used. So if you need long
/// timeouts at the request level, you will want to set the value on the client to to a larger value than the maximum
/// you need per request, or set the client to infinite. If this value is 0, an infinite timeout is used (basically
/// it then times out using whatever was configured at the client level).
/// </summary>
public int Timeout { get; set; }

Expand Down Expand Up @@ -170,12 +176,32 @@ public RestRequest(Uri resource, Method method = Method.Get)
/// </summary>
public HttpCompletionOption CompletionOption { get; set; } = HttpCompletionOption.ResponseContentRead;

/// <summary>
/// Explicit Host header value to use in requests independent from the request URI.
/// </summary>
public string? BaseHost { get; set; }

/// <summary>
/// Sets the user agent string to be used for this requests. Defaults to a the client default if not provided.
/// </summary>
public string? UserAgent { get; set; }

/// <summary>
/// Sets the cache policy to use for this request
/// </summary>
public CacheControlHeaderValue? CachePolicy { get; set; }

/// <summary>
/// Authenticator that will be used to populate request with necessary authentication data
/// </summary>
public IAuthenticator? Authenticator { get; set; }

/// <summary>
/// Set this to write response to Stream rather than reading into memory.
/// </summary>
public Func<Stream, Stream?>? ResponseWriter {
get => _responseWriter;
init {
set {
if (AdvancedResponseWriter != null)
throw new ArgumentException(
"AdvancedResponseWriter is not null. Only one response writer can be used."
Expand All @@ -190,7 +216,7 @@ public RestRequest(Uri resource, Method method = Method.Get)
/// </summary>
public Func<HttpResponseMessage, RestResponse>? AdvancedResponseWriter {
get => _advancedResponseHandler;
init {
set {
if (ResponseWriter != null)
throw new ArgumentException("ResponseWriter is not null. Only one response writer can be used.");

Expand Down
10 changes: 10 additions & 0 deletions src/RestSharp/Request/RestRequestExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

using System.Net;
using System.Text.RegularExpressions;
using RestSharp.Authenticators;
using RestSharp.Extensions;
using RestSharp.Serializers;

Expand Down Expand Up @@ -461,6 +462,15 @@ public static RestRequest AddCookie(this RestRequest request, string name, strin
return request;
}

/// <summary>
/// Enable request authentication for this request using the passed in authenticator
/// </summary>
/// <param name="request">Request to attach the authenticator to</param>
/// <param name="authenticator">Authenticator to use</param>
/// <returns></returns>
public static RestRequest UseAuthenticator(this RestRequest request, IAuthenticator authenticator)
=> request.With(x => x.Authenticator = authenticator);

static void CheckAndThrowsForInvalidHost(string name, string value) {
static bool InvalidHost(string host) => Uri.CheckHostName(PortSplitRegex.Split(host)[0]) == UriHostNameType.Unknown;

Expand Down
8 changes: 4 additions & 4 deletions src/RestSharp/RestClient.Async.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ async Task<InternalResponse> ExecuteInternal(RestRequest request, CancellationTo

using var requestContent = new RequestContent(this, request);

if (Authenticator != null) await Authenticator.Authenticate(this, request).ConfigureAwait(false);
if (request.Authenticator != null) await request.Authenticator.Authenticate(this, request).ConfigureAwait(false);

var httpMethod = AsHttpMethod(request.Method);
var url = BuildUri(request);
var message = new HttpRequestMessage(httpMethod, url) { Content = requestContent.BuildContent() };
message.Headers.Host = Options.BaseHost;
message.Headers.CacheControl = Options.CachePolicy;
message.Headers.Host = request.BaseHost;
message.Headers.CacheControl = request.CachePolicy;

using var timeoutCts = new CancellationTokenSource(request.Timeout > 0 ? request.Timeout : int.MaxValue);
using var cts = CancellationTokenSource.CreateLinkedTokenSource(timeoutCts.Token, cancellationToken);
Expand Down Expand Up @@ -111,7 +111,7 @@ record InternalResponse(HttpResponseMessage? ResponseMessage, Uri Url, Exception
var exception = response.Exception ?? response.ResponseMessage?.MaybeException();

if (exception != null) {
return Options.ThrowOnAnyError ? throw exception : null;
throw exception;
}

if (response.ResponseMessage == null) return null;
Expand Down
13 changes: 6 additions & 7 deletions src/RestSharp/RestClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
using System.Net;
using System.Net.Http.Headers;
using System.Text;
using RestSharp.Authenticators;
using RestSharp.Extensions;

// ReSharper disable VirtualMemberCallInConstructor
Expand Down Expand Up @@ -125,6 +124,11 @@ public RestClient(HttpClient httpClient, RestClientOptions options, bool dispose
/// <param name="disposeHandler">Dispose the handler when disposing RestClient, true by default</param>
public RestClient(HttpMessageHandler handler, bool disposeHandler = true) : this(new HttpClient(handler, disposeHandler), true) { }

/// <summary>
/// Returns the currently configured BaseUrl for this RestClient instance
/// </summary>
public Uri? BaseUrl => Options.BaseUrl;

void ConfigureHttpClient(HttpClient httpClient) {
if (Options.MaxTimeout > 0) httpClient.Timeout = TimeSpan.FromMilliseconds(Options.MaxTimeout);

Expand Down Expand Up @@ -161,11 +165,6 @@ void ConfigureHttpMessageHandler(HttpClientHandler handler) {

internal Func<string, Encoding, string> EncodeQuery { get; set; } = (s, encoding) => s.UrlEncode(encoding)!;

/// <summary>
/// Authenticator that will be used to populate request with necessary authentication data
/// </summary>
public IAuthenticator? Authenticator { get; set; }

public ParametersCollection DefaultParameters { get; } = new();

/// <summary>
Expand Down Expand Up @@ -239,4 +238,4 @@ public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
}
}
4 changes: 0 additions & 4 deletions src/RestSharp/RestClientExtensions.Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
//

using System.Text;
using RestSharp.Authenticators;
using RestSharp.Extensions;

namespace RestSharp;
Expand All @@ -41,7 +40,4 @@ public static partial class RestClientExtensions {
/// <returns></returns>
public static RestClient UseQueryEncoder(this RestClient client, Func<string, Encoding, string> queryEncoder)
=> client.With(x => x.EncodeQuery = queryEncoder);

public static RestClient UseAuthenticator(this RestClient client, IAuthenticator authenticator)
=> client.With(x => x.Authenticator = authenticator);
}
55 changes: 42 additions & 13 deletions src/RestSharp/RestClientExtensions.Json.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
//

using System.Net;
using RestSharp.Authenticators;
using RestSharp.Extensions;

namespace RestSharp;
Expand All @@ -25,10 +26,18 @@ public static partial class RestClientExtensions {
/// <param name="client">RestClient instance</param>
/// <param name="resource">Resource URL</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <param name="authenticator">Optional authenticator to use for the request</param>
/// <typeparam name="TResponse">Response object type</typeparam>
/// <returns></returns>
public static Task<TResponse?> GetJsonAsync<TResponse>(this RestClient client, string resource, CancellationToken cancellationToken = default) {
var request = new RestRequest(resource);
/// <returns>Deserialized response object</returns>
public static Task<TResponse?> GetJsonAsync<TResponse>(
this RestClient client,
string resource,
CancellationToken cancellationToken = default,
IAuthenticator? authenticator = null
) {
var request = new RestRequest(resource) {
Authenticator = authenticator
};
return client.GetAsync<TResponse>(request, cancellationToken);
}

Expand All @@ -39,16 +48,20 @@ public static partial class RestClientExtensions {
/// <param name="resource">Resource URL</param>
/// <param name="parameters">Parameters to pass to the request</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <param name="authenticator">Optional authenticator to use for the request</param>
/// <typeparam name="TResponse">Response object type</typeparam>
/// <returns>Deserialized response object</returns>
public static Task<TResponse?> GetJsonAsync<TResponse>(
this RestClient client,
string resource,
object parameters,
CancellationToken cancellationToken = default
CancellationToken cancellationToken = default,
IAuthenticator? authenticator = null
) {
var props = parameters.GetProperties();
var request = new RestRequest(resource);
var request = new RestRequest(resource) {
Authenticator = authenticator
};

foreach (var (name, value) in props) {
Parameter parameter = resource.Contains($"{name}") ? new UrlSegmentParameter(name, value!) : new QueryParameter(name, value);
Expand All @@ -66,16 +79,20 @@ public static partial class RestClientExtensions {
/// <param name="resource">Resource URL</param>
/// <param name="request">Request object, must be serializable to JSON</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <param name="authenticator">Optional authenticator to use for the request</param>
/// <typeparam name="TRequest">Request object type</typeparam>
/// <typeparam name="TResponse">Response object type</typeparam>
/// <returns>Deserialized response object</returns>
public static Task<TResponse?> PostJsonAsync<TRequest, TResponse>(
this RestClient client,
string resource,
TRequest request,
CancellationToken cancellationToken = default
CancellationToken cancellationToken = default,
IAuthenticator? authenticator = null
) where TRequest : class {
var restRequest = new RestRequest(resource).AddJsonBody(request);
var restRequest = new RestRequest(resource) {
Authenticator = authenticator
}.AddJsonBody(request);
return client.PostAsync<TResponse>(restRequest, cancellationToken);
}

Expand All @@ -87,15 +104,19 @@ public static partial class RestClientExtensions {
/// <param name="resource">Resource URL</param>
/// <param name="request">Request object, must be serializable to JSON</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <param name="authenticator">Optional authenticator to use for the request</param>
/// <typeparam name="TRequest">Request object type</typeparam>
/// <returns>Response status code</returns>
public static async Task<HttpStatusCode> PostJsonAsync<TRequest>(
this RestClient client,
string resource,
TRequest request,
CancellationToken cancellationToken = default
CancellationToken cancellationToken = default,
IAuthenticator? authenticator = null
) where TRequest : class {
var restRequest = new RestRequest(resource).AddJsonBody(request);
var restRequest = new RestRequest(resource) {
Authenticator = authenticator
}.AddJsonBody(request);
var response = await client.PostAsync(restRequest, cancellationToken).ConfigureAwait(false);
return response.StatusCode;
}
Expand All @@ -108,16 +129,20 @@ public static async Task<HttpStatusCode> PostJsonAsync<TRequest>(
/// <param name="resource">Resource URL</param>
/// <param name="request">Request object, must be serializable to JSON</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <param name="authenticator">Optional authenticator to use for the request</param>
/// <typeparam name="TRequest">Request object type</typeparam>
/// <typeparam name="TResponse">Response object type</typeparam>
/// <returns>Deserialized response object</returns>
public static Task<TResponse?> PutJsonAsync<TRequest, TResponse>(
this RestClient client,
string resource,
TRequest request,
CancellationToken cancellationToken = default
CancellationToken cancellationToken = default,
IAuthenticator? authenticator = null
) where TRequest : class {
var restRequest = new RestRequest(resource).AddJsonBody(request);
var restRequest = new RestRequest(resource) {
Authenticator = authenticator
}.AddJsonBody(request);
return client.PutAsync<TResponse>(restRequest, cancellationToken);
}

Expand All @@ -129,15 +154,19 @@ public static async Task<HttpStatusCode> PostJsonAsync<TRequest>(
/// <param name="resource">Resource URL</param>
/// <param name="request">Request object, must be serializable to JSON</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <param name="authenticator">Optional authenticator to use for the request</param>
/// <typeparam name="TRequest">Request object type</typeparam>
/// <returns>Response status code</returns>
public static async Task<HttpStatusCode> PutJsonAsync<TRequest>(
this RestClient client,
string resource,
TRequest request,
CancellationToken cancellationToken = default
CancellationToken cancellationToken = default,
IAuthenticator? authenticator = null
) where TRequest : class {
var restRequest = new RestRequest(resource).AddJsonBody(request);
var restRequest = new RestRequest(resource) {
Authenticator = authenticator
}.AddJsonBody(request);
var response = await client.PutAsync(restRequest, cancellationToken).ConfigureAwait(false);
return response.StatusCode;
}
Expand Down
13 changes: 8 additions & 5 deletions src/RestSharp/RestClientExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

using System.Runtime.CompilerServices;
using RestSharp.Authenticators;
using RestSharp.Extensions;
using RestSharp.Serializers;

Expand Down Expand Up @@ -306,18 +307,20 @@ public static async Task<RestResponse> DeleteAsync(this RestClient client, RestR
/// Reads a stream returned by the specified endpoint, deserializes each line to JSON and returns each object asynchronously.
/// It is required for each JSON object to be returned in a single line.
/// </summary>
/// <param name="client"></param>
/// <param name="resource"></param>
/// <param name="cancellationToken"></param>
/// <param name="client">Rest client</param>
/// <param name="resource">Resource URL</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <param name="authenticator">Optional authenticator to use for the request</param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
[PublicAPI]
public static async IAsyncEnumerable<T> StreamJsonAsync<T>(
this RestClient client,
string resource,
[EnumeratorCancellation] CancellationToken cancellationToken
[EnumeratorCancellation] CancellationToken cancellationToken,
IAuthenticator? authenticator = null
) {
var request = new RestRequest(resource);
var request = new RestRequest(resource) { Authenticator = authenticator };

#if NETSTANDARD
using var stream = await client.DownloadStreamAsync(request, cancellationToken).ConfigureAwait(false);
Expand Down
Loading