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/Parameters/Parameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ public abstract record Parameter(string? Name, object? Value, ParameterType Type
public override string ToString() => $"{Name}={Value}";

public static Parameter CreateParameter(string? name, object? value, ParameterType type, bool encode = true)
// ReSharper disable once SwitchExpressionHandlesSomeKnownEnumValuesWithExceptionInDefault
=> type switch {
ParameterType.GetOrPost => new GetOrPostParameter(name!, value?.ToString(), encode),
ParameterType.UrlSegment => new UrlSegmentParameter(name!, value?.ToString()!, encode),
ParameterType.HttpHeader => new HeaderParameter(name, value?.ToString()),
ParameterType.RequestBody => new BodyParameter(name, value!, Serializers.ContentType.Plain),
ParameterType.QueryString => new QueryParameter(name!, value?.ToString(), encode),
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
};
Expand Down
5 changes: 4 additions & 1 deletion src/RestSharp/Request/RestRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,10 @@ public Func<HttpResponseMessage, RestResponse>? AdvancedResponseWriter {
/// Removes a parameter object from the request parameters
/// </summary>
/// <param name="parameter">Parameter to remove</param>
public void RemoveParameter(Parameter parameter) => Parameters.RemoveParameter(parameter);
public RestRequest RemoveParameter(Parameter parameter) {
Parameters.RemoveParameter(parameter);
return this;
}

internal RestRequest AddFile(FileParameter file) => this.With(x => x._files.Add(file));
}
55 changes: 33 additions & 22 deletions src/RestSharp/Request/RestRequestExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,14 @@ public static RestRequest AddOrUpdateHeaders(this RestRequest request, ICollecti
/// <param name="encode">Encode the value or not, default true</param>
/// <returns></returns>
public static RestRequest AddParameter(this RestRequest request, string? name, object value, ParameterType type, bool encode = true)
=> request.AddParameter(Parameter.CreateParameter(name, value, type, encode));
=> type == ParameterType.RequestBody
? request.AddBodyParameter(name, value)
: request.AddParameter(Parameter.CreateParameter(name, value, type, encode));

static RestRequest AddBodyParameter(this RestRequest request, string? name, object value)
=> name != null && name.Contains("/")
? request.AddBody(value, name)
: request.AddParameter(new BodyParameter(name, value, ContentType.Plain));

/// <summary>
/// Adds or updates request parameter of a given type. It will create a typed parameter instance based on the type argument.
Expand All @@ -218,8 +225,13 @@ public static RestRequest AddParameter(this RestRequest request, string? name, o
/// <param name="type">Enum value specifying what kind of parameter is being added</param>
/// <param name="encode">Encode the value or not, default true</param>
/// <returns></returns>
public static RestRequest AddOrUpdateParameter(this RestRequest request, string name, object value, ParameterType type, bool encode = true)
=> request.AddOrUpdateParameter(Parameter.CreateParameter(name, value, type, encode));
public static RestRequest AddOrUpdateParameter(this RestRequest request, string name, object value, ParameterType type, bool encode = true) {
request.RemoveParameter(name, type);

return type == ParameterType.RequestBody
? request.AddBodyParameter(name, value)
: request.AddOrUpdateParameter(Parameter.CreateParameter(name, value, type, encode));
}

/// <summary>
/// Adds or updates request parameter, given the parameter instance, for example <see cref="QueryParameter"/> or <see cref="UrlSegmentParameter"/>.
Expand All @@ -228,13 +240,12 @@ public static RestRequest AddOrUpdateParameter(this RestRequest request, string
/// <param name="request">Request instance</param>
/// <param name="parameter">Parameter instance</param>
/// <returns></returns>
public static RestRequest AddOrUpdateParameter(this RestRequest request, Parameter parameter) {
var p = request.Parameters.FirstOrDefault(x => x.Name == parameter.Name && x.Type == parameter.Type);

if (p != null) request.RemoveParameter(p);
public static RestRequest AddOrUpdateParameter(this RestRequest request, Parameter parameter)
=> request.RemoveParameter(parameter.Name, parameter.Type).AddParameter(parameter);

request.AddParameter(parameter);
return request;
static RestRequest RemoveParameter(this RestRequest request, string? name, ParameterType type) {
var p = request.Parameters.FirstOrDefault(x => x.Name == name && x.Type == type);
return p != null ? request.RemoveParameter(p) : request;
}

/// <summary>
Expand All @@ -245,8 +256,7 @@ public static RestRequest AddOrUpdateParameter(this RestRequest request, Paramet
/// <param name="parameters">Collection of parameter instances</param>
/// <returns></returns>
public static RestRequest AddOrUpdateParameters(this RestRequest request, IEnumerable<Parameter> parameters) {
foreach (var parameter in parameters)
request.AddOrUpdateParameter(parameter);
foreach (var parameter in parameters) request.AddOrUpdateParameter(parameter);

return request;
}
Expand Down Expand Up @@ -304,15 +314,15 @@ public static RestRequest AddFile(
public static RestRequest AddBody(this RestRequest request, object obj, string? contentType = null) {
if (contentType == null) {
return request.RequestFormat switch {
DataFormat.Json => request.AddJsonBody(obj, contentType ?? ContentType.Json),
DataFormat.Xml => request.AddXmlBody(obj, contentType ?? ContentType.Xml),
DataFormat.Binary => request.AddParameter(new BodyParameter("", obj, contentType ?? ContentType.Binary)),
_ => request.AddParameter(new BodyParameter("", obj.ToString()!, contentType ?? ContentType.Plain))
DataFormat.Json => request.AddJsonBody(obj),
DataFormat.Xml => request.AddXmlBody(obj),
DataFormat.Binary => request.AddParameter(new BodyParameter("", obj, ContentType.Binary)),
_ => request.AddParameter(new BodyParameter("", obj.ToString()!, ContentType.Plain))
};
}

return
obj is string str ? request.AddParameter(new BodyParameter("", str, contentType)) :
obj is string str ? request.AddStringBody(str, contentType) :
obj is byte[] bytes ? request.AddParameter(new BodyParameter("", bytes, contentType, DataFormat.Binary)) :
contentType.Contains("xml") ? request.AddXmlBody(obj, contentType) :
contentType.Contains("json") ? request.AddJsonBody(obj, contentType) :
Expand Down Expand Up @@ -352,7 +362,7 @@ public static RestRequest AddStringBody(this RestRequest request, string body, s
/// <returns></returns>
public static RestRequest AddJsonBody<T>(this RestRequest request, T obj, string contentType = ContentType.Json) where T : class {
request.RequestFormat = DataFormat.Json;
return request.AddParameter(new JsonParameter("", obj, contentType));
return obj is string str ? request.AddStringBody(str, DataFormat.Json) : request.AddParameter(new JsonParameter("", obj, contentType));
}

/// <summary>
Expand All @@ -366,8 +376,10 @@ public static RestRequest AddJsonBody<T>(this RestRequest request, T obj, string
public static RestRequest AddXmlBody<T>(this RestRequest request, T obj, string contentType = ContentType.Xml, string xmlNamespace = "")
where T : class {
request.RequestFormat = DataFormat.Xml;
request.AddParameter(new XmlParameter("", obj, xmlNamespace, contentType));
return request;

return obj is string str
? request.AddStringBody(str, DataFormat.Xml)
: request.AddParameter(new XmlParameter("", obj, xmlNamespace, contentType));
}

/// <summary>
Expand Down Expand Up @@ -401,7 +413,6 @@ static void CheckAndThrowsDuplicateKeys(ICollection<KeyValuePair<string, string>
.Select(group => group.Key)
.ToList();

if (duplicateKeys.Any())
throw new ArgumentException($"Duplicate header names exist: {string.Join(", ", duplicateKeys)}");
if (duplicateKeys.Any()) throw new ArgumentException($"Duplicate header names exist: {string.Join(", ", duplicateKeys)}");
}
}
}
25 changes: 17 additions & 8 deletions src/RestSharp/RestClient.Async.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public async Task<RestResponse> ExecuteAsync(RestRequest request, CancellationTo
response.Request = request;
response.Request.IncreaseNumAttempts();

return Options.ThrowOnAnyError ? ThrowIfError(response) : response;
return Options.ThrowOnAnyError ? response.ThrowIfError() : response;
}

async Task<InternalResponse> ExecuteInternal(RestRequest request, CancellationToken cancellationToken) {
Expand Down Expand Up @@ -130,13 +130,6 @@ static RestResponse AddError(RestResponse response, Exception exception, Cancell
bool TimedOut() => timeoutToken.IsCancellationRequested || exception.Message.Contains("HttpClient.Timeout");
}

internal static RestResponse ThrowIfError(RestResponse response) {
var exception = response.GetException();
if (exception != null) throw exception;

return response;
}

static HttpMethod AsHttpMethod(Method method)
=> method switch {
Method.Get => HttpMethod.Get,
Expand All @@ -155,4 +148,20 @@ static HttpMethod AsHttpMethod(Method method)
Method.Search => new HttpMethod("SEARCH"),
_ => throw new ArgumentOutOfRangeException()
};
}

public static class ResponseThrowExtension {
public static RestResponse ThrowIfError(this RestResponse response) {
var exception = response.GetException();
if (exception != null) throw exception;

return response;
}

public static RestResponse<T> ThrowIfError<T>(this RestResponse<T> response) {
var exception = response.GetException();
if (exception != null) throw exception;

return response;
}
}
6 changes: 4 additions & 2 deletions src/RestSharp/RestClientExtensions.Params.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@ public static RestClient AddDefaultParameter(this RestClient client, string name
/// <param name="value">Value of the parameter</param>
/// <param name="type">The type of parameter to add</param>
/// <returns>This request</returns>
public static RestClient AddDefaultParameter(this RestClient client, string name, object value, ParameterType type)
=> client.AddDefaultParameter(Parameter.CreateParameter(name, value, type));
public static RestClient AddDefaultParameter(this RestClient client, string name, object value, ParameterType type) {
if (type == ParameterType.RequestBody) throw new ArgumentException("Default parameter cannot be Body", nameof(type));
return client.AddDefaultParameter(Parameter.CreateParameter(name, value, type));
}

/// <summary>
/// Adds a default header to the RestClient. Used on every request made by this client instance.
Expand Down
42 changes: 14 additions & 28 deletions src/RestSharp/RestClientExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,14 +160,12 @@ public static Task<RestResponse<T>> ExecuteAsync<T>(
/// <returns></returns>
public static async Task<T?> GetAsync<T>(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
var response = await client.ExecuteGetAsync<T>(request, cancellationToken).ConfigureAwait(false);
RestClient.ThrowIfError(response);
return response.Data;
return response.ThrowIfError().Data;
}

public static async Task<RestResponse> GetAsync(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
var response = await client.ExecuteGetAsync(request, cancellationToken).ConfigureAwait(false);
RestClient.ThrowIfError(response);
return response;
return response.ThrowIfError();
}

/// <summary>
Expand All @@ -181,17 +179,15 @@ public static async Task<RestResponse> GetAsync(this RestClient client, RestRequ
/// <returns></returns>
public static async Task<T?> PostAsync<T>(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
var response = await client.ExecutePostAsync<T>(request, cancellationToken).ConfigureAwait(false);
RestClient.ThrowIfError(response);
return response.Data;
return response.ThrowIfError().Data;
}

public static RestResponse Post(this RestClient client, RestRequest request)
=> AsyncHelpers.RunSync(() => client.PostAsync(request));

public static async Task<RestResponse> PostAsync(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
var response = await client.ExecutePostAsync(request, cancellationToken).ConfigureAwait(false);
RestClient.ThrowIfError(response);
return response;
return response.ThrowIfError();
}

/// <summary>
Expand All @@ -205,14 +201,12 @@ public static async Task<RestResponse> PostAsync(this RestClient client, RestReq
/// <returns></returns>
public static async Task<T?> PutAsync<T>(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
var response = await client.ExecuteAsync<T>(request, Method.Put, cancellationToken).ConfigureAwait(false);
RestClient.ThrowIfError(response);
return response.Data;
return response.ThrowIfError().Data;
}

public static async Task<RestResponse> PutAsync(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
var response = await client.ExecuteAsync(request, Method.Put, cancellationToken).ConfigureAwait(false);
RestClient.ThrowIfError(response);
return response;
return response.ThrowIfError();
}

/// <summary>
Expand All @@ -226,14 +220,12 @@ public static async Task<RestResponse> PutAsync(this RestClient client, RestRequ
/// <returns></returns>
public static async Task<T?> HeadAsync<T>(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
var response = await client.ExecuteAsync<T>(request, Method.Head, cancellationToken).ConfigureAwait(false);
RestClient.ThrowIfError(response);
return response.Data;
return response.ThrowIfError().Data;
}

public static async Task<RestResponse> HeadAsync(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
var response = await client.ExecuteAsync(request, Method.Head, cancellationToken).ConfigureAwait(false);
RestClient.ThrowIfError(response);
return response;
return response.ThrowIfError();
}

/// <summary>
Expand All @@ -247,14 +239,12 @@ public static async Task<RestResponse> HeadAsync(this RestClient client, RestReq
/// <returns></returns>
public static async Task<T?> OptionsAsync<T>(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
var response = await client.ExecuteAsync<T>(request, Method.Options, cancellationToken).ConfigureAwait(false);
RestClient.ThrowIfError(response);
return response.Data;
return response.ThrowIfError().Data;
}

public static async Task<RestResponse> OptionsAsync(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
var response = await client.ExecuteAsync(request, Method.Options, cancellationToken).ConfigureAwait(false);
RestClient.ThrowIfError(response);
return response;
return response.ThrowIfError();
}

/// <summary>
Expand All @@ -268,14 +258,12 @@ public static async Task<RestResponse> OptionsAsync(this RestClient client, Rest
/// <returns></returns>
public static async Task<T?> PatchAsync<T>(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
var response = await client.ExecuteAsync<T>(request, Method.Patch, cancellationToken).ConfigureAwait(false);
RestClient.ThrowIfError(response);
return response.Data;
return response.ThrowIfError().Data;
}

public static async Task<RestResponse> PatchAsync(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
var response = await client.ExecuteAsync(request, Method.Patch, cancellationToken).ConfigureAwait(false);
RestClient.ThrowIfError(response);
return response;
return response.ThrowIfError();
}

/// <summary>
Expand All @@ -289,14 +277,12 @@ public static async Task<RestResponse> PatchAsync(this RestClient client, RestRe
/// <returns></returns>
public static async Task<T?> DeleteAsync<T>(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
var response = await client.ExecuteAsync<T>(request, Method.Delete, cancellationToken).ConfigureAwait(false);
RestClient.ThrowIfError(response);
return response.Data;
return response.ThrowIfError().Data;
}

public static async Task<RestResponse> DeleteAsync(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) {
var response = await client.ExecuteAsync(request, Method.Delete, cancellationToken).ConfigureAwait(false);
RestClient.ThrowIfError(response);
return response;
return response.ThrowIfError();
}

/// <summary>
Expand Down
13 changes: 13 additions & 0 deletions test/RestSharp.Tests/RestContentTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,17 @@ public void RestContent_CaseInsensitiveHeaders() {

httpContent.Headers.ContentType!.MediaType.Should().Be(myContentType);
}

[Fact]
public void RestContent_supports_manual_json_body() {
const string myContentType = "application/json";
const string myJsonString = "[]";

var request = new RestRequest("resource").AddParameter(myContentType, myJsonString, ParameterType.RequestBody);
var content = new RequestContent(new RestClient(), request);

var httpContent = content.BuildContent();

httpContent.Headers.ContentType!.MediaType.Should().Be(myContentType);
}
}