Skip to content

Commit 6091d72

Browse files
committed
Setting the form boundary for #1716
1 parent 6c7b73b commit 6091d72

File tree

4 files changed

+19
-127
lines changed

4 files changed

+19
-127
lines changed

Diff for: src/RestSharp/Request/HttpContentExtensions.cs

-42
This file was deleted.

Diff for: src/RestSharp/Request/RequestContent.cs

+10-18
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,6 @@ public HttpContent BuildContent() {
4444
var postParameters = _request.Parameters.GetContentParameters(_request.Method);
4545
AddBody(!postParameters.IsEmpty());
4646
AddPostParameters(postParameters);
47-
48-
if (Content is MultipartFormDataContent && _request.FormatMultipartContentType != null) {
49-
ReplaceHeader(ContentType, GetContentTypeHeader(Content.Headers.ContentType!.MediaType!));
50-
}
51-
5247
AddHeaders();
5348

5449
return Content!;
@@ -57,7 +52,7 @@ public HttpContent BuildContent() {
5752
void AddFiles() {
5853
if (!_request.HasFiles() && !_request.AlwaysMultipartFormData) return;
5954

60-
var mpContent = new MultipartFormDataContent();
55+
var mpContent = new MultipartFormDataContent(GetOrSetFormBoundary());
6156

6257
foreach (var file in _request.Files) {
6358
var stream = file.GetFile();
@@ -122,6 +117,8 @@ static bool BodyShouldBeMultipartForm(BodyParameter bodyParameter) {
122117
return bodyParameter.Name.IsNotEmpty() && bodyParameter.Name != bodyContentType;
123118
}
124119

120+
string GetOrSetFormBoundary() => _request.FormBoundary ?? (_request.FormBoundary = Guid.NewGuid().ToString());
121+
125122
void AddBody(bool hasPostParameters) {
126123
if (!_request.TryGetBodyParameter(out var bodyParameter)) return;
127124

@@ -130,7 +127,7 @@ void AddBody(bool hasPostParameters) {
130127
// we need to send the body
131128
if (hasPostParameters || _request.HasFiles() || BodyShouldBeMultipartForm(bodyParameter!) || _request.AlwaysMultipartFormData) {
132129
// here we must use multipart form data
133-
var mpContent = Content as MultipartFormDataContent ?? new MultipartFormDataContent();
130+
var mpContent = Content as MultipartFormDataContent ?? new MultipartFormDataContent(GetOrSetFormBoundary());
134131
var ct = bodyContent.Headers.ContentType?.MediaType;
135132
var name = bodyParameter!.Name.IsEmpty() ? ct : bodyParameter.Name;
136133

@@ -167,7 +164,7 @@ void AddPostParameters(ParametersCollection? postParameters) {
167164
var formContent = new FormUrlEncodedContent(
168165
_request.Parameters
169166
.Where(x => x.Type == ParameterType.GetOrPost)
170-
.Select(x => new KeyValuePair<string, string>(x.Name!, x.Value!.ToString()!))!
167+
.Select(x => new KeyValuePair<string, string>(x.Name!, x.Value!.ToString()!))
171168
);
172169
Content = formContent;
173170
}
@@ -195,23 +192,18 @@ void AddHeader(Parameter parameter) {
195192
var pName = Ensure.NotNull(parameter.Name, nameof(parameter.Name));
196193
ReplaceHeader(pName, value);
197194
}
195+
196+
string GetContentTypeHeader(string contentType)
197+
=> Content is MultipartFormDataContent
198+
? $"{contentType}; boundary=\"{GetOrSetFormBoundary()}\""
199+
: contentType;
198200
}
199201

200202
void ReplaceHeader(string name, string? value) {
201203
Content!.Headers.Remove(name);
202204
Content!.Headers.TryAddWithoutValidation(name, value);
203205
}
204206

205-
static readonly FormatContentTypeHeader DefaultContentTypeHeader = (contentType, boundary) => $"{contentType}; boundary=\"{boundary}\"";
206-
207-
string GetContentTypeHeader(string contentType) {
208-
return Content is MultipartFormDataContent mpContent
209-
? ContentTypeValue()(contentType, mpContent.GetFormBoundary())
210-
: contentType;
211-
212-
FormatContentTypeHeader ContentTypeValue() => _request.FormatMultipartContentType ?? DefaultContentTypeHeader;
213-
}
214-
215207
public void Dispose() {
216208
_streams.ForEach(x => x.Dispose());
217209
Content?.Dispose();

Diff for: src/RestSharp/Request/RestRequest.cs

+2-7
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717

1818
namespace RestSharp;
1919

20-
public delegate string FormatContentTypeHeader(string contentType, string formBoundary);
21-
2220
/// <summary>
2321
/// Container for data used to make requests
2422
/// </summary>
@@ -69,6 +67,8 @@ public RestRequest(Uri resource, Method method = Method.Get)
6967
/// Always send a multipart/form-data request - even when no Files are present.
7068
/// </summary>
7169
public bool AlwaysMultipartFormData { get; set; }
70+
71+
public string? FormBoundary { get; set; }
7272

7373
/// <summary>
7474
/// Container of all HTTP parameters to be passed with the request.
@@ -147,11 +147,6 @@ public RestRequest(Uri resource, Method method = Method.Get)
147147
/// </summary>
148148
public HttpCompletionOption CompletionOption { get; set; } = HttpCompletionOption.ResponseContentRead;
149149

150-
/// <summary>
151-
/// Function that formats the content type header for multipart form fata
152-
/// </summary>
153-
public FormatContentTypeHeader? FormatMultipartContentType { get; set; }
154-
155150
/// <summary>
156151
/// Set this to write response to Stream rather than reading into memory.
157152
/// </summary>

Diff for: test/RestSharp.Tests.Integrated/MultipartFormDataTests.cs

+7-60
Original file line numberDiff line numberDiff line change
@@ -84,16 +84,9 @@ public async Task MultipartFormData() {
8484

8585
AddParameters(request);
8686

87-
string boundary = null;
88-
89-
request.OnBeforeRequest = http => {
90-
boundary = ((MultipartFormDataContent)http.Content)!.GetFormBoundary();
91-
return default;
92-
};
93-
9487
var response = await _client.ExecuteAsync(request);
9588

96-
var expected = string.Format(Expected, boundary);
89+
var expected = string.Format(Expected, request.FormBoundary);
9790

9891
_output.WriteLine($"Expected: {expected}");
9992
_output.WriteLine($"Actual: {response.Content}");
@@ -110,15 +103,10 @@ public async Task MultipartFormData_HasDefaultContentType() {
110103

111104
request.AddParameter(new BodyParameter("controlName", "test", "application/json"));
112105

113-
string boundary = null;
114-
115-
request.OnBeforeRequest = http => {
116-
boundary = ((MultipartFormDataContent)http.Content)!.GetFormBoundary();
117-
return default;
118-
};
119-
120106
var response = await _client.ExecuteAsync(request);
121107

108+
var boundary = request.FormBoundary;
109+
122110
var expectedFileAndBodyRequestContent = string.Format(ExpectedFileAndBodyRequestContent, boundary);
123111
var expectedDefaultMultipartContentType = string.Format(ExpectedDefaultMultipartContentType, boundary);
124112

@@ -140,14 +128,8 @@ public async Task MultipartFormData_WithCustomContentType() {
140128
request.AddFile("fileName", path);
141129
request.AddParameter(new BodyParameter("controlName", "test", "application/json"));
142130

143-
string boundary = null;
144-
145-
request.OnBeforeRequest = http => {
146-
boundary = ((MultipartFormDataContent)http.Content)!.GetFormBoundary();
147-
return default;
148-
};
149-
150131
var response = await _client.ExecuteAsync(request);
132+
var boundary = request.FormBoundary;
151133

152134
var expectedFileAndBodyRequestContent = string.Format(ExpectedFileAndBodyRequestContent, boundary);
153135
var expectedCustomMultipartContentType = string.Format(ExpectedCustomMultipartContentType, boundary);
@@ -167,58 +149,23 @@ public async Task MultipartFormData_WithParameterAndFile_Async() {
167149

168150
request.AddParameter(new BodyParameter("controlName", "test", "application/json"));
169151

170-
string boundary = null;
171-
172-
request.OnBeforeRequest = http => {
173-
boundary = ((MultipartFormDataContent)http.Content)!.GetFormBoundary();
174-
return default;
175-
};
176-
177152
var response = await _client.ExecuteAsync(request);
153+
var boundary = request.FormBoundary;
178154

179155
var expectedFileAndBodyRequestContent = string.Format(ExpectedFileAndBodyRequestContent, boundary);
180156

181157
response.Content.Should().Be(expectedFileAndBodyRequestContent);
182158
}
183159

184-
[Fact]
185-
public async Task MultipartFormDataWithBoundaryOverride() {
186-
var request = new RestRequest("/", Method.Post) {
187-
AlwaysMultipartFormData = true,
188-
FormatMultipartContentType = (ct, b) => $"{ct}; boundary=--------{b}"
189-
};
190-
191-
AddParameters(request);
192-
193-
HttpContent content = null;
194-
var boundary = "";
195-
196-
request.OnBeforeRequest = http => {
197-
content = http.Content;
198-
boundary = ((MultipartFormDataContent)http.Content)!.GetFormBoundary();
199-
return default;
200-
};
201-
202-
await _client.ExecuteAsync(request);
203-
204-
var contentType = content.Headers.ContentType!.ToString();
205-
contentType.Should().Be($"multipart/form-data; boundary=--------{boundary}");
206-
}
207-
208160
[Fact]
209161
public async Task MultipartFormDataAsync() {
210162
var request = new RestRequest("/", Method.Post) { AlwaysMultipartFormData = true };
211163

212164
AddParameters(request);
213165

214-
string boundary = null;
215-
216-
request.OnBeforeRequest = http => {
217-
boundary = ((MultipartFormDataContent)http.Content)!.GetFormBoundary();
218-
return default;
219-
};
220-
221166
var response = await _client.ExecuteAsync(request);
167+
168+
var boundary = request.FormBoundary;
222169
var expected = string.Format(Expected, boundary);
223170

224171
response.Content.Should().Be(expected);

0 commit comments

Comments
 (0)