Skip to content

Commit 2d36071

Browse files
committed
Merge remote-tracking branch 'origin/dev' into dev
2 parents 9ed66e6 + 30a0706 commit 2d36071

File tree

15 files changed

+230
-94
lines changed

15 files changed

+230
-94
lines changed

SECURITY.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ currently being supported with security updates.
77

88
| Version | Supported |
99
| ------- | ------------------ |
10-
| 106.x | :white_check_mark: |
11-
| < 106.0 | :x: |
10+
| 108.x | :white_check_mark: |
11+
| < 108.0 | :x: |
1212

1313
## Reporting a Vulnerability
1414

src/Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
<ItemGroup>
2121
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All"/>
22-
<PackageReference Include="MinVer" Version="4.0.0" PrivateAssets="All"/>
22+
<PackageReference Include="MinVer" Version="4.1.0" PrivateAssets="All"/>
2323
<PackageReference Include="JetBrains.Annotations" Version="2022.1.0" PrivateAssets="All"/>
2424
</ItemGroup>
2525
<ItemGroup>

src/RestSharp/Parameters/FileParameter.cs

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ namespace RestSharp;
2020
[PublicAPI]
2121
public record FileParameter {
2222
/// <summary>
23-
/// Provides raw data for file
23+
/// Name of the parameter
2424
/// </summary>
25-
public Func<Stream> GetFile { get; }
25+
public string Name { get; }
2626

2727
/// <summary>
2828
/// Name of the file to use when uploading
@@ -35,15 +35,18 @@ public record FileParameter {
3535
public string? ContentType { get; }
3636

3737
/// <summary>
38-
/// Name of the parameter
38+
/// Provides raw data for file
3939
/// </summary>
40-
public string Name { get; }
40+
public Func<Stream> GetFile { get; }
41+
42+
public FileParameterOptions Options { get; }
4143

42-
FileParameter(string name, string fileName, Func<Stream> getFile, string? contentType = null) {
43-
Name = name;
44-
FileName = fileName;
45-
GetFile = getFile;
46-
ContentType = contentType ?? Serializers.ContentType.Binary;
44+
FileParameter(string name, string fileName, Func<Stream> getFile, string? contentType, FileParameterOptions options) {
45+
Name = name;
46+
FileName = fileName;
47+
GetFile = getFile;
48+
Options = options;
49+
ContentType = contentType ?? Serializers.ContentType.Binary;
4750
}
4851

4952
/// <summary>
@@ -53,9 +56,10 @@ public record FileParameter {
5356
/// <param name="data">The data to use as the file's contents.</param>
5457
/// <param name="filename">The filename to use in the request.</param>
5558
/// <param name="contentType">The content type to use in the request.</param>
59+
/// <param name="options">File parameter options</param>
5660
/// <returns>The <see cref="FileParameter" /></returns>
57-
public static FileParameter Create(string name, byte[] data, string filename, string? contentType = null) {
58-
return new FileParameter(name, filename, GetFile, contentType);
61+
public static FileParameter Create(string name, byte[] data, string filename, string? contentType = null, FileParameterOptions? options = null) {
62+
return new FileParameter(name, filename, GetFile, contentType, options ?? new FileParameterOptions());
5963

6064
Stream GetFile() {
6165
var stream = new MemoryStream();
@@ -73,24 +77,31 @@ Stream GetFile() {
7377
/// <param name="getFile">Delegate that will be called with the request stream so you can write to it..</param>
7478
/// <param name="fileName">The filename to use in the request.</param>
7579
/// <param name="contentType">Optional: parameter content type, default is "application/g-zip"</param>
80+
/// <param name="options">File parameter options</param>
7681
/// <returns>The <see cref="FileParameter" /> using the default content type.</returns>
7782
public static FileParameter Create(
78-
string name,
79-
Func<Stream> getFile,
80-
string fileName,
81-
string? contentType = null
83+
string name,
84+
Func<Stream> getFile,
85+
string fileName,
86+
string? contentType = null,
87+
FileParameterOptions? options = null
8288
)
83-
=> new(name, fileName, getFile, contentType ?? Serializers.ContentType.Binary);
89+
=> new(name, fileName, getFile, contentType ?? Serializers.ContentType.Binary, options ?? new FileParameterOptions());
8490

85-
public static FileParameter FromFile(string fullPath, string? name = null, string? contentType = null) {
86-
if (!File.Exists(Ensure.NotEmptyString(fullPath, nameof(fullPath))))
87-
throw new FileNotFoundException("File not found", fullPath);
91+
public static FileParameter FromFile(string fullPath, string? name = null, string? contentType = null, FileParameterOptions? options = null) {
92+
if (!File.Exists(Ensure.NotEmptyString(fullPath, nameof(fullPath)))) throw new FileNotFoundException("File not found", fullPath);
8893

89-
var fileName = Path.GetFileName(fullPath);
94+
var fileName = Path.GetFileName(fullPath);
9095
var parameterName = name ?? fileName;
91-
92-
return new FileParameter(parameterName, fileName, GetFile, contentType);
96+
97+
return new FileParameter(parameterName, fileName, GetFile, contentType, options ?? new FileParameterOptions());
9398

9499
Stream GetFile() => File.OpenRead(fullPath);
95100
}
96-
}
101+
}
102+
103+
[PublicAPI]
104+
public class FileParameterOptions {
105+
public bool DisableFileNameStar { get; set; } = true;
106+
public bool DisableFilenameEncoding { get; set; }
107+
}

src/RestSharp/Request/RequestContent.cs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,16 @@ void AddFiles() {
5757

5858
if (file.ContentType != null) fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse(file.ContentType);
5959

60-
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") {
61-
Name = $"\"{file.Name}\"",
62-
FileName = $"\"{file.FileName}\""
63-
};
64-
mpContent.Add(fileContent, file.Name, file.FileName);
60+
var dispositionHeader = file.Options.DisableFilenameEncoding
61+
? ContentDispositionHeaderValue.Parse($"form-data; name=\"{file.Name}\"; filename=\"{file.FileName}\"")
62+
: new ContentDispositionHeaderValue("form-data") {
63+
Name = $"\"{file.Name}\"",
64+
FileName = $"\"{file.FileName}\""
65+
};
66+
if (!file.Options.DisableFileNameStar) dispositionHeader.FileNameStar = file.FileName;
67+
fileContent.Headers.ContentDisposition = dispositionHeader;
68+
69+
mpContent.Add(fileContent);
6570
}
6671

6772
Content = mpContent;
@@ -172,7 +177,7 @@ void AddPostParameters(ParametersCollection? postParameters) {
172177
.Select(x => new KeyValuePair<string, string>(x.Name!, x.Value!.ToString()!))!;
173178
var encodedItems = formData.Select(i => $"{WebUtility.UrlEncode(i.Key)}={WebUtility.UrlEncode(i.Value)}" /*.Replace("%20", "+")*/);
174179
var encodedContent = new StringContent(string.Join("&", encodedItems), null, "application/x-www-form-urlencoded");
175-
180+
176181
Content = encodedContent;
177182
#endif
178183
}

src/RestSharp/Request/RestRequestExtensions.cs

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -268,9 +268,16 @@ public static RestRequest AddOrUpdateParameters(this RestRequest request, IEnume
268268
/// <param name="name">Parameter name</param>
269269
/// <param name="path">Full path to the file</param>
270270
/// <param name="contentType">Optional: content type</param>
271+
/// <param name="options">File parameter header options</param>
271272
/// <returns></returns>
272-
public static RestRequest AddFile(this RestRequest request, string name, string path, string? contentType = null)
273-
=> request.AddFile(FileParameter.FromFile(path, name, contentType));
273+
public static RestRequest AddFile(
274+
this RestRequest request,
275+
string name,
276+
string path,
277+
string? contentType = null,
278+
FileParameterOptions? options = null
279+
)
280+
=> request.AddFile(FileParameter.FromFile(path, name, contentType, options));
274281

275282
/// <summary>
276283
/// Adds bytes to the request as file attachment
@@ -280,9 +287,17 @@ public static RestRequest AddFile(this RestRequest request, string name, string
280287
/// <param name="bytes">File content as bytes</param>
281288
/// <param name="filename">File name</param>
282289
/// <param name="contentType">Optional: content type. Default is "application/octet-stream"</param>
290+
/// <param name="options">File parameter header options</param>
283291
/// <returns></returns>
284-
public static RestRequest AddFile(this RestRequest request, string name, byte[] bytes, string filename, string? contentType = null)
285-
=> request.AddFile(FileParameter.Create(name, bytes, filename, contentType));
292+
public static RestRequest AddFile(
293+
this RestRequest request,
294+
string name,
295+
byte[] bytes,
296+
string filename,
297+
string? contentType = null,
298+
FileParameterOptions? options = null
299+
)
300+
=> request.AddFile(FileParameter.Create(name, bytes, filename, contentType, options));
286301

287302
/// <summary>
288303
/// Adds a file attachment to the request, where the file content will be retrieved from a given stream
@@ -292,15 +307,17 @@ public static RestRequest AddFile(this RestRequest request, string name, byte[]
292307
/// <param name="getFile">Function that returns a stream with the file content</param>
293308
/// <param name="fileName">File name</param>
294309
/// <param name="contentType">Optional: content type. Default is "application/octet-stream"</param>
310+
/// <param name="options">File parameter header options</param>
295311
/// <returns></returns>
296312
public static RestRequest AddFile(
297-
this RestRequest request,
298-
string name,
299-
Func<Stream> getFile,
300-
string fileName,
301-
string? contentType = null
313+
this RestRequest request,
314+
string name,
315+
Func<Stream> getFile,
316+
string fileName,
317+
string? contentType = null,
318+
FileParameterOptions? options = null
302319
)
303-
=> request.AddFile(FileParameter.Create(name, getFile, fileName, contentType));
320+
=> request.AddFile(FileParameter.Create(name, getFile, fileName, contentType, options));
304321

305322
/// <summary>
306323
/// Adds a body parameter to the request

src/RestSharp/Response/RestResponse.cs

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -34,24 +34,24 @@ public class RestResponse<T> : RestResponse {
3434

3535
public static RestResponse<T> FromResponse(RestResponse response)
3636
=> new() {
37-
Content = response.Content,
38-
RawBytes = response.RawBytes,
39-
ContentEncoding = response.ContentEncoding,
40-
ContentLength = response.ContentLength,
41-
ContentType = response.ContentType,
42-
Cookies = response.Cookies,
43-
ErrorMessage = response.ErrorMessage,
44-
ErrorException = response.ErrorException,
45-
Headers = response.Headers,
46-
ContentHeaders = response.ContentHeaders,
47-
IsSuccessful = response.IsSuccessful,
48-
ResponseStatus = response.ResponseStatus,
49-
ResponseUri = response.ResponseUri,
50-
Server = response.Server,
51-
StatusCode = response.StatusCode,
52-
StatusDescription = response.StatusDescription,
53-
Request = response.Request,
54-
RootElement = response.RootElement
37+
Content = response.Content,
38+
RawBytes = response.RawBytes,
39+
ContentEncoding = response.ContentEncoding,
40+
ContentLength = response.ContentLength,
41+
ContentType = response.ContentType,
42+
Cookies = response.Cookies,
43+
ErrorMessage = response.ErrorMessage,
44+
ErrorException = response.ErrorException,
45+
Headers = response.Headers,
46+
ContentHeaders = response.ContentHeaders,
47+
IsSuccessStatusCode = response.IsSuccessStatusCode,
48+
ResponseStatus = response.ResponseStatus,
49+
ResponseUri = response.ResponseUri,
50+
Server = response.Server,
51+
StatusCode = response.StatusCode,
52+
StatusDescription = response.StatusDescription,
53+
Request = response.Request,
54+
RootElement = response.RootElement
5555
};
5656
}
5757

@@ -78,28 +78,28 @@ async Task<RestResponse> GetDefaultResponse() {
7878
await using var stream = await readTask.ConfigureAwait(false);
7979
#endif
8080

81-
var bytes = stream == null ? null : await stream.ReadAsBytes(cancellationToken).ConfigureAwait(false);
81+
var bytes = request.ResponseWriter != null || stream == null ? null : await stream.ReadAsBytes(cancellationToken).ConfigureAwait(false);
8282
var content = bytes == null ? null : httpResponse.GetResponseString(bytes, encoding);
8383

8484
return new RestResponse {
85-
Content = content,
86-
RawBytes = bytes,
87-
ContentEncoding = httpResponse.Content.Headers.ContentEncoding,
88-
Version = httpResponse.RequestMessage?.Version,
89-
ContentLength = httpResponse.Content.Headers.ContentLength,
90-
ContentType = httpResponse.Content.Headers.ContentType?.MediaType,
91-
ResponseStatus = calculateResponseStatus(httpResponse),
92-
ErrorException = MaybeException(),
93-
ResponseUri = httpResponse.RequestMessage!.RequestUri,
94-
Server = httpResponse.Headers.Server.ToString(),
95-
StatusCode = httpResponse.StatusCode,
96-
StatusDescription = httpResponse.ReasonPhrase,
97-
IsSuccessful = httpResponse.IsSuccessStatusCode,
98-
Request = request,
99-
Headers = httpResponse.Headers.GetHeaderParameters(),
100-
ContentHeaders = httpResponse.Content.Headers.GetHeaderParameters(),
101-
Cookies = cookieCollection,
102-
RootElement = request.RootElement
85+
Content = content,
86+
RawBytes = bytes,
87+
ContentEncoding = httpResponse.Content.Headers.ContentEncoding,
88+
Version = httpResponse.RequestMessage?.Version,
89+
ContentLength = httpResponse.Content.Headers.ContentLength,
90+
ContentType = httpResponse.Content.Headers.ContentType?.MediaType,
91+
ResponseStatus = calculateResponseStatus(httpResponse),
92+
ErrorException = MaybeException(),
93+
ResponseUri = httpResponse.RequestMessage!.RequestUri,
94+
Server = httpResponse.Headers.Server.ToString(),
95+
StatusCode = httpResponse.StatusCode,
96+
StatusDescription = httpResponse.ReasonPhrase,
97+
IsSuccessStatusCode = httpResponse.IsSuccessStatusCode,
98+
Request = request,
99+
Headers = httpResponse.Headers.GetHeaderParameters(),
100+
ContentHeaders = httpResponse.Content.Headers.GetHeaderParameters(),
101+
Cookies = cookieCollection,
102+
RootElement = request.RootElement
103103
};
104104

105105
Exception? MaybeException()

src/RestSharp/Response/RestResponseBase.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,14 @@ public abstract class RestResponseBase {
6161
public HttpStatusCode StatusCode { get; set; }
6262

6363
/// <summary>
64-
/// Whether or not the response status code indicates success
64+
/// Whether or not the HTTP response status code indicates success
6565
/// </summary>
66-
public bool IsSuccessful { get; set; }
66+
public bool IsSuccessStatusCode { get; set; }
67+
68+
/// <summary>
69+
/// Whether or not the HTTP response status code indicates success and no other error occurred (deserialization, timeout, ...)
70+
/// </summary>
71+
public bool IsSuccessful { get => IsSuccessStatusCode && ResponseStatus == ResponseStatus.Completed; }
6772

6873
/// <summary>
6974
/// Description of HTTP status returned

src/RestSharp/Sync/RestClient.Sync.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,17 @@ public partial class RestClient {
2020
/// Executes the request synchronously, authenticating if needed
2121
/// </summary>
2222
/// <param name="request">Request to be executed</param>
23-
public RestResponse Execute(RestRequest request) => AsyncHelpers.RunSync(() => ExecuteAsync(request));
23+
/// <param name="cancellationToken">The cancellation token</param>
24+
public RestResponse Execute(RestRequest request, CancellationToken cancellationToken = default)
25+
=> AsyncHelpers.RunSync(() => ExecuteAsync(request, cancellationToken));
2426

2527
/// <summary>
2628
/// A specialized method to download files as streams.
2729
/// </summary>
2830
/// <param name="request">Pre-configured request instance.</param>
31+
/// <param name="cancellationToken">The cancellation token</param>
2932
/// <returns>The downloaded stream.</returns>
3033
[PublicAPI]
31-
public Stream? DownloadStream(RestRequest request) => AsyncHelpers.RunSync(() => DownloadStreamAsync(request));
34+
public Stream? DownloadStream(RestRequest request, CancellationToken cancellationToken = default)
35+
=> AsyncHelpers.RunSync(() => DownloadStreamAsync(request, cancellationToken));
3236
}
763 KB
Loading
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This is a test file for RestSharp.

0 commit comments

Comments
 (0)