Skip to content

Commit

Permalink
Rewrite payload serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
matteocontrini committed Oct 26, 2023
1 parent 06677e9 commit 924b708
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 119 deletions.
9 changes: 0 additions & 9 deletions PlainHttp/ContentType.cs

This file was deleted.

112 changes: 6 additions & 106 deletions PlainHttp/HttpRequest.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
using Flurl.Util;
using System.Diagnostics;
using System.Diagnostics;
using System.Text;
using System.Text.Json;
using System.Xml;
using System.Xml.Serialization;
using PlainHttp.Payloads;

namespace PlainHttp;

Expand All @@ -25,9 +22,7 @@ public class HttpRequest : IHttpRequest

public Uri? Proxy { get; set; }

public object? Payload { get; set; }

public ContentType ContentType { get; set; } = ContentType.Raw;
public IPayload? Payload { get; set; }

public string? DownloadFileName { get; set; }

Expand Down Expand Up @@ -72,6 +67,7 @@ public async Task<IHttpResponse> SendAsync(CancellationToken cancellationToken =
requestMessage.Headers.TryAddWithoutValidation(headerName, this.Headers[headerName]);
}

// Set the HTTP version
if (this.HttpVersion != null)
{
requestMessage.Version = this.HttpVersion;
Expand All @@ -83,7 +79,7 @@ public async Task<IHttpResponse> SendAsync(CancellationToken cancellationToken =
var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);

// Enable timeout, if set
if (this.Timeout != default)
if (this.Timeout != null)
{
cts.CancelAfter(this.Timeout.Value);
}
Expand All @@ -95,23 +91,7 @@ public async Task<IHttpResponse> SendAsync(CancellationToken cancellationToken =
// Serialize the payload
if (this.Payload != null)
{
switch (this.ContentType)
{
case ContentType.Json:
SerializeToJson(requestMessage);
break;
case ContentType.Xml:
SerializeToXml(requestMessage);
break;
case ContentType.UrlEncoded:
SerializeToUrlEncoded(requestMessage);
break;
case ContentType.Raw:
requestMessage.Content = new StringContent(this.Payload.ToString()!);
break;
default:
throw new ArgumentException($"Unknown content type: {this.ContentType}");
}
requestMessage.Content = this.Payload.Serialize();
}

// Send the request
Expand Down Expand Up @@ -173,86 +153,6 @@ private async Task<IHttpResponse> MockedResponse()
return await CreateHttpResponse(message).ConfigureAwait(false);
}

private void SerializeToUrlEncoded(HttpRequestMessage requestMessage)
{
// Already serialized
if (this.Payload is string stringPayload)
{
requestMessage.Content = new StringContent(
content: stringPayload,
encoding: Encoding.UTF8,
mediaType: "application/x-www-form-urlencoded"
);
}
else
{
var qp = new Flurl.QueryParamCollection();

foreach ((string key, object value) in this.Payload.ToKeyValuePairs())
{
qp.AddOrReplace(key, value, false, Flurl.NullValueHandling.Ignore);
}

string serialized = qp.ToString(true);

requestMessage.Content = new StringContent(
content: serialized,
encoding: Encoding.UTF8,
mediaType: "application/x-www-form-urlencoded"
);
}
}

private void SerializeToXml(HttpRequestMessage requestMessage)
{
string serialized;

// Already serialized
if (this.Payload is string stringPayload)
{
serialized = stringPayload;
}
else
{
XmlSerializer serializer = new XmlSerializer(this.Payload!.GetType());
StringBuilder result = new StringBuilder();

using (var writer = XmlWriter.Create(result))
{
serializer.Serialize(writer, this.Payload);
}

serialized = result.ToString();
}

requestMessage.Content = new StringContent(
content: serialized,
encoding: Encoding.UTF8,
mediaType: "text/xml"
);
}

private void SerializeToJson(HttpRequestMessage requestMessage)
{
string serialized;

// Already serialized
if (this.Payload is string stringPayload)
{
serialized = stringPayload;
}
else
{
serialized = JsonSerializer.Serialize(this.Payload);
}

requestMessage.Content = new StringContent(
content: serialized,
encoding: Encoding.UTF8,
mediaType: "application/json"
);
}

public override string ToString()
{
return $"{this.Method} {this.Uri}";
Expand Down
2 changes: 1 addition & 1 deletion PlainHttp/HttpResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public async Task ReadBody()
// Start a stopwatch to measure how long the read will last
stopwatch = Stopwatch.StartNew();

if (this.Request.Timeout != default)
if (this.Request.Timeout != null)
{
// Calculate how much time we have left
newTimeout = this.Request.Timeout.Value - this.ElapsedTime;
Expand Down
7 changes: 4 additions & 3 deletions PlainHttp/IHttpRequest.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
namespace PlainHttp;
using PlainHttp.Payloads;

namespace PlainHttp;

public interface IHttpRequest
{
ContentType ContentType { get; set; }
string? DownloadFileName { get; set; }
Dictionary<string, string> Headers { get; set; }
HttpRequestMessage? Message { get; }
HttpMethod Method { get; set; }
object? Payload { get; set; }
IPayload? Payload { get; set; }
Uri? Proxy { get; set; }
TimeSpan? Timeout { get; set; }
Uri Uri { get; set; }
Expand Down
44 changes: 44 additions & 0 deletions PlainHttp/Payloads/FormUrlEncodedPayload.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System.Text;
using Flurl.Util;

namespace PlainHttp.Payloads;

public class FormUrlEncodedPayload : IPayload
{
private readonly object payload;

public FormUrlEncodedPayload(object payload)
{
this.payload = payload;
}

public HttpContent Serialize()
{
// Already serialized
if (this.payload is string stringPayload)
{
return new StringContent(
content: stringPayload,
encoding: Encoding.UTF8,
mediaType: "application/x-www-form-urlencoded"
);
}
else
{
var qp = new Flurl.QueryParamCollection();

foreach ((string key, object value) in this.payload.ToKeyValuePairs())
{
qp.AddOrReplace(key, value, false, Flurl.NullValueHandling.Ignore);
}

string serialized = qp.ToString(true);

return new StringContent(
content: serialized,
encoding: Encoding.UTF8,
mediaType: "application/x-www-form-urlencoded"
);
}
}
}
6 changes: 6 additions & 0 deletions PlainHttp/Payloads/IPayload.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace PlainHttp.Payloads;

public interface IPayload
{
HttpContent Serialize();
}
41 changes: 41 additions & 0 deletions PlainHttp/Payloads/JsonPayload.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System.Text;
using System.Text.Json;

namespace PlainHttp.Payloads;

public class JsonPayload : IPayload
{
private readonly object payload;
private readonly JsonSerializerOptions? options;

public JsonPayload(object payload)
{
this.payload = payload;
}

public JsonPayload(object payload, JsonSerializerOptions options) : this(payload)
{
this.options = options;
}

public HttpContent Serialize()
{
string serialized;

// Already serialized
if (this.payload is string stringPayload)
{
serialized = stringPayload;
}
else
{
serialized = JsonSerializer.Serialize(this.payload, this.options);
}

return new StringContent(
content: serialized,
encoding: Encoding.UTF8,
mediaType: "application/json"
);
}
}
50 changes: 50 additions & 0 deletions PlainHttp/Payloads/XmlPayload.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace PlainHttp.Payloads;

public class XmlPayload : IPayload
{
private readonly object payload;
private readonly XmlWriterSettings? settings;

public XmlPayload(object payload)
{
this.payload = payload;
}

public XmlPayload(object payload, XmlWriterSettings settings) : this(payload)
{
this.settings = settings;
}

public HttpContent Serialize()
{
string serialized;

// Already serialized
if (this.payload is string stringPayload)
{
serialized = stringPayload;
}
else
{
XmlSerializer serializer = new XmlSerializer(this.payload.GetType());
StringBuilder result = new StringBuilder();

using (var writer = XmlWriter.Create(result, this.settings))
{
serializer.Serialize(writer, this.payload);
}

serialized = result.ToString();
}

return new StringContent(
content: serialized,
encoding: Encoding.UTF8,
mediaType: "text/xml"
);
}
}

0 comments on commit 924b708

Please sign in to comment.