Skip to content

Commit

Permalink
Merge pull request #1464 from Trellmor/RandomMultipartFormDataBoundary
Browse files Browse the repository at this point in the history
Use random value for multipart/form-data boundary.
  • Loading branch information
alexeyzimarev authored May 18, 2020
2 parents 1636701 + d16475b commit b0816cc
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 23 deletions.
8 changes: 4 additions & 4 deletions src/RestSharp/Http.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public partial class Http : IHttp
{
const string LineBreak = "\r\n";

const string FormBoundary = "-----------------------------28947758029299";
public string FormBoundary { get; } = "---------" + Guid.NewGuid().ToString().ToUpper();

static readonly Regex AddRangeRegex = new Regex("(\\w+)=(\\d+)-(\\d+)$");

Expand Down Expand Up @@ -234,7 +234,7 @@ static void AddRange(HttpWebRequest r, string range)

static HttpWebRequest CreateRequest(Uri uri) => (HttpWebRequest) WebRequest.Create(uri);

static string GetMultipartFileHeader(HttpFile file)
string GetMultipartFileHeader(HttpFile file)
=> $"--{FormBoundary}{LineBreak}Content-Disposition: form-data; name=\"{file.Name}\";" +
$" filename=\"{file.FileName}\"{LineBreak}" +
$"Content-Type: {file.ContentType ?? "application/octet-stream"}{LineBreak}{LineBreak}";
Expand All @@ -248,7 +248,7 @@ string GetMultipartFormData(HttpParameter param)
return string.Format(format, FormBoundary, param.Name, param.Value, LineBreak, param.ContentType);
}

static string GetMultipartFooter() => $"--{FormBoundary}--{LineBreak}";
string GetMultipartFooter() => $"--{FormBoundary}--{LineBreak}";

void PreparePostBody(WebRequest webRequest)
{
Expand All @@ -272,7 +272,7 @@ void PreparePostBody(WebRequest webRequest)

string EncodeParameters() => string.Join("&", Parameters.Select(p => $"{Encode(p.Name)}={Encode(p.Value)}"));

static string GetMultipartFormContentType() => $"multipart/form-data; boundary={FormBoundary}";
string GetMultipartFormContentType() => $"multipart/form-data; boundary={FormBoundary}";
}

void WriteMultipartFormData(Stream requestStream)
Expand Down
5 changes: 5 additions & 0 deletions src/RestSharp/IHttp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,11 @@ public interface IHttp
/// </summary>
string Host { get; set; }

/// <summary>
/// Boundary that will be used for multipart/form-data requests
/// </summary>
string FormBoundary { get; }

/// <summary>
/// List of allowed decompression methods
/// </summary>
Expand Down
66 changes: 50 additions & 16 deletions test/RestSharp.IntegrationTests/MultipartFormDataTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,30 +24,30 @@ public void SetupServer()
const string LineBreak = "\r\n";

readonly string _expected =
"-------------------------------28947758029299" + LineBreak +
"--{0}" + LineBreak +
"Content-Disposition: form-data; name=\"foo\"" + LineBreak + LineBreak +
"bar" + LineBreak +
"-------------------------------28947758029299" + LineBreak +
"--{0}" + LineBreak +
"Content-Disposition: form-data; name=\"a name with spaces\"" + LineBreak + LineBreak +
"somedata" + LineBreak +
"-------------------------------28947758029299--" + LineBreak;
"--{0}--" + LineBreak;

readonly string _expectedFileAndBodyRequestContent =
"-------------------------------28947758029299" + LineBreak +
"--{0}" + LineBreak +
"Content-Type: application/json" + LineBreak +
"Content-Disposition: form-data; name=\"controlName\"" + LineBreak + LineBreak +
"test" + LineBreak +
"-------------------------------28947758029299" + LineBreak +
"--{0}" + LineBreak +
"Content-Disposition: form-data; name=\"fileName\"; filename=\"TestFile.txt\"" + LineBreak +
"Content-Type: application/octet-stream" + LineBreak + LineBreak +
"This is a test file for RestSharp." + LineBreak +
"-------------------------------28947758029299--" + LineBreak;
"--{0}--" + LineBreak;

readonly string _expectedDefaultMultipartContentType =
"multipart/form-data; boundary=-----------------------------28947758029299";
"multipart/form-data; boundary={0}";

readonly string _expectedCustomMultipartContentType =
"multipart/vnd.resteasy+form-data; boundary=-----------------------------28947758029299";
"multipart/vnd.resteasy+form-data; boundary={0}";

SimpleServer _server;
RestClient _client;
Expand Down Expand Up @@ -139,9 +139,14 @@ public void MultipartFormData()

AddParameters(request);

string boundary = null;
request.OnBeforeRequest += http => boundary = http.FormBoundary;

var response = _client.Execute(request);

Assert.AreEqual(_expected, response.Content);
var expected = string.Format(_expected, boundary);

Assert.AreEqual(expected, response.Content);
}

