How to send a message to specific connectionId to aws api gateway websockets?

Viewed 2353

I am using this code to establish a new connection on user device.

var socket = new WebSocket("wss://cdsbxtx2xi.execute-api.us-east-2.amazonaws.com/test"); 
socket.onmessage = function (event) {
  json = JSON.parse(event.data);
  connectionId = json.connectionId;
  document.cookie = "connection_id="+connectionId;
  console.info(json);
}

Suppose from this request I get connectionId CLO5bFP1CYcFSbw=

Another user from another device also established a new connection with connectionId Cs42Fs5s5yuSbc=. Now how can I send a message from user 2 device to user 1?

I already tried this. I don't know this is right way or not but still, i am open for any suggestion.

use Aws\Signature\SignatureV4;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Request;
use Aws\Credentials\Credentials;
$client =  new GuzzleHttp\Client();
$credentials = new Credentials("XXXXXXXXXX","XXXXXXXX");
$url = "https://cdsbxtx2xi.execute-api.us-east-2.amazonaws.com/test/@connections/CLO5bFP1CYcFSbw=";
$region = 'us-east-2'; 
$msg['action'] = 'sendmessage';
$msg['data'] = 'hello world';
$msg = json_encode($msg);
$request = new Request('POST', $url, '["json"=>$msg]');

$s4 = new SignatureV4("execute-api", $region);
$signedrequest = $s4->signRequest($request, $credentials); 
$response = $client->send($signedrequest);
echo $response->getBody();

This code keeps on loading and finally throws gateway timeout error.

I expect that user 2 should be able to send message to any specific connectionId over wss or https.

I tried https by signing this request but signing doesn't works. I am getting an error with the signing part

2 Answers

After struggling with this problem for the last 3 days finally I found the solution. None of the previously mentioned solutions on StackOverflow was working for me.

This is the correct solution. I hope this will be helpful to someone.

use Aws\Signature\SignatureV4;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Request;
use Aws\Credentials\Credentials;
$client =  new GuzzleHttp\Client();
$credentials = new Credentials(accessKeyId, secretAccessKey);
$url = "https://xsdsdsd.execute-api.us-east-2.amazonaws.com/test/@connections/CNtBveH2iYcCKrA="; 
// CNtBveH2iYcCKrA= is connectionid
$region = 'us-east-2'; 
$msg['action'] = 'sendmessage';
$msg['data'] = 'hello world'; 
$msg = json_encode($msg); 
$headers = array('Content-Type => application/x-www-form-urlencoded');
$request = new GuzzleHttp\Psr7\Request('POST', $url, ['Content-Type' => 'application/json'], $msg); 
$signer = new Aws\Signature\SignatureV4('execute-api', $region); 
$request = $signer->signRequest($request, $credentials);
$headers = array('Content-Type => application/x-www-form-urlencoded');
$client = new \GuzzleHttp\Client([ 'headers' => $headers]);
$response = $client->send($request);
$result = $response->getBody();

Hey you can use the Connection URL to send message also.

Connection url : https://{api-id}.execute-api.us-east-1.amazonaws.com/{stage}/@connections

To find go to : Aws console > Api gateway > api > your_api > dashboard their you will find your connection url.

Use php cURL method because its easy and fast as compare to GuzzleHttp

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => 'https://{api-id}.execute-api.us-east-1.amazonaws.com/{stage}/@connections/{YOUR_CONNECTION_ID_OF_USER}',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => '',
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_POSTFIELDS =>'{"message" : "Hello world"}',
  CURLOPT_HTTPHEADER => array(
    'Content-Type: application/json'
  ),
));

$response = curl_exec($curl);

curl_close($curl);
echo $response;
Related