Reputation: 1541
I am using Postman to connect AWS Appsync subscription as per : https://docs.aws.amazon.com/appsync/latest/devguide/real-time-websocket-client.html
with the below config:
{ "payload": { "errors": [ { "message": "NoProtocolError", "errorCode": 400 } ] }, "type": "connection_error" }
Upvotes: 1
Views: 1961
Reputation: 1
Connection URL: Ensure that the WebSocket connection URL is correctly formatted. It should be in the following format:
wss://<your-appsync-api-id>.appsync-realtime-api.<region>.amazonaws.com/graphql
Headers: When connecting, you need to include the appropriate headers:
{
"host": "<your-appsync-api-id>.appsync-api.<region>.amazonaws.com",
"x-api-key": "<your-api-key>"
}
Base64 Encoding: Both the header and payload need to be base64 encoded and appended to the connection URL:
Both the header and payload need to be base64 encoded and assembled as follows:
connection_url = WSS_URL + '?header=' + <B64-ENCODED-HEADER> + '&payload=e30=
For the initial connection the payload is always the same (empty JSON object {}). The base 64 representation of {} is: =e30=.
Before connecting to the server, there is one more parameter to set. In the connection request we need to add a secondary protocol graphql-ws
this format for creating subscription worked for me, check it out:
import React, { useEffect, useState } from 'react';
const App = () => {
const [updates, setUpdates] = useState([]);
useEffect(() => {
const headers = {
"host": "<YOUR_APPSYNC_API_HOST>",
"x-api-key": "<YOUR_API_KEY>"
};
const encodedHeader = btoa(JSON.stringify(headers));
const payload = "e30="; // Base64 for {}
const wssUrl = "wss://<YOUR_APPSYNC_REALTIME_API_ENDPOINT>/graphql";
const connectionUrl = `${wssUrl}?header=${encodedHeader}&payload=${payload}`;
const ws = new WebSocket(connectionUrl, "graphql-ws");
ws.onopen = () => {
console.log("Connected!");
ws.send(JSON.stringify({ type: "connection_init", payload: {} }));
};
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
console.log("Received:", message);
if (message.type === 'connection_ack') {
const subscriptionMessage = {
id: "1", // Unique ID for the subscription
type: "start",
payload: {
data: JSON.stringify({
query: `subscription <YOUR_SUBSCRIPTION_NAME>($variable: <VARIABLE_TYPE!>) {
<YOUR_SUBSCRIPTION_NAME>(<variable: $variable>) {
<FIELDS_YOU_WANT>
}
}`,
variables: {
variable: "<YOUR_VARIABLE_VALUE>" // Replace with actual variable value
}
}),
extensions: {
authorization: {
"x-api-key": headers["x-api-key"],
"host": headers["host"]
}
}
}
};
ws.send(JSON.stringify(subscriptionMessage));
} else if (message.type === 'data' && message.id === '1') {
const update = message.payload.data.<YOUR_SUBSCRIPTION_NAME>;
console.log("Update Received:", update);
setUpdates(prevUpdates => [...prevUpdates, update]);
} else if (message.type === 'ka') {
console.log("Keep-alive received");
}
};
ws.onerror = (error) => {
console.error("Error:", error);
};
ws.onclose = (closeEvent) => {
console.log("Connection closed with code:", closeEvent.code, "and message:", closeEvent.reason);
};
return () => {
ws.close();
};
}, []);
return (
<div>
<h1>WebSocket Connection</h1>
<h2>Updates:</h2>
<ul>
{updates.map((update, index) => (
<li key={index}>
{/* Display your update fields here */}
<strong>Update:</strong> {JSON.stringify(update)} <br />
</li>
))}
</ul>
</div>
);
};
export default App;
Final Notes
Postman Limitations: Postman isn't suitable for testing WebSocket connections directly, as it's primarily an HTTP client.
Error Handling: Always handle connection errors and other events to maintain a robust application.
Upvotes: 0
Reputation: 111
if you get this error in unity use this way;
using System.Net.WebSockets;
var webSocket = new ClientWebSocket();
webSocket.Options.UseDefaultCredentials = false;
webSocket.Options.AddSubProtocol("graphql-ws");
Upvotes: 1
Reputation: 1541
The problem occurs due to a missing header:-
Sec-WebSocket-Protocol = graphql-ws
Upvotes: 8