6

I am trying to send a message to a client connected through the socket by using **AWS.ApiGatewayManagementApi() postToConnection** method. It's working fine in local, but not working in ec2. The only difference is VPC. Is that would be a problem?

var AWS = require('aws-sdk');

var awsGW = new AWS.ApiGatewayManagementApi({
    endpoint: "https://endpoint",
    accessKeyId: "accessKeyId",
    secretAccessKey: "secretAccessKey",
    region: "region"
});

awsGW.postToConnection({
    ConnectionId: 'ConnectionId',
    Data: '{"key1":"msg1","key2":"msg2"}'
}, (err, success) => {
    if (err) {
        console.log('Socket error', err);
    } else {
    }
});

ERROR:

{ ForbiddenException: Forbidden
    at Object.extractError (/home/ubuntu/git/backend/node_modules/aws-sdk/lib/protocol/json.js:51:27)
    at Request.extractError (/home/ubuntu/git/backend/node_modules/aws-sdk/lib/protocol/rest_json.js:55:8)
    at Request.callListeners (/home/ubuntu/git/backend/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
    at Request.emit (/home/ubuntu/git/backend/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
    at Request.emit (/home/ubuntu/git/backend/node_modules/aws-sdk/lib/request.js:683:14)
    at Request.transition (/home/ubuntu/git/backend/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (/home/ubuntu/git/backend/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at /home/ubuntu/git/backend/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (/home/ubuntu/git/backend/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> (/home/ubuntu/git/backend/node_modules/aws-sdk/lib/request.js:685:12)
  message: 'Forbidden',
  code: 'ForbiddenException',
  time: 2019-06-10T07:40:02.214Z,
  requestId: 'f4caef03-8b52-11e9-9cc3-91bfe40b8eb0',
  statusCode: 403,
  retryable: false,
  retryDelay: 37.0834357877396 } 
ravjduker
  • 61
  • 1
  • 1
  • 5

5 Answers5

6

I ran into a similar problem and it was because I was using the wrong endpoint. I was generating it from the event object but on a normal API request, so I was getting an endpoint for a different service (the normal API, and not the websocket).

If your websockets service is deployed to a URL like wss://abcd then your endpoint should be https://abcd.

Malvineous
  • 25,144
  • 16
  • 116
  • 151
  • 2
    Exactly the problem I was having. Using `https` rather than `wss` as the URL is super un-intuitive when you read the documentation (golang: https://docs.aws.amazon.com/sdk-for-go/api/service/apigatewaymanagementapi/) and when you consider that the API Gateway console itself says the WebSocket URL is `wss://...` – John Dibling Feb 07 '20 at 12:06
2

In my case, there was just an error/undefined value in the endpoint I was using to instantiate the

new AWS.ApiGatewayManagementApi({
    endpoint,
    region,
})

Note: endpoint can provided in 2 forms:

  • custom domain name+ base path mapping, for example: wss.my-super-website-with-websocket.com/v1 (where v1 is the configured base path mapping)
  • default aws-style url like https://********.execute-api.us-east-5.amazonaws.com/prod where prod is the stage configured in API Gateway.

More importantly, for your debugging purposes, if you get desperate, I found out that you can quite easily log the request made by aws-sdk to make sure you are making the correct request (using the aws cli to try the request is also a good idea): node_modules\aws-sdk\lib\event_listeners.js

function executeSend() {
  var http = AWS.HttpClient.getInstance();
  var httpOptions = resp.request.service.config.httpOptions || {};
  try {
    console.log('event listener execute send', resp.request.httpRequest); // only this line is added
    ...
arseneoaa
  • 286
  • 5
  • 5
0

403 sounds like you need to update the policies for the IAM role calling your postToConnection

In my case I had explicit missing rules, hence I had to attach authorizations for ExecuteAPI

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "execute-api:*",
            "Resource": "arn:aws:execute-api:eu-west-1:###########:*/*/*/*"
        }
    ]
}
Chris
  • 1,016
  • 1
  • 14
  • 18
0

I faced the same issue - I have Lambda inside VPC in private subnet and there was VPC endpoint for API Gateway but it always returned 403 Forbidden.

It's weird, but after replacing VPC endpoint with NAT Gateway issue has gone.

rkm
  • 2,971
  • 22
  • 29
0

This is what worked for me Source : https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-apigatewaymanagementapi/classes/posttoconnectioncommand.html

import { PostToConnectionCommand } from "@aws-sdk/client-apigatewaymanagementapi";

const input = {
   Data: response,
   ConnectionId: connectId,
};
const command = new PostToConnectionCommand(input);
await client.send(command);
lewisemann
  • 19
  • 3