diff --git a/PlainHttp/ContentType.cs b/PlainHttp/ContentType.cs deleted file mode 100644 index 70ab5a2..0000000 --- a/PlainHttp/ContentType.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace PlainHttp; - -public enum ContentType -{ - Raw, - Json, - Xml, - UrlEncoded -} diff --git a/PlainHttp/HttpRequest.cs b/PlainHttp/HttpRequest.cs index 5b5e93b..ecfda1b 100644 --- a/PlainHttp/HttpRequest.cs +++ b/PlainHttp/HttpRequest.cs @@ -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; @@ -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; } @@ -72,6 +67,7 @@ public async Task SendAsync(CancellationToken cancellationToken = requestMessage.Headers.TryAddWithoutValidation(headerName, this.Headers[headerName]); } + // Set the HTTP version if (this.HttpVersion != null) { requestMessage.Version = this.HttpVersion; @@ -83,7 +79,7 @@ public async Task 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); } @@ -95,23 +91,7 @@ public async Task 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 @@ -173,86 +153,6 @@ private async Task 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}"; diff --git a/PlainHttp/HttpResponse.cs b/PlainHttp/HttpResponse.cs index 536c02b..b7cfbd3 100644 --- a/PlainHttp/HttpResponse.cs +++ b/PlainHttp/HttpResponse.cs @@ -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; diff --git a/PlainHttp/IHttpRequest.cs b/PlainHttp/IHttpRequest.cs index 0bfff75..2e81857 100644 --- a/PlainHttp/IHttpRequest.cs +++ b/PlainHttp/IHttpRequest.cs @@ -1,13 +1,14 @@ -namespace PlainHttp; +using PlainHttp.Payloads; + +namespace PlainHttp; public interface IHttpRequest { - ContentType ContentType { get; set; } string? DownloadFileName { get; set; } Dictionary 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; } diff --git a/PlainHttp/Payloads/FormUrlEncodedPayload.cs b/PlainHttp/Payloads/FormUrlEncodedPayload.cs new file mode 100644 index 0000000..defbd45 --- /dev/null +++ b/PlainHttp/Payloads/FormUrlEncodedPayload.cs @@ -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" + ); + } + } +} diff --git a/PlainHttp/Payloads/IPayload.cs b/PlainHttp/Payloads/IPayload.cs new file mode 100644 index 0000000..bde0aed --- /dev/null +++ b/PlainHttp/Payloads/IPayload.cs @@ -0,0 +1,6 @@ +namespace PlainHttp.Payloads; + +public interface IPayload +{ + HttpContent Serialize(); +} diff --git a/PlainHttp/Payloads/JsonPayload.cs b/PlainHttp/Payloads/JsonPayload.cs new file mode 100644 index 0000000..8eec600 --- /dev/null +++ b/PlainHttp/Payloads/JsonPayload.cs @@ -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" + ); + } +} diff --git a/PlainHttp/Payloads/XmlPayload.cs b/PlainHttp/Payloads/XmlPayload.cs new file mode 100644 index 0000000..fd9da00 --- /dev/null +++ b/PlainHttp/Payloads/XmlPayload.cs @@ -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" + ); + } +}