Skip to content

Commit

Permalink
Cleaning up parameters (#1683)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexeyzimarev committed Jan 7, 2022
1 parent 0c3ea2a commit 949a342
Show file tree
Hide file tree
Showing 11 changed files with 128 additions and 49 deletions.
9 changes: 5 additions & 4 deletions src/RestSharp/Extensions/MiscExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ static class MiscExtensions {

return ms.ToArray();
}
internal static IEnumerable<(string Name, object Value)> GetProperties(this object obj, params string[] includedProperties) {

internal static IEnumerable<(string Name, string? Value)> GetProperties(this object obj, params string[] includedProperties) {
// automatically create parameters from object props
var type = obj.GetType();
var props = type.GetProperties();
Expand All @@ -63,12 +63,13 @@ static class MiscExtensions {
if (array.Length > 0 && elementType != null) {
// convert the array to an array of strings
var values = array.Cast<object>().Select(item => item.ToString());
yield return (prop.Name, string.Join(",", values));

val = string.Join(",", values);
continue;
}
}

yield return(prop.Name, val);
yield return (prop.Name, val.ToString());
}

bool IsAllowedProperty(string propertyName)
Expand Down
1 change: 1 addition & 0 deletions src/RestSharp/KnownHeaders.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ public static class KnownHeaders {
public const string ContentType = "Content-Type";
public const string LastModified = "Last-Modified";
public const string ContentMD5 = "Content-MD5";
public const string Host = "Host";
}
15 changes: 4 additions & 11 deletions src/RestSharp/Parameters/FileParameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,6 @@ namespace RestSharp;
/// </summary>
[PublicAPI]
public record FileParameter {
/// <summary>
/// The length of data to be sent
/// </summary>
public long ContentLength { get; }

/// <summary>
/// Provides raw data for file
/// </summary>
Expand All @@ -44,10 +39,9 @@ public record FileParameter {
/// </summary>
public string Name { get; }

FileParameter(string name, string fileName, long contentLength, Func<Stream> getFile, string? contentType = null) {
FileParameter(string name, string fileName, Func<Stream> getFile, string? contentType = null) {
Name = name;
FileName = fileName;
ContentLength = contentLength;
GetFile = getFile;
ContentType = contentType ?? "application/octet-stream";
}
Expand All @@ -61,7 +55,7 @@ public record FileParameter {
/// <param name="contentType">The content type to use in the request.</param>
/// <returns>The <see cref="FileParameter" /></returns>
public static FileParameter Create(string name, byte[] data, string filename, string? contentType = null) {
return new FileParameter(name, filename, data.Length, GetFile, contentType);
return new FileParameter(name, filename, GetFile, contentType);

Stream GetFile() {
var stream = new MemoryStream();
Expand All @@ -86,17 +80,16 @@ public record FileParameter {
string fileName,
string? contentType = null
)
=> new(name, fileName, contentLength, getFile, contentType ?? Serializers.ContentType.File);
=> new(name, fileName, getFile, contentType ?? Serializers.ContentType.File);

public static FileParameter FromFile(string fullPath, string? name = null, string? contentType = null) {
if (!File.Exists(Ensure.NotEmptyString(fullPath, nameof(fullPath))))
throw new FileNotFoundException("File not found", fullPath);

var fileName = Path.GetFileName(fullPath);
var parameterName = name ?? fileName;
var length = new FileInfo(fullPath).Length;

return new FileParameter(parameterName, fileName, length, GetFile);
return new FileParameter(parameterName, fileName, GetFile);

Stream GetFile() => File.OpenRead(fullPath);
}
Expand Down
7 changes: 6 additions & 1 deletion src/RestSharp/Parameters/GetOrPostParameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@
// 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.
//

namespace RestSharp;

public record GetOrPostParameter : NamedParameter {
/// <summary>
/// Instantiates an HTTP parameter instance (QueryString for GET, DELETE, OPTIONS and HEAD; Encoded form for POST and PUT)
/// </summary>
/// <param name="name">Name of the parameter</param>
/// <param name="value">Value of the parameter</param>
/// <param name="encode">Encode the value or not, default true</param>
public GetOrPostParameter(string name, string? value, bool encode = true) : base(name, value, ParameterType.GetOrPost, encode) { }
}
5 changes: 5 additions & 0 deletions src/RestSharp/Parameters/HeaderParameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,10 @@
namespace RestSharp;

public record HeaderParameter : Parameter {
/// <summary>
/// Instantiates a header parameter
/// </summary>
/// <param name="name">Parameter name</param>
/// <param name="value">Parameter value</param>
public HeaderParameter(string? name, string? value) : base(name, value, ParameterType.HttpHeader, false) { }
}
6 changes: 6 additions & 0 deletions src/RestSharp/Parameters/QueryParameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,11 @@
namespace RestSharp;

public record QueryParameter : NamedParameter {
/// <summary>
/// Instantiates a new query parameter instance that will be added to the request URL as {name}={value} part of the query string.
/// </summary>
/// <param name="name">Parameter name</param>
/// <param name="value">Parameter value</param>
/// <param name="encode">Optional: encode the value, default is true</param>
public QueryParameter(string name, string? value, bool encode = true) : base(name, value, ParameterType.QueryString, encode) { }
}
8 changes: 7 additions & 1 deletion src/RestSharp/Parameters/UrlSegmentParameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,17 @@
// 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.
//

namespace RestSharp;

public record UrlSegmentParameter : NamedParameter {
/// <summary>
/// Instantiates a new query parameter instance that will be added to the request URL part of the query string.
/// The request resource should have a placeholder {name} that will be replaced with the parameter value when the request is made.
/// </summary>
/// <param name="name">Parameter name</param>
/// <param name="value">Parameter value</param>
/// <param name="encode">Optional: encode the value, default is true</param>
public UrlSegmentParameter(string name, string value, bool encode = true)
: base(name, Ensure.NotEmpty(value, nameof(value)).Replace("%2F", "/").Replace("%2f", "/"), ParameterType.UrlSegment, encode) { }
}
13 changes: 11 additions & 2 deletions src/RestSharp/Request/RestRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,18 @@ public RestRequest(Uri resource, Method method = Method.Get)
}
}

public RestRequest AddParameter(Parameter p) => this.With(x => x.Parameters.AddParameter(p));
/// <summary>
/// Adds a parameter object to the request parameters
/// </summary>
/// <param name="parameter">Parameter to add</param>
/// <returns></returns>
public RestRequest AddParameter(Parameter parameter) => this.With(x => x.Parameters.AddParameter(parameter));

public void RemoveParameter(Parameter p) => Parameters.RemoveParameter(p);
/// <summary>
/// Removes a parameter object from the request parameters
/// </summary>
/// <param name="parameter">Parameter to remove</param>
public void RemoveParameter(Parameter parameter) => Parameters.RemoveParameter(parameter);

internal RestRequest AddFile(FileParameter file) => this.With(x => x._files.Add(file));
}
96 changes: 69 additions & 27 deletions src/RestSharp/Request/RestRequestExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,49 +30,75 @@ public static class RestRequestExtensions {
/// <param name="value">Value of the parameter</param>
/// <param name="encode">Encode the value or not, default true</param>
/// <returns>This request</returns>
public static RestRequest AddParameter(this RestRequest request, string name, object? value, bool encode = true)
=> request.AddParameter(new GetOrPostParameter(name, value?.ToString(), encode));
public static RestRequest AddParameter(this RestRequest request, string name, string? value, bool encode = true)
=> request.AddParameter(new GetOrPostParameter(name, value, encode));

public static RestRequest AddParameter(this RestRequest request, string? name, object value, ParameterType type, bool encode = true)
=> request.AddParameter(Parameter.CreateParameter(name, value, type, encode));

public static RestRequest AddOrUpdateParameter(this RestRequest request, Parameter parameter) {
var p = request.Parameters.FirstOrDefault(x => x.Name == parameter.Name && x.Type == parameter.Type);
/// <summary>
/// Adds a HTTP parameter to the request (QueryString for GET, DELETE, OPTIONS and HEAD; Encoded form for POST and PUT)
/// </summary>
/// <param name="request">Request instance</param>
/// <param name="name">Name of the parameter</param>
/// <param name="value">Value of the parameter</param>
/// <param name="encode">Encode the value or not, default true</param>
/// <returns>This request</returns>
public static RestRequest AddParameter<T>(this RestRequest request, string name, T value, bool encode = true) where T : struct
=> request.AddParameter(name, value.ToString(), encode);

if (p != null) request.RemoveParameter(p);
/// <summary>
/// Adds or updates a HTTP parameter to the request (QueryString for GET, DELETE, OPTIONS and HEAD; Encoded form for POST and PUT)
/// </summary>
/// <param name="request">Request instance</param>
/// <param name="name">Name of the parameter</param>
/// <param name="value">Value of the parameter</param>
/// <param name="encode">Encode the value or not, default true</param>
/// <returns>This request</returns>
public static RestRequest AddOrUpdateParameter(this RestRequest request, string name, string? value, bool encode = true)
=> request.AddOrUpdateParameter(new GetOrPostParameter(name, value, encode));

request.AddParameter(parameter);
return request;
}
/// <summary>
/// Adds or updates a HTTP parameter to the request (QueryString for GET, DELETE, OPTIONS and HEAD; Encoded form for POST and PUT)
/// </summary>
/// <param name="request">Request instance</param>
/// <param name="name">Name of the parameter</param>
/// <param name="value">Value of the parameter</param>
/// <param name="encode">Encode the value or not, default true</param>
/// <returns>This request</returns>
public static RestRequest AddOrUpdateParameter<T>(this RestRequest request, string name, T value, bool encode = true) where T : struct
=> request.AddOrUpdateParameter(name, value.ToString(), encode);

public static RestRequest AddOrUpdateParameters(this RestRequest request, IEnumerable<Parameter> parameters) {
foreach (var parameter in parameters)
request.AddOrUpdateParameter(parameter);
public static RestRequest AddUrlSegment(this RestRequest request, string name, string value, bool encode = true)
=> request.AddParameter(new UrlSegmentParameter(name, value, encode));

return request;
}
public static RestRequest AddUrlSegment<T>(this RestRequest request, string name, T value, bool encode = true) where T : struct
=> request.AddUrlSegment(name, Ensure.NotNull(value.ToString(), nameof(value)), encode);

public static RestRequest AddOrUpdateParameter(this RestRequest request, string name, object? value)
=> request.AddOrUpdateParameter(new GetOrPostParameter(name, value?.ToString()));
public static RestRequest AddQueryParameter(this RestRequest request, string name, string? value, bool encode = true)
=> request.AddParameter(new QueryParameter(name, value, encode));

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 AddQueryParameter<T>(this RestRequest request, string name, T value, bool encode = true) where T : struct
=> request.AddQueryParameter(name, value.ToString(), encode);

public static RestRequest AddHeader(this RestRequest request, string name, string value) {
CheckAndThrowsForInvalidHost(name, value);
return request.AddParameter(new HeaderParameter(name, value));
}

public static RestRequest AddHeader<T>(this RestRequest request, string name, T value) where T : struct
=> request.AddHeader(name, Ensure.NotNull(value.ToString(), nameof(value)));

public static RestRequest AddOrUpdateHeader(this RestRequest request, string name, string value) {
CheckAndThrowsForInvalidHost(name, value);
return request.AddOrUpdateParameter(new HeaderParameter(name, value));
}

public static RestRequest AddOrUpdateHeader<T>(this RestRequest request, string name, T value) where T : struct
=> request.AddOrUpdateHeader(name, Ensure.NotNull(value.ToString(), nameof(value)));

public static RestRequest AddHeaders(this RestRequest request, ICollection<KeyValuePair<string, string>> headers) {
CheckAndThrowsDuplicateKeys(headers);

foreach (var pair in headers) {
request.AddHeader(pair.Key, pair.Value);
foreach (var header in headers) {
request.AddHeader(header.Key, header.Value);
}

return request;
Expand All @@ -88,11 +114,27 @@ public static RestRequest AddOrUpdateParameter(this RestRequest request, string
return request;
}

public static RestRequest AddUrlSegment(this RestRequest request, string name, string value, bool encode = true)
=> request.AddParameter(new UrlSegmentParameter(name, value, encode));
public static RestRequest AddParameter(this RestRequest request, string? name, object value, ParameterType type, bool encode = true)
=> request.AddParameter(Parameter.CreateParameter(name, value, type, encode));

public static RestRequest AddQueryParameter(this RestRequest request, string name, string value, bool encode = true)
=> request.AddParameter(new QueryParameter(name, value, encode));
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);

request.AddParameter(parameter);
return request;
}

public static RestRequest AddOrUpdateParameters(this RestRequest request, IEnumerable<Parameter> parameters) {
foreach (var parameter in parameters)
request.AddOrUpdateParameter(parameter);

return request;
}

public static RestRequest AddOrUpdateParameter(this RestRequest request, string name, object value, ParameterType type, bool encode = true)
=> request.AddOrUpdateParameter(Parameter.CreateParameter(name, value, type, encode));

/// <summary>
/// Adds a file parameter to the request body. The file will be read from disk as a stream.
Expand Down Expand Up @@ -198,7 +240,7 @@ public static RestRequest AddFile(this RestRequest request, string name, byte[]
static void CheckAndThrowsForInvalidHost(string name, string value) {
static bool InvalidHost(string host) => Uri.CheckHostName(PortSplitRegex.Split(host)[0]) == UriHostNameType.Unknown;

if (name == "Host" && InvalidHost(value))
if (name == KnownHeaders.Host && InvalidHost(value))
throw new ArgumentException("The specified value is not a valid Host header string.", nameof(value));
}

Expand Down
4 changes: 2 additions & 2 deletions src/RestSharp/RestClientExtensions.Json.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ public static partial class RestClientExtensions {
var param = $"{name}";

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

Expand Down
13 changes: 12 additions & 1 deletion test/RestSharp.Tests/ParametersTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,21 @@ public class ParametersTests {

var expected = headers.Select(x => new HeaderParameter(x.Key, x.Value));

var client = new RestClient(BaseUrl);
var client = new RestClient(BaseUrl);
client.AddDefaultHeaders(headers);

var actual = client.DefaultParameters.Select(x => x as HeaderParameter);
expected.Should().BeSubsetOf(actual);
}

[Fact]
public void AddUrlSegmentWithInt() {
const string name = "foo";

var request = new RestRequest().AddUrlSegment(name, 1);
var actual = request.Parameters.FirstOrDefault(x => x.Name == name);
var expected = new UrlSegmentParameter(name, "1");

expected.Should().BeEquivalentTo(actual);
}
}

0 comments on commit 949a342

Please sign in to comment.