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
2 changes: 1 addition & 1 deletion src/RestSharp/Authenticators/AuthenticatorBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ public abstract class AuthenticatorBase : IAuthenticator {
protected abstract ValueTask<Parameter> GetAuthenticationParameter(string accessToken);

public async ValueTask Authenticate(RestClient client, RestRequest request)
=> request.AddOrUpdateParameter(await GetAuthenticationParameter(Token));
=> request.AddOrUpdateParameter(await GetAuthenticationParameter(Token).ConfigureAwait(false));
}
4 changes: 2 additions & 2 deletions src/RestSharp/Extensions/MiscExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ public static async Task<byte[]> ReadAsBytes(this Stream input, CancellationToke

int read;
#if NETSTANDARD
while ((read = await input.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) > 0)
while ((read = await input.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) > 0)
#else
while ((read = await input.ReadAsync(buffer, cancellationToken)) > 0)
while ((read = await input.ReadAsync(buffer, cancellationToken).ConfigureAwait(false)) > 0)
#endif
ms.Write(buffer, 0, read);

Expand Down
43 changes: 43 additions & 0 deletions src/RestSharp/Response/ResponseHandling.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright © 2009-2020 John Sheehan, Andrew Young, Alexey Zimarev and RestSharp community
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

using System.Text;

namespace RestSharp;

static class ResponseHandling {
public static string GetResponseString(this HttpResponseMessage response, byte[] bytes) {
var encodingString = response.Content.Headers.ContentEncoding.FirstOrDefault();
var encoding = encodingString != null ? TryGetEncoding(encodingString) : Encoding.Default;
return encoding.GetString(bytes);

Encoding TryGetEncoding(string es) {
try {
return Encoding.GetEncoding(es);
}
catch {
return Encoding.Default;
}
}
}

public static Task<Stream?> ReadResponse(this HttpResponseMessage response, CancellationToken cancellationToken) {
#if NETSTANDARD
return response.Content.ReadAsStreamAsync();
# else
return response.Content.ReadAsStreamAsync(cancellationToken);
#endif
}
}
50 changes: 13 additions & 37 deletions src/RestSharp/Response/RestResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@

using System.Diagnostics;
using System.Net;
using System.Net.Http.Headers;
using System.Text;
using RestSharp.Extensions;

// ReSharper disable SuggestBaseTypeForParameter
Expand Down Expand Up @@ -51,8 +49,7 @@ public static RestResponse<T> FromResponse(RestResponse response)
Server = response.Server,
StatusCode = response.StatusCode,
StatusDescription = response.StatusDescription,
Request = response.Request,
ResponseMessage = response.ResponseMessage
Request = response.Request
};
}

