@@ -0,0 +1,134 @@
1+// <copyright file="RequestBodyFactory.cs" company="On Test Automation">
2+// Copyright 2019 the original author or authors.
3+//
4+// Licensed under the Apache License, Version 2.0 (the "License");
5+// you may not use this file except in compliance with the License.
6+// You may obtain a copy of the License at
7+//
8+// http://www.apache.org/licenses/LICENSE-2.0
9+//
10+// Unless required by applicable law or agreed to in writing, software
11+// distributed under the License is distributed on an "AS IS" BASIS,
12+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+// See the License for the specific language governing permissions and
14+// limitations under the License.
15+// </copyright>
16+namespace RestAssured.Request
17+{
18+using System.Collections.Generic;
19+using System.IO;
20+using System.Net.Http;
21+using System.Net.Http.Headers;
22+using System.Text;
23+using System.Xml.Serialization;
24+using Microsoft.AspNetCore.StaticFiles;
25+using Newtonsoft.Json;
26+using RestAssured.Request.Exceptions;
27+28+/// <summary>
29+/// Holds the serialization-related settings for creating a request body.
30+/// </summary>
31+/// <param name="contentType">The resolved content type for the request.</param>
32+/// <param name="contentEncoding">The resolved content encoding for the request.</param>
33+/// <param name="stripCharset">Flag indicating whether the charset should be stripped from the content type.</param>
34+/// <param name="jsonSerializerSettings">The resolved JSON serializer settings for the request.</param>
35+internal record RequestBodySettings(
36+string contentType,
37+Encoding contentEncoding,
38+bool stripCharset,
39+JsonSerializerSettings jsonSerializerSettings);
40+41+/// <summary>
42+/// Provides methods for creating and serializing HTTP request bodies.
43+/// </summary>
44+internal static class RequestBodyFactory
45+{
46+/// <summary>
47+/// Creates the body payload for the request.
48+/// </summary>
49+/// <param name="multipartFormDataContent">The multipart form data content, if any.</param>
50+/// <param name="formData">The form data, if any.</param>
51+/// <param name="requestBody">The request body object.</param>
52+/// <param name="settings">The serialization settings for the request body.</param>
53+/// <returns>The request body as an object of type <see cref="HttpContent"/>.</returns>
54+internal static HttpContent Create(
55+MultipartFormDataContent? multipartFormDataContent,
56+IEnumerable<KeyValuePair<string, string>>? formData,
57+object requestBody,
58+RequestBodySettings settings)
59+{
60+if (multipartFormDataContent != null)
61+{
62+return multipartFormDataContent;
63+}
64+65+if (formData != null)
66+{
67+return new FormUrlEncodedContent(formData);
68+}
69+70+string requestBodyAsString = Serialize(requestBody, settings.contentType, settings.jsonSerializerSettings);
71+72+var stringContent = new StringContent(requestBodyAsString, settings.contentEncoding, settings.contentType);
73+74+if (settings.stripCharset)
75+{
76+stringContent.Headers.ContentType!.CharSet = null;
77+}
78+79+return stringContent;
80+}
81+82+/// <summary>
83+/// Serializes the request body to the appropriate format based on the content type.
84+/// </summary>
85+/// <param name="body">The request body object.</param>
86+/// <param name="contentType">The request Content-Type header value.</param>
87+/// <param name="jsonSerializerSettings">The JSON serializer settings to use when serializing to JSON.</param>
88+/// <returns>Either the body itself (if the body is a string), or a serialized version of the body.</returns>
89+internal static string Serialize(object body, string contentType, JsonSerializerSettings jsonSerializerSettings)
90+{
91+if (body is string)
92+{
93+return (string)body;
94+}
95+96+if (contentType.Contains("json"))
97+{
98+return JsonConvert.SerializeObject(body, jsonSerializerSettings);
99+}
100+101+if (contentType.Contains("xml"))
102+{
103+using (StringWriter sw = new StringWriter())
104+{
105+XmlSerializer xmlSerializer = new XmlSerializer(body.GetType());
106+xmlSerializer.Serialize(sw, body);
107+return sw.ToString();
108+}
109+}
110+111+throw new RequestCreationException(
112+$"Could not determine how to serialize request based on specified content type '{contentType}'");
113+}
114+115+/// <summary>
116+/// Determines the content type for a file based on its extension.
117+/// </summary>
118+/// <param name="fileName">The file to determine the content type for.</param>
119+/// <returns>The <see cref="MediaTypeHeaderValue"/> for the file.</returns>
120+internal static MediaTypeHeaderValue GetContentTypeForFile(FileInfo fileName)
121+{
122+FileExtensionContentTypeProvider provider = new FileExtensionContentTypeProvider();
123+124+string contentType;
125+126+if (!provider.TryGetContentType(fileName.FullName, out contentType!))
127+{
128+contentType = "application/octet-stream";
129+}
130+131+return MediaTypeHeaderValue.Parse(contentType);
132+}
133+}
134+}