Skip to content

Commit 94e578a

Browse files
committed
Enable using URL segment parameters without encoding
1 parent 922bf07 commit 94e578a

File tree

7 files changed

+67
-68
lines changed

7 files changed

+67
-68
lines changed

src/RestSharp/Authenticators/OAuth/OAuth1Authenticator.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ void AddOAuthData(IRestClient client, IRestRequest request, OAuthWorkflow workfl
274274
// if this change causes trouble we need to introduce a flag indicating the specific OAuth implementation level,
275275
// or implement a separate class for each OAuth version
276276
static bool BaseQuery(Parameter x)
277-
=> x.Type is ParameterType.GetOrPost or ParameterType.QueryString or ParameterType.QueryStringWithoutEncode;
277+
=> x.Type is ParameterType.GetOrPost or ParameterType.QueryString;
278278

279279
var query =
280280
request.AlwaysMultipartFormData || request.Files.Count > 0

src/RestSharp/Enum.cs

+5-11
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,15 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
namespace RestSharp
16-
{
15+
namespace RestSharp {
1716
/// <summary>
1817
/// Types of parameters that can be added to requests
1918
/// </summary>
20-
public enum ParameterType
21-
{
19+
public enum ParameterType {
2220
/// <summary>
2321
/// Cookie parameter
2422
/// </summary>
25-
Cookie,
26-
GetOrPost, UrlSegment, HttpHeader, RequestBody, QueryString,
27-
QueryStringWithoutEncode
23+
Cookie, GetOrPost, UrlSegment, HttpHeader, RequestBody, QueryString, QueryStringWithoutEncode
2824
}
2925

3026
/// <summary>
@@ -35,17 +31,15 @@ public enum DataFormat { Json, Xml, None }
3531
/// <summary>
3632
/// HTTP method to use when making requests
3733
/// </summary>
38-
public enum Method
39-
{
34+
public enum Method {
4035
GET, POST, PUT, DELETE, HEAD, OPTIONS,
4136
PATCH, MERGE, COPY
4237
}
4338

4439
/// <summary>
4540
/// Format strings for commonly-used date formats
4641
/// </summary>
47-
public struct DateFormat
48-
{
42+
public struct DateFormat {
4943
/// <summary>
5044
/// .NET format string for ISO 8601 date format
5145
/// </summary>

src/RestSharp/IRestRequest.cs

+9
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,15 @@ public interface IRestRequest
417417
/// <returns></returns>
418418
IRestRequest AddUrlSegment(string name, string value);
419419

420+
/// <summary>
421+
/// Shortcut to AddParameter(name, value, UrlSegment) overload
422+
/// </summary>
423+
/// <param name="name">Name of the segment to add</param>
424+
/// <param name="value">Value of the segment to add</param>
425+
/// <param name="encode">Specify false if the value should not be encoded</param>
426+
/// <returns></returns>
427+
IRestRequest AddUrlSegment(string name, string value, bool encode);
428+
420429
/// <summary>
421430
/// Shortcut to AddParameter(name, value, UrlSegment) overload
422431
/// </summary>

src/RestSharp/Parameter.cs

+28-36
Original file line numberDiff line numberDiff line change
@@ -20,25 +20,24 @@
2020
using JetBrains.Annotations;
2121
using RestSharp.Validation;
2222

23-
namespace RestSharp
24-
{
23+
namespace RestSharp {
2524
/// <summary>
2625
/// Parameter container for REST requests
2726
/// </summary>
2827
[Obsolete("Use Add[XXX]Parameter methods of IRestRequest instead of instantiating the Parameter class.")]
29-
public class Parameter : IEquatable<Parameter>
30-
{
31-
public Parameter(string name, object value, ParameterType type)
32-
{
28+
public class Parameter : IEquatable<Parameter> {
29+
public Parameter(string name, object? value, ParameterType type, bool encode = true) {
3330
if (type != ParameterType.RequestBody)
3431
Ensure.NotEmpty(name, nameof(name));
3532

36-
Name = name;
37-
Value = type != ParameterType.UrlSegment ? value : value?.ToString().Replace("%2F", "/").Replace("%2f", "/");
38-
Type = type;
33+
Name = name;
34+
Value = type != ParameterType.UrlSegment ? value : value?.ToString().Replace("%2F", "/").Replace("%2f", "/");
35+
Type = type == ParameterType.QueryStringWithoutEncode ? ParameterType.QueryString : type;
36+
Encode = type != ParameterType.QueryStringWithoutEncode && encode;
3937
}
4038

41-
public Parameter(string name, object value, string contentType, ParameterType type) : this(name, value, type) => ContentType = contentType;
39+
public Parameter(string name, object value, string contentType, ParameterType type, bool encode = true) : this(name, value, type, encode)
40+
=> ContentType = contentType;
4241

4342
/// <summary>
4443
/// Name of the parameter
@@ -65,49 +64,45 @@ public Parameter(string name, object value, ParameterType type)
6564
/// </summary>
6665
public string? ContentType { get; set; }
6766

67+
internal bool Encode { get; }
68+
6869
/// <summary>
6970
/// Return a human-readable representation of this parameter
7071
/// </summary>
7172
/// <returns>String</returns>
7273
public override string ToString() => $"{Name}={Value}";
7374

74-
public bool Equals(Parameter other)
75-
{
75+
public bool Equals(Parameter? other) {
7676
if (ReferenceEquals(null, other)) return false;
7777
if (ReferenceEquals(this, other)) return true;
7878

79-
return Name == other.Name
80-
&& Equals(Value, other.Value)
81-
&& Type == other.Type
82-
&& DataFormat == other.DataFormat
83-
&& ContentType == other.ContentType;
79+
return Name == other.Name &&
80+
Equals(Value, other.Value) &&
81+
Type == other.Type &&
82+
DataFormat == other.DataFormat &&
83+
ContentType == other.ContentType;
8484
}
8585

86-
public override bool Equals(object obj)
87-
=> !ReferenceEquals(null, obj)
88-
&& (ReferenceEquals(this, obj) || obj.GetType() == this.GetType() && Equals((Parameter) obj));
86+
public override bool Equals(object? obj)
87+
=> !ReferenceEquals(null, obj) && (ReferenceEquals(this, obj) || obj.GetType() == GetType() && Equals((Parameter)obj));
8988

9089
// ReSharper disable NonReadonlyMemberInGetHashCode
91-
public override int GetHashCode()
92-
{
93-
unchecked
94-
{
90+
public override int GetHashCode() {
91+
unchecked {
9592
var hashCode = Name != null ? Name.GetHashCode() : 0;
9693

9794
hashCode = (hashCode * 397) ^ (Value != null ? Value.GetHashCode() : 0);
98-
hashCode = (hashCode * 397) ^ (int) Type;
99-
hashCode = (hashCode * 397) ^ (int) DataFormat;
95+
hashCode = (hashCode * 397) ^ (int)Type;
96+
hashCode = (hashCode * 397) ^ (int)DataFormat;
10097
hashCode = (hashCode * 397) ^ (ContentType != null ? ContentType.GetHashCode() : 0);
10198
return hashCode;
10299
}
103100
}
104101
// ReSharper enable NonReadonlyMemberInGetHashCode
105102
}
106103

107-
public class XmlParameter : Parameter
108-
{
109-
public XmlParameter(string name, object value, string? xmlNamespace = null) : base(name, value, ParameterType.RequestBody)
110-
{
104+
public class XmlParameter : Parameter {
105+
public XmlParameter(string name, object value, string? xmlNamespace = null) : base(name, value, ParameterType.RequestBody) {
111106
XmlNamespace = xmlNamespace;
112107
DataFormat = DataFormat.Xml;
113108
ContentType = Serialization.ContentType.Xml;
@@ -116,16 +111,13 @@ public XmlParameter(string name, object value, string? xmlNamespace = null) : ba
116111
public string? XmlNamespace { get; }
117112
}
118113

119-
public class JsonParameter : Parameter
120-
{
121-
public JsonParameter(string name, object value) : base(name, value, ParameterType.RequestBody)
122-
{
114+
public class JsonParameter : Parameter {
115+
public JsonParameter(string name, object value) : base(name, value, ParameterType.RequestBody) {
123116
DataFormat = DataFormat.Json;
124117
ContentType = Serialization.ContentType.Json;
125118
}
126119

127-
public JsonParameter(string name, object value, string contentType) : base(name, value, ParameterType.RequestBody)
128-
{
120+
public JsonParameter(string name, object value, string contentType) : base(name, value, ParameterType.RequestBody) {
129121
DataFormat = DataFormat.Json;
130122
ContentType = contentType ?? Serialization.ContentType.Json;
131123
}

src/RestSharp/RestClient.cs

+10-16
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ public Uri BuildUri(IRestRequest request)
238238
return new Uri(finalUri);
239239
}
240240

241-
string IRestClient.BuildUriWithoutQueryParameters(IRestRequest request)
241+
string? IRestClient.BuildUriWithoutQueryParameters(IRestRequest request)
242242
{
243243
DoBuildUriValidations(request);
244244

@@ -303,7 +303,7 @@ UrlSegmentParamsValues GetUrlSegmentParamsValues(IRestRequest request)
303303
foreach (var parameter in parameters)
304304
{
305305
var paramPlaceHolder = $"{{{parameter.Name}}}";
306-
var paramValue = Encode(parameter.Value!.ToString());
306+
var paramValue = parameter.Encode ? Encode(parameter.Value!.ToString()) : parameter.Value!.ToString();
307307

308308
if (hasResource) assembled = assembled.Replace(paramPlaceHolder, paramValue);
309309

@@ -313,11 +313,11 @@ UrlSegmentParamsValues GetUrlSegmentParamsValues(IRestRequest request)
313313
return new UrlSegmentParamsValues(builder.Uri, assembled);
314314
}
315315

316-
static string MergeBaseUrlAndResource(Uri baseUrl, string resource)
316+
static string? MergeBaseUrlAndResource(Uri? baseUrl, string? resource)
317317
{
318318
var assembled = resource;
319319

320-
if (!IsNullOrEmpty(assembled) && assembled.StartsWith("/")) assembled = assembled.Substring(1);
320+
if (!IsNullOrEmpty(assembled) && assembled!.StartsWith("/")) assembled = assembled.Substring(1);
321321

322322
if (baseUrl == null || IsNullOrEmpty(baseUrl.AbsoluteUri)) return assembled;
323323

@@ -326,7 +326,7 @@ static string MergeBaseUrlAndResource(Uri baseUrl, string resource)
326326
return assembled != null ? new Uri(usingBaseUri, assembled).AbsoluteUri : baseUrl.AbsoluteUri;
327327
}
328328

329-
string ApplyQueryStringParamsValuesToUri(string mergedUri, IRestRequest request)
329+
string? ApplyQueryStringParamsValuesToUri(string? mergedUri, IRestRequest request)
330330
{
331331
var parameters = GetQueryStringParameters(request).ToList();
332332
parameters.AddRange(GetDefaultQueryStringParameters(request));
@@ -342,28 +342,22 @@ IEnumerable<Parameter> GetDefaultQueryStringParameters(IRestRequest request)
342342
=> request.Method != Method.POST && request.Method != Method.PUT && request.Method != Method.PATCH
343343
? DefaultParameters
344344
.Where(
345-
p => p.Type == ParameterType.GetOrPost ||
346-
p.Type == ParameterType.QueryString ||
347-
p.Type == ParameterType.QueryStringWithoutEncode
345+
p => p.Type is ParameterType.GetOrPost or ParameterType.QueryString
348346
)
349347
: DefaultParameters
350348
.Where(
351-
p => p.Type == ParameterType.QueryString ||
352-
p.Type == ParameterType.QueryStringWithoutEncode
349+
p => p.Type is ParameterType.QueryString
353350
);
354351

355352
static IEnumerable<Parameter> GetQueryStringParameters(IRestRequest request)
356353
=> request.Method != Method.POST && request.Method != Method.PUT && request.Method != Method.PATCH
357354
? request.Parameters
358355
.Where(
359-
p => p.Type == ParameterType.GetOrPost ||
360-
p.Type == ParameterType.QueryString ||
361-
p.Type == ParameterType.QueryStringWithoutEncode
356+
p => p.Type is ParameterType.GetOrPost or ParameterType.QueryString
362357
)
363358
: request.Parameters
364359
.Where(
365-
p => p.Type == ParameterType.QueryString ||
366-
p.Type == ParameterType.QueryStringWithoutEncode
360+
p => p.Type is ParameterType.QueryString
367361
);
368362

369363
Func<IDeserializer>? GetHandler(string contentType)
@@ -402,7 +396,7 @@ string EncodeParameters(IEnumerable<Parameter> parameters, Encoding encoding)
402396
string EncodeParameter(Parameter parameter, Encoding encoding)
403397
{
404398
return
405-
parameter.Type == ParameterType.QueryStringWithoutEncode
399+
!parameter.Encode
406400
? $"{parameter.Name}={StringOrEmpty(parameter.Value)}"
407401
: $"{EncodeQuery(parameter.Name!, encoding)}={EncodeQuery(StringOrEmpty(parameter.Value), encoding)}";
408402

src/RestSharp/RestRequest.cs

+10-2
Original file line numberDiff line numberDiff line change
@@ -426,13 +426,21 @@ public IRestRequest AddOrUpdateHeaders(ICollection<KeyValuePair<string, string>>
426426

427427
/// <inheritdoc />
428428
public IRestRequest AddUrlSegment(string name, string value) => AddParameter(name, value, ParameterType.UrlSegment);
429+
430+
/// <inheritdoc />
431+
public IRestRequest AddUrlSegment(string name, string value, bool encode) {
432+
var parameter = new Parameter(name, value, ParameterType.UrlSegment, encode);
433+
return AddParameter(parameter);
434+
}
429435

430436
/// <inheritdoc />
431437
public IRestRequest AddQueryParameter(string name, string value) => AddParameter(name, value, ParameterType.QueryString);
432438

433439
/// <inheritdoc />
434-
public IRestRequest AddQueryParameter(string name, string value, bool encode)
435-
=> AddParameter(name, value, encode ? ParameterType.QueryString : ParameterType.QueryStringWithoutEncode);
440+
public IRestRequest AddQueryParameter(string name, string value, bool encode) {
441+
var parameter = new Parameter(name, value, ParameterType.QueryString, encode);
442+
return AddParameter(parameter);
443+
}
436444

437445
/// <inheritdoc />
438446
public IRestRequest AddDecompressionMethod(DecompressionMethods decompressionMethod)

test/RestSharp.Tests/RestRequestTests.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@ public void RestRequest_Test_Already_Encoded()
2222
Assert.AreEqual(2, request.Parameters.Count);
2323
Assert.AreEqual("query", request.Parameters[0].Name);
2424
Assert.AreEqual("Id%3d198", request.Parameters[0].Value);
25-
Assert.AreEqual(ParameterType.QueryStringWithoutEncode, request.Parameters[0].Type);
25+
Assert.AreEqual(ParameterType.QueryString, request.Parameters[0].Type);
26+
Assert.AreEqual(false, request.Parameters[0].Encode);
2627
Assert.AreEqual("another", request.Parameters[1].Name);
2728
Assert.AreEqual("notencoded", request.Parameters[1].Value);
28-
Assert.AreEqual(ParameterType.QueryStringWithoutEncode, request.Parameters[1].Type);
29+
Assert.AreEqual(ParameterType.QueryString, request.Parameters[1].Type);
30+
Assert.AreEqual(false, request.Parameters[1].Encode);
2931
}
3032

3133
[Test]

0 commit comments

Comments
 (0)