Skip to content

Commit d184961

Browse files
Consider the boundary quotes request option value (#2020)
* Consider the boundary quotes request option value * Set the boundary quote marks to true as it's the current default * Fixed the boundary quotes
1 parent 93ca86a commit d184961

File tree

3 files changed

+43
-25
lines changed

3 files changed

+43
-25
lines changed

src/RestSharp/Request/RequestContent.cs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public HttpContent BuildContent() {
4949
void AddFiles() {
5050
if (!_request.HasFiles() && !_request.AlwaysMultipartFormData) return;
5151

52-
var mpContent = new MultipartFormDataContent(GetOrSetFormBoundary());
52+
var mpContent = CreateMultipartFormDataContent();
5353

5454
foreach (var file in _request.Files) {
5555
var stream = file.GetFile();
@@ -60,10 +60,7 @@ void AddFiles() {
6060

6161
var dispositionHeader = file.Options.DisableFilenameEncoding
6262
? ContentDispositionHeaderValue.Parse($"form-data; name=\"{file.Name}\"; filename=\"{file.FileName}\"")
63-
: new ContentDispositionHeaderValue("form-data") {
64-
Name = $"\"{file.Name}\"",
65-
FileName = $"\"{file.FileName}\""
66-
};
63+
: new ContentDispositionHeaderValue("form-data") { Name = $"\"{file.Name}\"", FileName = $"\"{file.FileName}\"" };
6764
if (!file.Options.DisableFileNameStar) dispositionHeader.FileNameStar = file.FileName;
6865
fileContent.Headers.ContentDisposition = dispositionHeader;
6966

@@ -104,11 +101,7 @@ HttpContent GetSerialized() {
104101

105102
var contentType = body.ContentType.Or(serializer.Serializer.ContentType);
106103

107-
return new StringContent(
108-
content,
109-
_client.Options.Encoding,
110-
contentType.Value
111-
);
104+
return new StringContent(content, _client.Options.Encoding, contentType.Value);
112105
}
113106
}
114107

@@ -119,6 +112,15 @@ static bool BodyShouldBeMultipartForm(BodyParameter bodyParameter) {
119112

120113
string GetOrSetFormBoundary() => _request.FormBoundary ?? (_request.FormBoundary = Guid.NewGuid().ToString());
121114

115+
MultipartFormDataContent CreateMultipartFormDataContent() {
116+
var boundary = GetOrSetFormBoundary();
117+
var mpContent = new MultipartFormDataContent(boundary);
118+
var contentType = new MediaTypeHeaderValue("multipart/form-data");
119+
contentType.Parameters.Add(new NameValueHeaderValue(nameof(boundary), GetBoundary(boundary, _request.MultipartFormQuoteParameters)));
120+
mpContent.Headers.ContentType = contentType;
121+
return mpContent;
122+
}
123+
122124
void AddBody(bool hasPostParameters) {
123125
if (!_request.TryGetBodyParameter(out var bodyParameter)) return;
124126

@@ -127,7 +129,7 @@ void AddBody(bool hasPostParameters) {
127129
// we need to send the body
128130
if (hasPostParameters || _request.HasFiles() || BodyShouldBeMultipartForm(bodyParameter!) || _request.AlwaysMultipartFormData) {
129131
// here we must use multipart form data
130-
var mpContent = Content as MultipartFormDataContent ?? new MultipartFormDataContent(GetOrSetFormBoundary());
132+
var mpContent = Content as MultipartFormDataContent ?? CreateMultipartFormDataContent();
131133
var ct = bodyContent.Headers.ContentType?.MediaType;
132134
var name = bodyParameter!.Name.IsEmpty() ? ct : bodyParameter.Name;
133135

@@ -157,7 +159,7 @@ void AddPostParameters(GetOrPostParameter[] postParameters) {
157159

158160
mpContent.Add(
159161
new StringContent(postParameter.Value?.ToString() ?? "", _client.Options.Encoding, postParameter.ContentType.Value),
160-
_request.MultipartFormQuoteParameters ? $"\"{parameterName}\"" : parameterName
162+
parameterName
161163
);
162164
}
163165
}
@@ -179,6 +181,8 @@ void AddPostParameters(GetOrPostParameter[] postParameters) {
179181
}
180182
}
181183

184+
static string GetBoundary(string boundary, bool quote) => quote ? $"\"{boundary}\"" : boundary;
185+
182186
void AddHeaders() {
183187
var contentHeaders = _parameters
184188
.GetParameters<HeaderParameter>()
@@ -205,7 +209,7 @@ void AddHeader(HeaderParameter parameter) {
205209

206210
string GetContentTypeHeader(string contentType)
207211
=> Content is MultipartFormDataContent
208-
? $"{contentType}; boundary=\"{GetOrSetFormBoundary()}\""
212+
? $"{contentType}; boundary={GetBoundary(GetOrSetFormBoundary(), _request.MultipartFormQuoteParameters)}"
209213
: contentType;
210214
}
211215

src/RestSharp/Request/RestRequest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ public RestRequest(Uri resource, Method method = Method.Get)
8686
/// quotation marks. Default is false. Enable it if the remote endpoint requires parameters
8787
/// to be in quotes (for example, FreshDesk API).
8888
/// </summary>
89-
public bool MultipartFormQuoteParameters { get; set; }
89+
public bool MultipartFormQuoteParameters { get; set; } = true;
9090

9191
public string? FormBoundary { get; set; }
9292

test/RestSharp.Tests.Integrated/MultipartFormDataTests.cs

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ public MultipartFormDataTests(ITestOutputHelper output) {
3232
$"--{{0}}--{LineBreak}";
3333

3434
const string ExpectedFileAndBodyRequestContent =
35-
"--{0}" +
36-
$"{LineBreak}{KnownHeaders.ContentType}: application/octet-stream" +
35+
"--{0}" +
36+
$"{LineBreak}{KnownHeaders.ContentType}: application/octet-stream" +
3737
$"{LineBreak}{KnownHeaders.ContentDisposition}: form-data; name=\"fileName\"; filename=\"TestFile.txt\"" +
38-
$"{LineBreak}{LineBreak}This is a test file for RestSharp.{LineBreak}" +
39-
$"--{{0}}{LineBreak}{KnownHeaders.ContentType}: application/json; {CharsetString}" +
40-
$"{LineBreak}{KnownHeaders.ContentDisposition}: form-data; name=controlName" +
41-
$"{LineBreak}{LineBreak}test{LineBreak}" +
38+
$"{LineBreak}{LineBreak}This is a test file for RestSharp.{LineBreak}" +
39+
$"--{{0}}{LineBreak}{KnownHeaders.ContentType}: application/json; {CharsetString}" +
40+
$"{LineBreak}{KnownHeaders.ContentDisposition}: form-data; name=controlName" +
41+
$"{LineBreak}{LineBreak}test{LineBreak}" +
4242
$"--{{0}}--{LineBreak}";
4343

4444
const string ExpectedDefaultMultipartContentType = "multipart/form-data; boundary=\"{0}\"";
@@ -76,11 +76,24 @@ public async Task AlwaysMultipartFormData_WithParameter_Execute() {
7676
Assert.Null(response.ErrorException);
7777
}
7878

79+
[Fact]
80+
public async Task MultipartFormData_NoBoundaryQuotes() {
81+
var request = new RestRequest("/", Method.Post) { AlwaysMultipartFormData = true };
82+
83+
AddParameters(request);
84+
request.MultipartFormQuoteParameters = false;
85+
86+
var response = await _client.ExecuteAsync(request);
87+
88+
var expected = string.Format(Expected, request.FormBoundary);
89+
90+
response.Content.Should().Be(expected);
91+
RequestHandler.CapturedContentType.Should().Be($"multipart/form-data; boundary={request.FormBoundary}");
92+
}
93+
7994
[Fact]
8095
public async Task MultipartFormData() {
81-
var request = new RestRequest("/", Method.Post) {
82-
AlwaysMultipartFormData = true
83-
};
96+
var request = new RestRequest("/", Method.Post) { AlwaysMultipartFormData = true };
8497

8598
AddParameters(request);
8699

@@ -91,7 +104,8 @@ public async Task MultipartFormData() {
91104
_output.WriteLine($"Expected: {expected}");
92105
_output.WriteLine($"Actual: {response.Content}");
93106

94-
Assert.Equal(expected, response.Content);
107+
response.Content.Should().Be(expected);
108+
RequestHandler.CapturedContentType.Should().Be($"multipart/form-data; boundary=\"{request.FormBoundary}\"");
95109
}
96110

97111
[Fact]
@@ -187,4 +201,4 @@ public async Task ShouldHaveJsonContentType() {
187201

188202
var response = await _client.ExecuteAsync(request);
189203
}
190-
}
204+
}

0 commit comments

Comments
 (0)