[Test]
Expand All @@ -154,10 +159,16 @@ public void MultipartFormData_HasDefaultContentType()

request.AddParameter("controlName", "test", "application/json", ParameterType.RequestBody);

string boundary = null;
request.OnBeforeRequest += http => boundary = http.FormBoundary;

var response = _client.Execute(request);

Assert.AreEqual(_expectedFileAndBodyRequestContent, response.Content);
Assert.AreEqual(_expectedDefaultMultipartContentType, RequestHandler.CapturedContentType);
var expectedFileAndBodyRequestContent = string.Format(_expectedFileAndBodyRequestContent, boundary);
var expectedDefaultMultipartContentType= string.Format(_expectedDefaultMultipartContentType, boundary);

Assert.AreEqual(expectedFileAndBodyRequestContent, response.Content);
Assert.AreEqual(expectedDefaultMultipartContentType, RequestHandler.CapturedContentType);
}

[Test]
Expand All @@ -173,10 +184,16 @@ public void MultipartFormData_WithCustomContentType()

request.AddParameter("controlName", "test", "application/json", ParameterType.RequestBody);

string boundary = null;
request.OnBeforeRequest += http => boundary = http.FormBoundary;

var response = _client.Execute(request);

Assert.AreEqual(_expectedFileAndBodyRequestContent, response.Content);
Assert.AreEqual(_expectedCustomMultipartContentType, RequestHandler.CapturedContentType);
var expectedFileAndBodyRequestContent = string.Format(_expectedFileAndBodyRequestContent, boundary);
var expectedCustomMultipartContentType= string.Format(_expectedCustomMultipartContentType, boundary);

Assert.AreEqual(expectedFileAndBodyRequestContent, response.Content);
Assert.AreEqual(expectedCustomMultipartContentType, RequestHandler.CapturedContentType);
}

[Test]
Expand All @@ -192,9 +209,14 @@ public void MultipartFormData_WithParameterAndFile()

request.AddParameter("controlName", "test", "application/json", ParameterType.RequestBody);

string boundary = null;
request.OnBeforeRequest += http => boundary = http.FormBoundary;

var response = _client.Execute(request);

Assert.AreEqual(_expectedFileAndBodyRequestContent, response.Content);
var expectedFileAndBodyRequestContent = string.Format(_expectedFileAndBodyRequestContent, boundary);

Assert.AreEqual(expectedFileAndBodyRequestContent, response.Content);
}

[Test]
Expand All @@ -210,8 +232,14 @@ public async Task MultipartFormData_WithParameterAndFile_Async()

request.AddParameter("controlName", "test", "application/json", ParameterType.RequestBody);

string boundary = null;
request.OnBeforeRequest += http => boundary = http.FormBoundary;

var response = await _client.ExecuteAsync(request);
Assert.AreEqual(_expectedFileAndBodyRequestContent, response.Content);

var expectedFileAndBodyRequestContent = string.Format(_expectedFileAndBodyRequestContent, boundary);

Assert.AreEqual(expectedFileAndBodyRequestContent, response.Content);
}

[Test]
Expand All @@ -224,11 +252,17 @@ public void MultipartFormDataAsync()

AddParameters(request);

string boundary = null;

var expected = string.Format(_expected, boundary);

request.OnBeforeRequest += http => boundary = http.FormBoundary;

_client.ExecuteAsync(
request, (restResponse, handle) =>
{
Console.WriteLine(restResponse.Content);
Assert.AreEqual(_expected, restResponse.Content);
Assert.AreEqual(expected, restResponse.Content);
}
);
}
Expand Down
7 changes: 4 additions & 3 deletions test/RestSharp.IntegrationTests/RequestBodyTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -175,14 +175,15 @@ public void Can_Not_Be_Added_To_HEAD_Request()
[Test]
public void MultipartFormData_Without_File_Creates_A_Valid_RequestBody()
{
const string expectedFormBoundary = "-------------------------------28947758029299";
string expectedFormBoundary = null;

var client = new RestClient(_server.Url);

var request = new RestRequest(RequestBodyCapturer.Resource, Method.POST)
{
AlwaysMultipartFormData = true
};
request.OnBeforeRequest += http => expectedFormBoundary = http.FormBoundary;

const string contentType = "text/plain";
const string bodyData = "abc123 foo bar baz BING!";
Expand All @@ -192,7 +193,7 @@ public void MultipartFormData_Without_File_Creates_A_Valid_RequestBody()

client.Execute(request);

var expectedBody = expectedFormBoundary +
var expectedBody = "--" + expectedFormBoundary +
NewLine
+ "Content-Type: " +
contentType
Expand All @@ -202,7 +203,7 @@ public void MultipartFormData_Without_File_Creates_A_Valid_RequestBody()
+ NewLine
+ bodyData
+ NewLine
+ expectedFormBoundary + "--"
+ "--" + expectedFormBoundary + "--"
+ NewLine;

Assert.AreEqual(
Expand Down

0 comments on commit b0816cc

Please sign in to comment.