Search code examples
firebase-cloud-messagingelixirphoenix-frameworkpigeon

Is there a simple solution to my Phoenix problem rendering a response in JSON from a (Pigeon) Google FCM V1 request containing `{:token, my_token}`?


I'm sending the new FCM V1 API messages using Pigeon (v2.0.0) through Phoenix (1.7.12). Part of the new messaging includes the field {:token, my_token} in the outgoing message. When Phoenix gets the response it generates JSON from the response and the original notification, but there is no protocol for encoding a tuple.

Is there a simple solution to avoiding this problem?

Does anyone have any solution? Is anyone using Pigeon V2 with FCM V1 and Phoenix?

Sample error:

13:31:21.789 module=Bandit.Pipeline function=handle_error/5 line=233 [error] ** (Protocol.UndefinedError) protocol Jason.Encoder not implemented for {:token, "fj6NWX76QIyLrm8WseC22C:APA91bHRcPDl6eFRPQr0yrElZIp6Ry931kZAPaV_XotfgePuVXPAb3iblwTwUF81S7Id8q6qi_IWJo8dgTgPbAMSHEbn4fauxFC2h50ymOreVjgsLuk-tqKqLU6SeGEpp8o05XfrbrtG"} of type Tuple, Jason.Encoder protocol must always be explicitly implemented. This protocol is implemented for the following type(s): Any, Atom, BitString, Date, DateTime, Decimal, Ecto.Association.NotLoaded, Ecto.Schema.Metadata, Float, Integer, Jason.Fragment, Jason.OrderedObject, List, Map, NaiveDateTime, Time
    (jason 1.4.1) lib/jason.ex:213: Jason.encode_to_iodata!/2
    (phoenix 1.7.12) lib/phoenix/controller.ex:365: Phoenix.Controller.json/2
    (push_server 2.0.0) lib/push_server_web/api/controllers/fcm_controller.ex:1: PushServerWeb.API.FcmController.action/2
    (push_server 2.0.0) lib/push_server_web/api/controllers/fcm_controller.ex:1: PushServerWeb.API.FcmController.phoenix_controller_pipeline/2
    (phoenix 1.7.12) lib/phoenix/router.ex:484: Phoenix.Router.__call__/5
    (push_server 2.0.0) lib/push_server_web/endpoint.ex:1: PushServerWeb.Endpoint.plug_builder_call/2
    (push_server 2.0.0) deps/plug/lib/plug/debugger.ex:136: PushServerWeb.Endpoint."call (overridable 3)"/2

Solution

  • I've started to think that maybe my combination of apps is unusual. We have a centralized push server that accepts push notifications from multiple servers, so that the authentication with Apple only has to be managed and updated in a central, private server. We therefore send the pushes through a Phoenix channel to the push server, which may be unusual/unique.

    I've solved this by creating a second implementation of new for FCM that accepts a map with the token instead of a tuple.

    I've also found it useful to define the Jason.Encoder protocol for the FCM.Notification structure (excluding the struct field) so that Jason doesn't object to getting a full Notification structure to handle.