Expand All @@ -67,40 +64,13 @@ internal static async Task<RestResponse> FromHttpResponse(
CookieCollection cookieCollection,
CancellationToken cancellationToken
) {
return request.AdvancedResponseWriter?.Invoke(httpResponse) ?? await GetDefaultResponse();
return request.AdvancedResponseWriter?.Invoke(httpResponse) ?? await GetDefaultResponse().ConfigureAwait(false);

async Task<RestResponse> GetDefaultResponse() {
byte[]? bytes;
string? content;

if (request.ResponseWriter != null) {
#if NETSTANDARD
var stream = await httpResponse.Content.ReadAsStreamAsync();
# else
var stream = await httpResponse.Content.ReadAsStreamAsync(cancellationToken);
#endif
var converted = request.ResponseWriter(stream);

if (converted == null) {
bytes = null;
content = null;
}
else {
bytes = await converted.ReadAsBytes(cancellationToken);
var encodingString = httpResponse.Content.Headers.ContentEncoding.FirstOrDefault();
var encoding = encodingString != null ? Encoding.GetEncoding(encodingString) : Encoding.UTF8;
content = encoding.GetString(bytes);
}
}
else {
#if NETSTANDARD
bytes = await httpResponse.Content.ReadAsByteArrayAsync();
content = await httpResponse.Content.ReadAsStringAsync();
# else
bytes = await httpResponse.Content.ReadAsByteArrayAsync(cancellationToken);
content = await httpResponse.Content.ReadAsStringAsync(cancellationToken);
#endif
}
var readTask = request.ResponseWriter == null ? ReadResponse() : ReadAndConvertResponse();
using var stream = await readTask.ConfigureAwait(false);
var bytes = stream == null ? null : await stream.ReadAsBytes(cancellationToken).ConfigureAwait(false);
var content = bytes == null ? null : httpResponse.GetResponseString(bytes);

return new RestResponse {
Content = content,
Expand All @@ -116,11 +86,17 @@ async Task<RestResponse> GetDefaultResponse() {
StatusDescription = httpResponse.ReasonPhrase,
IsSuccessful = httpResponse.IsSuccessStatusCode,
Request = request,
ResponseMessage = httpResponse,
Headers = httpResponse.Headers.GetHeaderParameters(),
ContentHeaders = httpResponse.Content.Headers.GetHeaderParameters(),
Cookies = cookieCollection
};

Task<Stream?> ReadResponse() => httpResponse.ReadResponse(cancellationToken);

async Task<Stream?> ReadAndConvertResponse() {
using var original = await ReadResponse().ConfigureAwait(false);
return request.ResponseWriter!(original!);
}
}
}
}
2 changes: 0 additions & 2 deletions src/RestSharp/Response/RestResponseBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ public abstract class RestResponseBase {
/// Mainly for debugging if ResponseStatus is not OK
/// </remarks>
public RestRequest? Request { get; set; }

public HttpResponseMessage? ResponseMessage { get; init; }

/// <summary>
/// MIME content type of response
Expand Down
70 changes: 20 additions & 50 deletions src/RestSharp/RestClient.Async.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,18 @@ public partial class RestClient {
/// <param name="request">Request to be executed</param>
/// <param name="cancellationToken">Cancellation token</param>
public async Task<RestResponse> ExecuteAsync(RestRequest request, CancellationToken cancellationToken = default) {
var internalResponse = await ExecuteInternal(request, cancellationToken);
var internalResponse = await ExecuteInternal(request, cancellationToken).ConfigureAwait(false);

var response = new RestResponse();

response = internalResponse.Exception == null
? await RestResponse.FromHttpResponse(
internalResponse.ResponseMessage!,
request,
CookieContainer.GetCookies(internalResponse.Url),
cancellationToken
)
internalResponse.ResponseMessage!,
request,
CookieContainer.GetCookies(internalResponse.Url),
cancellationToken
)
.ConfigureAwait(false)
: ReturnErrorOrThrow(response, internalResponse.Exception, internalResponse.TimeoutToken);

response.Request = request;
Expand All @@ -47,7 +48,7 @@ async Task<InternalResponse> ExecuteInternal(RestRequest request, CancellationTo
using var requestContent = new RequestContent(this, request);

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

var httpMethod = AsHttpMethod(request.Method);
var url = BuildUri(request);
Expand All @@ -67,12 +68,12 @@ async Task<InternalResponse> ExecuteInternal(RestRequest request, CancellationTo
message.AddHeaders(headers);

if (request.OnBeforeRequest != null)
await request.OnBeforeRequest(message);
await request.OnBeforeRequest(message).ConfigureAwait(false);

var responseMessage = await HttpClient.SendAsync(message, request.CompletionOption, ct);
var responseMessage = await HttpClient.SendAsync(message, request.CompletionOption, ct).ConfigureAwait(false);

if (request.OnAfterRequest != null)
await request.OnAfterRequest(responseMessage);
await request.OnAfterRequest(responseMessage).ConfigureAwait(false);

return new InternalResponse(responseMessage, url, null, timeoutCts.Token);
}
Expand All @@ -89,8 +90,9 @@ record InternalResponse(HttpResponseMessage? ResponseMessage, Uri Url, Exception
/// <param name="request">Pre-configured request instance.</param>
/// <param name="cancellationToken"></param>
/// <returns>The downloaded stream.</returns>
[PublicAPI]
public async Task<Stream?> DownloadStreamAsync(RestRequest request, CancellationToken cancellationToken = default) {
var response = await ExecuteInternal(request, cancellationToken);
var response = await ExecuteInternal(request, cancellationToken).ConfigureAwait(false);

if (response.Exception != null) {
return Options.ThrowOnAnyError ? throw response.Exception : null;
Expand All @@ -99,18 +101,11 @@ record InternalResponse(HttpResponseMessage? ResponseMessage, Uri Url, Exception
if (response.ResponseMessage == null) return null;

if (request.ResponseWriter != null) {
#if NETSTANDARD
var stream = await response.ResponseMessage.Content.ReadAsStreamAsync();
# else
var stream = await response.ResponseMessage.Content.ReadAsStreamAsync(cancellationToken);
#endif
return request.ResponseWriter(stream);
using var stream = await response.ResponseMessage.ReadResponse(cancellationToken).ConfigureAwait(false);
return request.ResponseWriter(stream!);
}
#if NETSTANDARD
return await response.ResponseMessage.Content.ReadAsStreamAsync();
# else
return await response.ResponseMessage.Content.ReadAsStreamAsync(cancellationToken);
#endif

return await response.ResponseMessage.ReadResponse(cancellationToken).ConfigureAwait(false);
}

/// <summary>
Expand All @@ -119,35 +114,10 @@ record InternalResponse(HttpResponseMessage? ResponseMessage, Uri Url, Exception
/// <param name="request">Pre-configured request instance.</param>
/// <param name="cancellationToken"></param>
/// <returns>The downloaded file.</returns>
[PublicAPI]
public async Task<byte[]?> DownloadDataAsync(RestRequest request, CancellationToken cancellationToken = default) {
var response = await ExecuteInternal(request, cancellationToken);

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

if (response.ResponseMessage == null) return null;

byte[]? bytes;

if (request.ResponseWriter != null) {
#if NETSTANDARD
var stream = await response.ResponseMessage.Content.ReadAsStreamAsync();
# else
var stream = await response.ResponseMessage.Content.ReadAsStreamAsync(cancellationToken);
#endif
var converted = request.ResponseWriter(stream);
bytes = converted == null ? null : await converted.ReadAsBytes(cancellationToken);
}
else {
#if NETSTANDARD
bytes = await response.ResponseMessage.Content.ReadAsByteArrayAsync();
# else
bytes = await response.ResponseMessage.Content.ReadAsByteArrayAsync(cancellationToken);
#endif
}

return bytes;
using var stream = await DownloadStreamAsync(request, cancellationToken).ConfigureAwait(false);
return stream == null ? null : await stream.ReadAsBytes(cancellationToken).ConfigureAwait(false);
}

RestResponse ReturnErrorOrThrow(RestResponse response, Exception exception, CancellationToken timeoutToken) {
Expand Down
20 changes: 4 additions & 16 deletions src/RestSharp/RestClientExtensions.Json.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,22 +39,10 @@ public static partial class RestClientExtensions {
CancellationToken cancellationToken = default
) {
var props = parameters.GetProperties();
var query = new List<Parameter>();

foreach (var (name, value) in props) {
var param = $"{name}";

if (resource.Contains(param)) {
resource = resource.Replace(param, value);
}
else {
query.Add(new QueryParameter(name, value));
}
}

var request = new RestRequest(resource);

foreach (var parameter in query) {
foreach (var (name, value) in props) {
Parameter parameter = resource.Contains($"{name}") ? new UrlSegmentParameter(name, value!) : new QueryParameter(name, value);
request.AddParameter(parameter);
}

Expand Down Expand Up @@ -99,7 +87,7 @@ public static async Task<HttpStatusCode> PostJsonAsync<TRequest>(
CancellationToken cancellationToken = default
) where TRequest : class {
var restRequest = new RestRequest().AddJsonBody(request);
var response = await client.PostAsync(restRequest, cancellationToken);
var response = await client.PostAsync(restRequest, cancellationToken).ConfigureAwait(false);
return response.StatusCode;
}

Expand Down Expand Up @@ -141,7 +129,7 @@ public static async Task<HttpStatusCode> PutJsonAsync<TRequest>(
CancellationToken cancellationToken = default
) where TRequest : class {
var restRequest = new RestRequest().AddJsonBody(request);
var response = await client.PutAsync(restRequest, cancellationToken);
var response = await client.PutAsync(restRequest, cancellationToken).ConfigureAwait(false);
return response.StatusCode;
}
}
Loading