Skip to content

Commit 1d1dfaf

Browse files
committed
Fix the custom boundary format
1 parent 6a91263 commit 1d1dfaf

File tree

3 files changed

+45
-6
lines changed

3 files changed

+45
-6
lines changed

src/RestSharp/Request/RequestContent.cs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,13 @@ 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+
4752
AddHeaders();
53+
4854
return Content!;
4955
}
5056

@@ -180,16 +186,25 @@ void AddHeader(Parameter parameter) {
180186
_ => parameterStringValue
181187
};
182188
var pName = Ensure.NotNull(parameter.Name, nameof(parameter.Name));
183-
Content!.Headers.Remove(pName);
184-
Content!.Headers.TryAddWithoutValidation(pName, value);
189+
ReplaceHeader(pName, value);
185190
}
186191
}
187192

188-
string GetContentTypeHeader(string contentType)
189-
=> Content is MultipartFormDataContent mpContent
190-
? _request.FormatMultipartContentType(contentType, mpContent.GetFormBoundary())
193+
void ReplaceHeader(string name, string? value) {
194+
Content!.Headers.Remove(name);
195+
Content!.Headers.TryAddWithoutValidation(name, value);
196+
}
197+
198+
static readonly FormatContentTypeHeader DefaultContentTypeHeader = (contentType, boundary) => $"{contentType}; boundary=\"{boundary}\"";
199+
200+
string GetContentTypeHeader(string contentType) {
201+
return Content is MultipartFormDataContent mpContent
202+
? ContentTypeValue()(contentType, mpContent.GetFormBoundary())
191203
: contentType;
192204

205+
FormatContentTypeHeader ContentTypeValue() => _request.FormatMultipartContentType ?? DefaultContentTypeHeader;
206+
}
207+
193208
public void Dispose() {
194209
_streams.ForEach(x => x.Dispose());
195210
Content?.Dispose();

src/RestSharp/Request/RestRequest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ public RestRequest(Uri resource, Method method = Method.Get)
150150
/// <summary>
151151
/// Function that formats the content type header for multipart form fata
152152
/// </summary>
153-
public FormatContentTypeHeader FormatMultipartContentType { get; set; } = (contentType, boundary) => $"{contentType}; boundary=\"{boundary}\"";
153+
public FormatContentTypeHeader? FormatMultipartContentType { get; set; }
154154

155155
/// <summary>
156156
/// Set this to write response to Stream rather than reading into memory.

test/RestSharp.Tests.Integrated/MultipartFormDataTests.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,30 @@ public async Task MultipartFormData_WithParameterAndFile_Async() {
177177
response.Content.Should().Be(expectedFileAndBodyRequestContent);
178178
}
179179

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

0 commit comments

Comments
 (0)