Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

com.utilities.rest 3.1.0 #79

Merged
merged 1 commit into from
Jun 7, 2024
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
com.utilities.rest 3.1.0
- refactor Server Sent Event callback handler
- added Response.ctr with reference to UnityWebRequest
- added Response.ServerSentEvents list
- sealed all public classes
  • Loading branch information
StephenHodgson committed Jun 7, 2024
commit 1f665c436ff28eeeea5f0c815729b60cef054ef4
21 changes: 3 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Advanced features includes progress notifications, authentication and native mul
- [Rest Parameters](#rest-parameters)
- [Get](#get)
- [Post](#post)
- [Server Sent Events](#server-sent-events)
- [Server Sent Events](#server-sent-events) :new:
- [Data Received Callbacks](#data-received-callbacks)
- [Put](#put)
- [Patch](#patch)
Expand Down Expand Up @@ -115,25 +115,10 @@ response.Validate(debug: true);

#### Server Sent Events

> [!WARNING]
> Breaking change. `eventData` payloads are now json objects where the type is the key and field data is value.
> For existing data callbacks, they are now nested: `{"data":"{<payload data>}"}`

Handles [server sent event](https://html.spec.whatwg.org/multipage/server-sent-events.html#server-sent-events) messages.

`eventData` json Schema:

```json
{
"type":"value",
"data":"{<payload data>}" // nullable
}
```

```csharp
var jsonData = "{\"data\":\"content\"}";
var response = await Rest.PostAsync("www.your.api/endpoint", jsonData, eventData => {
Debug.Log(eventData);
var response = await Rest.PostAsync("www.your.api/endpoint", jsonData, (sseResponse, ssEvent) => {
Debug.Log(ssEvent);
});
// Validates the response for you and will throw a RestException if the response is unsuccessful.
response.Validate(debug: true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Advanced features includes progress notifications, authentication and native mul
- [Rest Parameters](#rest-parameters)
- [Get](#get)
- [Post](#post)
- [Server Sent Events](#server-sent-events)
- [Server Sent Events](#server-sent-events) :new:
- [Data Received Callbacks](#data-received-callbacks)
- [Put](#put)
- [Patch](#patch)
Expand Down Expand Up @@ -115,25 +115,10 @@ response.Validate(debug: true);

#### Server Sent Events

> [!WARNING]
> Breaking change. `eventData` payloads are now json objects where the type is the key and field data is value.
> For existing data callbacks, they are now nested: `{"data":"{<payload data>}"}`

Handles [server sent event](https://html.spec.whatwg.org/multipage/server-sent-events.html#server-sent-events) messages.

`eventData` json Schema:

```json
{
"type":"value",
"data":"{<payload data>}" // nullable
}
```

```csharp
var jsonData = "{\"data\":\"content\"}";
var response = await Rest.PostAsync("www.your.api/endpoint", jsonData, eventData => {
Debug.Log(eventData);
var response = await Rest.PostAsync("www.your.api/endpoint", jsonData, (sseResponse, ssEvent) => {
Debug.Log(ssEvent);
});
// Validates the response for you and will throw a RestException if the response is unsuccessful.
response.Validate(debug: true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Utilities.Rest.Extensions
/// Converts empty strings to null values so they are properly ignored by the serializer.
/// https://stackoverflow.com/questions/39855694/convert-empty-strings-to-null-with-json-net
/// </summary>
public class EmptyToNullStringContractResolver : DefaultContractResolver
public sealed class EmptyToNullStringContractResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
=> type.GetProperties()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Utilities.Rest.Extensions
/// <summary>
/// https://stackoverflow.com/questions/39855694/convert-empty-strings-to-null-with-json-net
/// </summary>
public class EmptyToNullStringValueProvider : IValueProvider
public sealed class EmptyToNullStringValueProvider : IValueProvider
{
private readonly PropertyInfo memberInfo;

Expand Down
89 changes: 75 additions & 14 deletions Utilities.Rest/Packages/com.utilities.rest/Runtime/Response.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine.Networking;

namespace Utilities.WebRequestRest
{
/// <summary>
/// Response to a REST Call.
/// </summary>
public class Response
public sealed class Response
{
private static readonly Dictionary<string, string> invalidHeaders = new() { { "Invalid Headers", "Invalid Headers" } };

/// <summary>
/// The original request that prompted the response.
/// </summary>
Expand Down Expand Up @@ -63,6 +66,66 @@ public class Response
/// </summary>
public RestParameters Parameters { get; }

/// <summary>
/// Full list of server sent events.
/// </summary>
public IReadOnlyList<ServerSentEvent> ServerSentEvents => Parameters?.ServerSentEvents;

/// <summary>
/// Constructor.
/// </summary>
/// <param name="webRequest">The request that prompted the response.</param>
/// <param name="requestBody">The request body that prompted the response.</param>
/// <param name="successful">Was the request successful?</param>
/// <param name="parameters">The parameters of the request.</param>
/// <param name="responseBody">Optional, response body override.</param>
public Response(UnityWebRequest webRequest, string requestBody, bool successful, RestParameters parameters, string responseBody = null)
{
Request = webRequest.url;
RequestBody = requestBody;
Method = webRequest.method;
Successful = successful;

if (string.IsNullOrWhiteSpace(responseBody))
{
switch (webRequest.downloadHandler)
{
case DownloadHandlerFile:
case DownloadHandlerTexture:
case DownloadHandlerAudioClip:
case DownloadHandlerAssetBundle:
Body = null;
Data = null;
break;
case DownloadHandlerBuffer downloadHandlerBuffer:
Body = downloadHandlerBuffer.text;
Data = downloadHandlerBuffer.data;
break;
case DownloadHandlerScript downloadHandlerScript:
Body = downloadHandlerScript.text;
Data = downloadHandlerScript.data;
break;
default:
Body = webRequest.responseCode == 401 ? "Invalid Credentials" : webRequest.downloadHandler?.text;
Data = webRequest.downloadHandler?.data;
break;
}
}
else
{
Body = responseBody;
}

Code = webRequest.responseCode;
Headers = webRequest.GetResponseHeaders() ?? invalidHeaders;
Parameters = parameters;

if (!successful)
{
Error = $"{webRequest.error}\n{webRequest.downloadHandler?.error}";
}
}

/// <summary>
/// Constructor.
/// </summary>
Expand Down Expand Up @@ -158,29 +221,27 @@ public string ToString(string methodName)
{
if (Parameters.ServerSentEvents.Count > 0)
{
debugMessageObject["response"]["body"] = new JArray();
var array = new JArray();

foreach (var (type, value, data) in Parameters.ServerSentEvents)
foreach (var @event in Parameters.ServerSentEvents)
{
var eventObject = new JObject
{
[type] = value
[@event.Event.ToString().ToLower()] = @event.Value
};

if (!string.IsNullOrWhiteSpace(data))
if (@event.Data != null)
{
try
{
eventObject[nameof(data)] = JToken.Parse(data);
}
catch
{
eventObject[nameof(data)] = data;
}
eventObject["data"] = @event.Data;
}

((JArray)debugMessageObject["response"]["body"]).Add(eventObject);
array.Add(eventObject);
}

debugMessageObject["response"]["body"] = new JObject
{
["events"] = array
};
}
else
{
Expand Down
Loading