Skip to content

Commit

Permalink
Support using JsonSerializerOptions (no trimming) with custom data in…
Browse files Browse the repository at this point in the history
… APNs
  • Loading branch information
mburumaxwell committed Oct 2, 2023
1 parent 8a997e7 commit 3232c1d
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 12 deletions.
59 changes: 47 additions & 12 deletions src/Tingle.Extensions.PushNotifications/Apple/ApnsNotifier.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System.Diagnostics.CodeAnalysis;
using System.Net.Http.Headers;
using System.Text.Json.Serialization.Metadata;
using Tingle.Extensions.Http;
Expand All @@ -22,24 +23,59 @@ public class ApnsNotifier : AbstractHttpApiClient<ApnsNotifierOptions>
public ApnsNotifier(HttpClient httpClient, IOptionsSnapshot<ApnsNotifierOptions> optionsAccessor) : base(httpClient, optionsAccessor) { }

/// <summary>Send a push notification via Apple Push Notification Service (APNS).</summary>
/// <param name="header">The header for the notification</param>
/// <param name="data">The data</param>
/// <param name="header">The header for the notification.</param>
/// <param name="data">The data.</param>
/// <param name="cancellationToken">The token to cancel the request.</param>
public virtual Task<ResourceResponse<ApnsMessageResponse, ApnsResponseError>> SendAsync(ApnsMessageHeader header,
ApnsMessageData data,
CancellationToken cancellationToken = default)
=> SendAsync(header, data, SC.Default.ApnsMessageData, cancellationToken);

/// <summary>Send a push notification with custom data via Apple Push Notification Service (APNS).</summary>
/// <param name="header">The header for the notification</param>
/// <param name="data">The data</param>
/// <param name="header">The header for the notification.</param>
/// <param name="data">The customized data.</param>
/// <param name="cancellationToken">The token to cancel the request.</param>
[RequiresUnreferencedCode(MessageStrings.SerializationUnreferencedCodeMessage)]
[RequiresDynamicCode(MessageStrings.SerializationRequiresDynamicCodeMessage)]
public virtual Task<ResourceResponse<ApnsMessageResponse, ApnsResponseError>> SendAsync<TData>(ApnsMessageHeader header,
TData data,
CancellationToken cancellationToken = default)
where TData : ApnsMessageData
{
// ensure we have the aps node
if (data == null) throw new ArgumentNullException(nameof(data));
if (data.Aps == null) throw new ArgumentException($"{nameof(data.Aps)} cannot be null", nameof(data));

var content = MakeJsonContent(data);
return SendAsync(header, content, cancellationToken);
}

/// <summary>Send a push notification with custom data via Apple Push Notification Service (APNS).</summary>
/// <param name="header">The header for the notification.</param>
/// <param name="data">The customized data.</param>
/// <param name="jsonTypeInfo">Metadata about the <typeparamref name="TData"/> to convert.</param>
/// <param name="cancellationToken">The token to cancel the request.</param>
public virtual async Task<ResourceResponse<ApnsMessageResponse, ApnsResponseError>> SendAsync<TData>(ApnsMessageHeader header,
TData data,
JsonTypeInfo<TData> jsonTypeInfo,
CancellationToken cancellationToken = default)
public virtual Task<ResourceResponse<ApnsMessageResponse, ApnsResponseError>> SendAsync<TData>(ApnsMessageHeader header,
TData data,
JsonTypeInfo<TData> jsonTypeInfo,
CancellationToken cancellationToken = default)
where TData : ApnsMessageData
{
// ensure we have the aps node
if (data == null) throw new ArgumentNullException(nameof(data));
if (data.Aps == null) throw new ArgumentException($"{nameof(data.Aps)} cannot be null", nameof(data));

var content = MakeJsonContent(data, jsonTypeInfo);
return SendAsync(header, content, cancellationToken);
}

/// <summary>Send a push notification via Apple Push Notification Service (APNS).</summary>
/// <param name="header">The header for the notification.</param>
/// <param name="content">The <see cref="HttpContent"/> to use in the body.</param>
/// <param name="cancellationToken">The token to cancel the request.</param>
protected virtual async Task<ResourceResponse<ApnsMessageResponse, ApnsResponseError>> SendAsync(ApnsMessageHeader header,
HttpContent content,
CancellationToken cancellationToken = default)
{
// infer the endpoint from the provided environment
var endpoint = new Uri(header.Environment == ApnsEnvironment.Production ? ProductionBaseUrl : DevelopmentBaseUrl);
Expand All @@ -50,16 +86,15 @@ public virtual async Task<ResourceResponse<ApnsMessageResponse, ApnsResponseErro
throw new ArgumentException($"{nameof(header.DeviceToken)} cannot be null", nameof(header));
}

// ensure we have the aps node
if (data == null) throw new ArgumentNullException(nameof(data));
if (data.Aps == null) throw new ArgumentException($"{nameof(data.Aps)} cannot be null", nameof(data));
// ensure we have the content
if (content == null) throw new ArgumentNullException(nameof(content));

var path = $"/3/device/{header.DeviceToken}";
var uri = new Uri(endpoint, path);
var request = new HttpRequestMessage(HttpMethod.Post, uri)
{
Version = new Version(2, 0), // APNs requires HTTP/2
Content = MakeJsonContent(data, jsonTypeInfo),
Content = content,
};

// specify the header for content we can accept
Expand Down
7 changes: 7 additions & 0 deletions src/Tingle.Extensions.PushNotifications/MessageStrings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Tingle.Extensions.PushNotifications;

internal class MessageStrings
{
internal const string SerializationUnreferencedCodeMessage = "JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.";
internal const string SerializationRequiresDynamicCodeMessage = "JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation. Use System.Text.Json source generation for native AOT applications.";
}

0 comments on commit 3232c1d

Please sign in to comment.