Support appsync subscription
As mentioned in issue #98, here are the changes necessary to support subscriptions with AppSync.
Hi,
Thanks for this! I really appreciate the contribution. Do you know if the "subscriptions as data" is a common pattern, or is it something unique to Appsync? My inclination is to have something like an implementation "flavour" called Appsync, which would take care of any aspects unique to Appsync. The impl parts were intended more as a way of exposing the underlying transport libraries to empower users if they needed to tweak something at the transport level, but I see Appsync as more of a protocol thing.
What do you think?
Cheers
Thank you for reviewing this, Oli.
I was trying to be agnostic in the naming of "subscription as data", but I'm not sure if it is a common pattern so the AppSync flavour makes sense. Noted on the usage of impl. I'll have a think about this and will put forward some changes this weekend.
Hey Oli
I had a little think on this and have added a way define a custom payload function. I think it simplifies things considerably and can let you shape the payload anyway you choose.
Everything to support AppSync is now doable from the init:
(defn- encode [obj]
(js/JSON.stringify (clj->js obj)))
(defn auth-session-callback [{:keys [token] :as data}]
(let [graphql-endpoint-url (.-aws_appsync_graphqlEndpoint aws-exports)
;; https://docs.aws.amazon.com/appsync/latest/devguide/real-time-websocket-client.html
graphql-endpoint-ws-url (-> graphql-endpoint-url
(string/replace #"^https:" "wss:")
(string/replace #"\.appsync-api\." ".appsync-realtime-api."))
appsync-host (extract-host graphql-endpoint-url)
header-b64 (str->base64 (clj->json-str {"Host" appsync-host, "Authorization" token}))
payload-b64 (str->base64 (clj->json-str {})) ;; documentation says an empty payload is required
graphql-endpoint-ws-url-with-auth (str graphql-endpoint-ws-url "?header=" header-b64 "&payload=" payload-b64)]
(rf/dispatch
[:re-graph.core/init
{:ws {:url graphql-endpoint-ws-url-with-auth
:supported-operations #{:subscribe}
:create-payload (fn create-payload-appsync [query]
{:data (encode query)
:extensions {"authorization" {"Authorization" token
"host" appsync-host}}})}
:http {:url graphql-endpoint-url
:supported-operations #{:query :mutation}
:impl {:with-credentials? false
:headers {"Authorization" token}}}}]))
(rf/dispatch [:app.auth.events/current-session data]))
I look forward to your feedback.
Chris.
Hey @oliyh any thoughts on this? I know you suggested flavours, but is this approach sufficient instead?
Hi,
Very grateful for this. Busy weekend but I will try to look at this next week.
Cheers