Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
<PackageReadmeFile>README.md</PackageReadmeFile>
<RepositoryUrl>https://github.com/AMDevIT/Restling.git</RepositoryUrl>
<PackageTags>rest;httpclient;api;apiclient;client;restclient;restling</PackageTags>
<AssemblyVersion>1.0.18.10</AssemblyVersion>
<AssemblyVersion>1.0.19.0</AssemblyVersion>
<FileVersion>$(AssemblyVersion)</FileVersion>
<PackageReleaseNotes>Added a property used to force json serializer for the HTTP Rest call. Also, it's possibile to define the default JSON serializer for the restling client as a global property.
<PackageReleaseNotes>Added support for raw content requests and form url encoded requests. Also changed behaviours of redirects, now Restling doesn't follow redirects automatically.
</PackageReleaseNotes>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using AMDevIT.Restling.Core.Network;

namespace AMDevIT.Restling.Core
{
/// <summary>
/// Represents a request that will be sent as a non rest compliant form-urlencoded request.
/// </summary>
public class FormUrlEncodedRequest
: RestRequest
{
#region Fields

private readonly IDictionary<string, string> parameters = new Dictionary<string, string>();

#endregion

#region Properties

public IDictionary<string, string> Parameters => this.parameters;

#endregion

#region .ctor

public FormUrlEncodedRequest(string uri,
HttpMethod method,
string? customMethod = null)
: base(uri, method, customMethod)
{
}

public FormUrlEncodedRequest(string uri,
HttpMethod method,
RequestHeaders headers,
string? customMethod = null)
: base(uri, method, headers, customMethod)
{
}

public FormUrlEncodedRequest(string uri,
HttpMethod method,
IDictionary<string, string> parameters,
string? customMethod = null)
: this(uri, method, customMethod)
{
this.parameters = parameters;
}

public FormUrlEncodedRequest(string uri,
HttpMethod method,
RequestHeaders headers,
IDictionary<string, string> parameters,
string? customMethod = null)
: this(uri, method, headers, customMethod)
{
this.parameters = parameters;
}

#endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,22 @@ public async Task<RestRequestResult> DecodeAsync(HttpResponseMessage resultHttpM
{
byte[] rawContent;
RetrievedContentResult retrievedContent;
ResponseHeaders responseHeaders;
MediaTypeHeaderValue? contentType = resultHttpMessage.Content.Headers.ContentType;
Charset charset = CharsetParser.Parse(contentType?.CharSet);
rawContent = await resultHttpMessage.Content.ReadAsByteArrayAsync(cancellationToken);
retrievedContent = RetrieveContent(rawContent, contentType);

responseHeaders = ResponseHeaders.Create(resultHttpMessage.Headers);

restRequestResult = new(restRequest,
resultHttpMessage.StatusCode,
elapsed,
rawContent,
contentType?.MediaType,
charset,
retrievedContent);
retrievedContent,
responseHeaders);
}
else
{
Expand All @@ -79,6 +83,7 @@ public async Task<RestRequestResult<T>> DecodeAsync<T>(HttpResponseMessage resul
byte[] rawContent;
T? data = default;
RetrievedContentResult content;
ResponseHeaders responseHeaders;
MediaTypeHeaderValue? contentType = resultHttpMessage.Content.Headers.ContentType;
Charset charset = CharsetParser.Parse(contentType?.CharSet);
rawContent = await resultHttpMessage.Content.ReadAsByteArrayAsync(cancellationToken);
Expand Down Expand Up @@ -108,14 +113,16 @@ public async Task<RestRequestResult<T>> DecodeAsync<T>(HttpResponseMessage resul
// If not, ignore the exception.
}

responseHeaders = ResponseHeaders.Create(resultHttpMessage.Headers);
restRequestResult = new(restRequest,
data,
resultHttpMessage.StatusCode,
elapsed,
rawContent,
contentType?.MediaType,
charset,
content);
content,
responseHeaders);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,8 @@ public HttpClientContext Build()
SocketsHttpHandler socketsHttpHandler = new()
{
CookieContainer = this.cookieContainer,
UseCookies = true
UseCookies = true,
AllowAutoRedirect = false
};
this.httpMessageHandler = socketsHttpHandler;
this.disposeHandler = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using System.Collections.ObjectModel;
using System.Net.Http.Headers;

namespace AMDevIT.Restling.Core.Network
{
public class ResponseHeaders
{
#region Fields

private static readonly ResponseHeaders empty = new();

private readonly ReadOnlyDictionary<string, IEnumerable<string>> headers;
private readonly string? redirectLocation;

#endregion

#region Properties

public static ResponseHeaders Empty => empty;

public ReadOnlyDictionary<string, IEnumerable<string>> Headers => this.headers;

public string? RedirectLocation => this.redirectLocation;

#endregion

#region .ctor

protected ResponseHeaders()
{
Dictionary<string, IEnumerable<string>> headers = [];
this.headers = new ReadOnlyDictionary<string, IEnumerable<string>>(headers);
this.redirectLocation = null;
}

protected ResponseHeaders(HttpResponseHeaders sourceResponseHeaders)
{
Dictionary<string, IEnumerable<string>> headers = [];

foreach (KeyValuePair<string, IEnumerable<string>> header in sourceResponseHeaders)
{
headers.Add(header.Key, header.Value);
}

this.headers = new ReadOnlyDictionary<string, IEnumerable<string>>(headers);
this.redirectLocation = sourceResponseHeaders.Location?.ToString();
}

#endregion

#region Methods

public static ResponseHeaders Create(HttpResponseHeaders httpResponseMessage)
{
ResponseHeaders responseHeaders = new(httpResponseMessage);
return responseHeaders;
}

public override string ToString()
{
string headers;

if (this.headers.Count > 0)
headers = string.Join(", ", this.headers.Select(h => $"{h.Key}: {h.Value}"));
else
headers = "No headers";

return $"Headers: {headers} - Redirect location: {this.redirectLocation ?? "No redirect location provided"}";
}

#endregion
}
}
105 changes: 105 additions & 0 deletions Sources/AMDevIT.Restling/AMDevIT.Restling.Core/RestRawRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using AMDevIT.Restling.Core.Network;

namespace AMDevIT.Restling.Core
{
public class RestRawRequest
: RestRequest
{
#region Properties

public string? Content
{
get;
set;
}

public string? AcceptType
{
get;
set;
}

public string? ContentType
{
get;
set;
}

#endregion

#region .ctor

public RestRawRequest(string uri,
HttpMethod method,
string? customMethod = null)
: base(uri, method, customMethod)
{
}

public RestRawRequest(string uri,
HttpMethod method,
RequestHeaders headers,
string? customMethod = null)
: base(uri, method, headers, customMethod)
{
}

public RestRawRequest(string uri,
HttpMethod method,
string? content,
string? contentType,
string? customMethod = null)
: base(uri, method, customMethod)
{
this.Content = content;
this.ContentType = contentType;
}

public RestRawRequest(string uri,
HttpMethod method,
string? content,
string? customMethod = null)
: this(uri, method, content: content, contentType: null, customMethod)
{
}

public RestRawRequest(string uri,
HttpMethod method,
string? content,
RequestHeaders headers,
string? customMethod = null)
: this(uri,
method,
content: content,
contentType: null,
headers,
customMethod)
{
}

public RestRawRequest(string uri,
HttpMethod method,
string? content,
string? contentType,
RequestHeaders headers,
string? customMethod = null)
: base(uri, method, headers, customMethod)
{
this.Content = content;
this.ContentType = contentType;
}

#endregion

#region Methods

public override string ToString()
{
return $"{base.ToString()} - Content: {this.Content ?? "No content"} " +
$"- ContentType: {this.ContentType ?? "No content type"} " +
$"- Accept Type: {this.AcceptType ?? "No accept type"}";
}

#endregion
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using AMDevIT.Restling.Core.Text;
using AMDevIT.Restling.Core.Network;
using AMDevIT.Restling.Core.Text;
using System.Net;
using System.Security.AccessControl;

namespace AMDevIT.Restling.Core
{
Expand All @@ -10,6 +12,7 @@ public class RestRequestResult(RestRequest request,
string? contentType,
Charset charset,
RetrievedContentResult? retrievedContent,
ResponseHeaders responseHeaders,
Exception? exception = null)
{
#region Fields
Expand All @@ -22,6 +25,7 @@ public class RestRequestResult(RestRequest request,
private readonly byte[]? rawContent = rawContent;
private readonly RetrievedContentResult? retrievedContent = retrievedContent;
private readonly Exception? exception = exception;
private readonly ResponseHeaders responseHeaders = responseHeaders;

#endregion

Expand All @@ -37,15 +41,16 @@ public class RestRequestResult(RestRequest request,

public string? ContentType => this.contentType;
public Charset CharSet => this.charSet;

public Exception? Exception => this.exception;

public ResponseHeaders ResponseHeaders => this.responseHeaders;

#endregion

#region .ctor

public RestRequestResult(RestRequest request, Exception exception)
: this(request, null, TimeSpan.Zero, [], null, Charset.UTF8, null, exception)
: this(request, null, TimeSpan.Zero, [], null, Charset.UTF8, null, ResponseHeaders.Empty, exception)
{

}
Expand All @@ -59,7 +64,8 @@ public RestRequestResult(RestRequest request,
[],
null,
Charset.UTF8,
null,
null,
ResponseHeaders.Empty,
exception)
{
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using AMDevIT.Restling.Core.Text;
using AMDevIT.Restling.Core.Network;
using AMDevIT.Restling.Core.Text;
using System.Net;

namespace AMDevIT.Restling.Core
Expand Down Expand Up @@ -28,14 +29,16 @@ public RestRequestResult(RestRequest request,
string? contentType,
Charset charset,
RetrievedContentResult? retrievedContent,
ResponseHeaders responseHeaders,
Exception? exception = null)
: base(request,
statusCode,
elapsed,
rawContent,
contentType,
charset,
retrievedContent,
retrievedContent,
responseHeaders,
exception)
{
this.data = data;
Expand Down
Loading