Ошибка неизвестного веб-сокета AWS API Gateway

#amazon-web-services #websocket #aws-api-gateway

#amazon-веб-сервисы #веб-сокет #aws-api-gateway

Вопрос:

Мы столкнулись с ошибкой при выполнении postToConnection() вызова SDK в качестве обещания, полная информация об ошибке приведена ниже. Другие вызовы в той же функции с другим идентификатором соединения выполняются успешно. Ожидаемые 410 ошибок подключения происходят правильно и в миллисекундах и обрабатываются корректно.

Для возврата этой ошибки требуется от 40 секунд до более минуты, что приводит к тому, что она всегда вызывает ошибки «тайм-аут запроса конечной точки» в API веб-сокетов, поскольку максимальный тайм-аут запроса составляет 30 секунд. Кто-нибудь сталкивался с этой проблемой раньше и / или какое-либо реализованное решение? Любые идеи по устранению проблемы будут высоко оценены, спасибо.

Неизвестная ошибка: сетевая ошибка связи с конечной точкой в Object.extractError (/opt/nodejs/node_modules/aws-sdk/lib/protocol/json.js:51:27)

Ответ №1:

вы пытаетесь использовать postToConnection внутри обработчика подключения? Соединение с веб-сокетом создается только после того, как обработчик соединения вернул код состояния 200. Вы не должны использовать postToConnection внутри обработчика подключения.

Комментарии:

1. Спасибо за приведенное выше предложение, теперь оно работает так, как ожидалось!

2. как отправить сообщение клиенту, который только что подключился? 🙂

3. @patrick Похоже, что клиент должен отправить первоначальный запрос на отдельный маршрут, чтобы получить первое сообщение.

Ответ №2:

Чтобы избежать головной боли 410 при использовании веб-сокетов без сервера, не забывайте перехватывать исключения:

 export const ApiGatewayConnector = (event) => {

  const endpoint = process.env.IS_OFFLINE
            ? 'http://localhost:3001'
            : `${event.requestContext.domainName}/${event.requestContext.stage}`
            const apiVersion = '2018-11-29'
            return new AWS.ApiGatewayManagementApi({ apiVersion, endpoint })
}
  

….

 if (event.requestContext.stage == 'local') {
              await ApiGatewayConnector(event)
              .postToConnection({ ConnectionId, Data })
              .promise()
              .catch(_ => removeId(ConnectionId));<----- N.B. Remove disconnected IDs
            } else {
              await ws.send(Data, ConnectionId)
            }
}
        
  

Ответ №3:

Эта ошибка выдается при вызове .postToConnection в ответ на событие $connect . Вы можете вызвать .postConnection без ошибок в ответ на событие $default .

 // index.js
// the handler is defined as: index.handler

const AWS = require("aws-sdk");

exports.handler = function (event, context, callback) {

    console.log('event.requestContext.eventType', event amp;amp; event.requestContext amp;amp; event.requestContext.eventType)

    if (event.requestContext.eventType === "CONNECT") {

        console.log('$connect event')

        // calling apigwManagementApi.postToConnection will throw an exception

        callback(null, {
            statusCode: 200,
            body: "Connected"
        });

    } else if (event.requestContext.eventType === "DISCONNECT") {

        console.log('$disconnect event')

        // calling apigwManagementApi.postToConnection is pointless since the client has disconneted

        callback(null, {
            statusCode: 200,
            body: "Disconnected"
        });
    } else {

        console.log('$default event')

        const ConnectionId = event.requestContext.connectionId
        const bodyString = event.body
        const Data = bodyString

        const apigwManagementApi = new AWS.ApiGatewayManagementApi({
            apiVersion: "2018-11-29",
            endpoint: event.requestContext.domainName   "/"   event.requestContext.stage
        });

        apigwManagementApi
        .postToConnection({ ConnectionId, Data })
        .promise().then(() => {

            callback(null, {
                statusCode: 200,
                body: "Disconnected"
            });

        })

    }

};
  

Ответ №4:

Не совсем уверен, соответствует ли это наилучшей практике, но я смог использовать postToConnection внутри connect обработчика (вызвав callback перед инициализацией postToConnection )

 exports.handler = async (event, context, callback) => {
  try {
    const {
      body = '{}',
      requestContext: { apiId, connectionId, routeKey, stage },
    } = event;

    const apigwManagementApi = new ApiGatewayManagementApi({
      endpoint: 'local' === stage ? `http://localhost:4002` : `https://${apiId}.execute-api.${process.env.AWS_REGION}.amazonaws.com/${stage}`,
    });

    switch(routeKey) {
      case '$connect':

        // call callback to create connection
        callback(null, {
          statusCode: 200,
          body: "Connected"
        });

        await apigwManagementApi.postToConnection({
          ConnectionId: connectionId,
          Data: JSON.stringify({
            action: 'test-message'
          }),
        }).promise();

        break;
      case '$disconnect':
        console.log('DISCONNECT');
        break;
      default:
        console.log('DEFAULT');
        break;
    }

    return { statusCode: 200 };
  } catch (error) {
    console.log('Got error', error)
  }
};
  

Комментарии:

1. Я пробовал это, но это просто не сработало для меня