Skip to content

Commit

Permalink
Default headers should allow multiple values
Browse files Browse the repository at this point in the history
  • Loading branch information
alexeyzimarev committed Jul 11, 2024
1 parent b82834b commit df05ab9
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 24 deletions.
25 changes: 14 additions & 11 deletions gen/SourceGenerator/ImmutableGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,24 @@ public void Execute(GeneratorExecutionContext context) {

static string GenerateImmutableClass(TypeDeclarationSyntax mutableClass, Compilation compilation) {
var containingNamespace = compilation.GetSemanticModel(mutableClass.SyntaxTree).GetDeclaredSymbol(mutableClass)!.ContainingNamespace;

var namespaceName = containingNamespace.ToDisplayString();

var className = mutableClass.Identifier.Text;

var usings = mutableClass.SyntaxTree.GetCompilationUnitRoot().Usings.Select(u => u.ToString());
var namespaceName = containingNamespace.ToDisplayString();
var className = mutableClass.Identifier.Text;
var usings = mutableClass.SyntaxTree.GetCompilationUnitRoot().Usings.Select(u => u.ToString());

var properties = GetDefinitions(SyntaxKind.SetKeyword)
.Select(prop => $" public {prop.Type} {prop.Identifier.Text} {{ get; }}")
.Select(
prop => {
var xml = prop.GetLeadingTrivia().FirstOrDefault(x => x.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia)).GetStructure();
return $"/// {xml} public {prop.Type} {prop.Identifier.Text} {{ get; }}";
}
)
.ToArray();

var props = GetDefinitions(SyntaxKind.SetKeyword).ToArray();

const string argName = "inner";
var mutableProperties = props
.Select(prop => $" {prop.Identifier.Text} = {argName}.{prop.Identifier.Text};");

var mutableProperties = props.Select(prop => $" {prop.Identifier.Text} = {argName}.{prop.Identifier.Text};");

var constructor = $$"""
public ReadOnly{{className}}({{className}} {{argName}}) {
Expand Down Expand Up @@ -85,7 +87,8 @@ IEnumerable<PropertyDeclarationSyntax> GetDefinitions(SyntaxKind kind)
.OfType<PropertyDeclarationSyntax>()
.Where(
prop =>
prop.AccessorList!.Accessors.Any(accessor => accessor.Keyword.IsKind(kind)) && prop.AttributeLists.All(list => list.Attributes.All(attr => attr.Name.ToString() != "Exclude"))
prop.AccessorList!.Accessors.Any(accessor => accessor.Keyword.IsKind(kind)) &&
prop.AttributeLists.All(list => list.Attributes.All(attr => attr.Name.ToString() != "Exclude"))
);
}
}
}
1 change: 1 addition & 0 deletions src/RestSharp/Options/RestClientOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ public RestClientOptions(string baseUrl) : this(new Uri(Ensure.NotEmptyString(ba

/// <summary>
/// Set to true to allow multiple default parameters with the same name. Default is false.
/// This setting doesn't apply to headers as multiple header values for the same key is allowed.
/// </summary>
public bool AllowMultipleDefaultParametersWithSameName { get; set; }

Expand Down
4 changes: 1 addition & 3 deletions src/RestSharp/Parameters/DefaultParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ public sealed class DefaultParameters(ReadOnlyRestClientOptions options) : Param
[MethodImpl(MethodImplOptions.Synchronized)]
public DefaultParameters AddParameter(Parameter parameter) {
if (parameter.Type == ParameterType.RequestBody)
throw new NotSupportedException(
"Cannot set request body using default parameters. Use Request.AddBody() instead."
);
throw new NotSupportedException("Cannot set request body using default parameters. Use Request.AddBody() instead.");

if (!options.AllowMultipleDefaultParametersWithSameName &&
parameter.Type != ParameterType.HttpHeader &&
Expand Down
6 changes: 4 additions & 2 deletions src/RestSharp/Parameters/Parameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,16 @@ protected Parameter(string? name, object? value, ParameterType type, bool encode
/// Return a human-readable representation of this parameter
/// </summary>
/// <returns>String</returns>
public sealed override string ToString() => Value == null ? $"{Name}" : $"{Name}={Value}";
public sealed override string ToString() => Value == null ? $"{Name}" : $"{Name}={ValueString}";

protected virtual string ValueString => Value?.ToString() ?? "null";

public static Parameter CreateParameter(string? name, object? value, ParameterType type, bool encode = true)
// ReSharper disable once SwitchExpressionHandlesSomeKnownEnumValuesWithExceptionInDefault
=> type switch {
ParameterType.GetOrPost => new GetOrPostParameter(Ensure.NotEmptyString(name, nameof(name)), value?.ToString(), encode),
ParameterType.UrlSegment => new UrlSegmentParameter(Ensure.NotEmptyString(name, nameof(name)), value?.ToString()!, encode),
ParameterType.HttpHeader => new HeaderParameter(name, value?.ToString()),
ParameterType.HttpHeader => new HeaderParameter(name!, value?.ToString()!),
ParameterType.QueryString => new QueryParameter(Ensure.NotEmptyString(name, nameof(name)), value?.ToString(), encode),
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
};
Expand Down
2 changes: 1 addition & 1 deletion src/RestSharp/Request/RestRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
using RestSharp.Authenticators;
using RestSharp.Extensions;
using RestSharp.Interceptors;
// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global

// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
// ReSharper disable UnusedAutoPropertyAccessor.Global

namespace RestSharp;
Expand Down
19 changes: 17 additions & 2 deletions src/RestSharp/Request/RestRequestExtensions.Headers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@
namespace RestSharp;

public static partial class RestRequestExtensions {
/// <summary>
/// Adds a header to the request. RestSharp will try to separate request and content headers when calling the resource.
/// </summary>
/// <param name="request">Request instance</param>
/// <param name="name">Header name</param>
/// <param name="values">Header values</param>
/// <returns></returns>
public static RestRequest AddHeader(this RestRequest request, string name, string[] values) {
foreach (var value in values) {
AddHeader(request, name, value);
}

return request;
}

/// <summary>
/// Adds a header to the request. RestSharp will try to separate request and content headers when calling the resource.
/// </summary>
Expand All @@ -41,7 +56,7 @@ public static RestRequest AddHeader<T>(this RestRequest request, string name, T

/// <summary>
/// Adds or updates the request header. RestSharp will try to separate request and content headers when calling the resource.
/// Existing header with the same name will be replaced.
/// The existing header with the same name will be replaced.
/// </summary>
/// <param name="request">Request instance</param>
/// <param name="name">Header name</param>
Expand All @@ -54,7 +69,7 @@ public static RestRequest AddOrUpdateHeader(this RestRequest request, string nam

/// <summary>
/// Adds or updates the request header. RestSharp will try to separate request and content headers when calling the resource.
/// Existing header with the same name will be replaced.
/// The existing header with the same name will be replaced.
/// </summary>
/// <param name="request">Request instance</param>
/// <param name="name">Header name</param>
Expand Down
11 changes: 6 additions & 5 deletions test/RestSharp.Tests/RequestHeaderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ public void AddOrUpdateHeader_ShouldUpdateExistingHeader_WhenHeaderExist() {
request.AddOrUpdateHeader(KnownHeaders.Accept, ContentType.Json);

// Assert
var headers = GetHeaders(request);
GetHeader(request, KnownHeaders.Accept).Should().Be(ContentType.Json);
}

Expand Down Expand Up @@ -158,16 +157,18 @@ public void AddOrUpdateHeaders_ShouldAddAndUpdateHeaders_WhenSomeExists() {

[Fact]
public void Should_not_allow_null_header_value() {
var request = new RestRequest();
Assert.Throws<ArgumentNullException>("value", () => request.AddHeader("name", null!));
string value = null;
var request = new RestRequest();
// ReSharper disable once AssignNullToNotNullAttribute
Assert.Throws<ArgumentNullException>("value", () => request.AddHeader("name", value));
}

[Fact]
public void Should_not_allow_null_header_name() {
var request = new RestRequest();
Assert.Throws<ArgumentNullException>("name", () => request.AddHeader(null!, "value"));
}

[Fact]
public void Should_not_allow_empty_header_name() {
var request = new RestRequest();
Expand Down

0 comments on commit df05ab9

Please sign in to comment.