未找到 API 网关 WSS Endpoint

0

【以下的问题经过翻译处理】 我使用AWS的.NET Lambda模板中的示例创建了一个WSS聊天应用程序。我的Web前端可以连接正常,并且它在Dynamo中创建了一条记录,但是当我尝试广播消息给所有连接时,我收到了以下错误:

`Name or service not known (execute-api.ap-southeast-2.amazonaws.com:443) `

我正在使用以下代码进行设置:

var protocol = "https";
  //var protocol = "wss";
  
  var domainName = request.RequestContext.DomainName;
  //var domainName = "ID HERE.execute-api.ap-southeast-2.amazonaws.com";
  
  var stage = request.RequestContext.Stage;
  // var stage = "";
  //var stage = "test";
  //var stage = "test/@connections";
  
  var endpoint = $"{protocol}://{domainName}/{stage}";

并记录如下内容:

API Gateway management endpoint: https://ID HERE.execute-api.ap-southeast-2.amazonaws.com/test

我尝试了所有的组合,甚至使用了自定义域名。我在这个问题上卡了一段时间了,准备放弃了。有没有人有什么想法??

更新:以下是发送消息的代码 - 它只是示例的更新版本。从启动代码中:

public Functions()
  {
    DDBClient = new AmazonDynamoDBClient();

    // Grab the name of the DynamoDB from the environment variable setup in the CloudFormation template serverless.template
    if (Environment.GetEnvironmentVariable(TABLE_NAME_ENV) == null)
    {
      throw new ArgumentException($"Missing required environment variable {TABLE_NAME_ENV}");
    }

    ConnectionMappingTable = Environment.GetEnvironmentVariable(TABLE_NAME_ENV) ?? "";

    this.ApiGatewayManagementApiClientFactory = (Func<string, AmazonApiGatewayManagementApiClient>)((endpoint) =>
    {
      return new AmazonApiGatewayManagementApiClient(new AmazonApiGatewayManagementApiConfig
      {
        ServiceURL = endpoint,
        
        RegionEndpoint = RegionEndpoint.APSoutheast2, // without this I get Credential errors
        LogResponse = true,  // dont see anything extra with these
        LogMetrics = true,
        DisableLogging = false
      });
    });
  }

然后SendMessageFunction:

try
    {
      // Construct the API Gateway endpoint that incoming message will be broadcasted to.
      var protocol = "https";
      //var protocol = "wss";
      
      var domainName = request.RequestContext.DomainName;
      //var domainName = "?????.execute-api.ap-southeast-2.amazonaws.com";
      
      var stage = request.RequestContext.Stage;
      // var stage = "";
      //var stage = "test";
      //var stage = "test/@connections";
      
      var endpoint = $"{protocol}://{domainName}/{stage}";
      
      context.Logger.LogInformation($"API Gateway management endpoint: {endpoint}");
      
      JObject message = JObject.Parse(request.Body);
      context.Logger.LogInformation(request.Body);


      if (!GetRecipient(message, context, out WSMessageRecipient? recipient))
      {
        context.Logger.LogError($"Invalid or empty WSMessageRecipient");
        return new APIGatewayProxyResponse
        {
          StatusCode = (int)HttpStatusCode.BadRequest, Body = "Nothing to do or invalid request"
        };
      }
      
      if (!GetData(message, context, out string? data))
      {
        context.Logger.LogError($"Invalid or empty WSSendMessage");
        return new APIGatewayProxyResponse
        {
          StatusCode = (int)HttpStatusCode.BadRequest, Body = "Nothing to do or invalid request"
        };
      }

      var stream = new MemoryStream(UTF8Encoding.UTF8.GetBytes(data!));
      
      if (stream.Length == 0)
      {
        context.Logger.LogError($"Empty Stream");
        return new APIGatewayProxyResponse
        {
          StatusCode = (int)HttpStatusCode.BadRequest, Body = "Empty data stream"
        };
      }

      // List all of the current connections. In a more advanced use case the table could be used to grab a group of connection ids for a chat group.
      ScanResponse scanResponse = await GetConnectionItems(recipient);

      // Construct the IAmazonApiGatewayManagementApi which will be used to send the message to.
      var apiClient = ApiGatewayManagementApiClientFactory(endpoint);

      context.Logger.LogInformation($"Table scan of {ConnectionMappingTable} got {scanResponse.Items.Count} records.");
      
      // Loop through all of the connections and broadcast the message out to the connections.
      var count = 0;
      foreach (var item in scanResponse.Items)
      {
        var connectionId = item[ConnectionIdField].S;

        context.Logger.LogInformation($"Posting to connection {count}: {connectionId}");

        var postConnectionRequest = new PostToConnectionRequest
        {
          ConnectionId = connectionId, Data = stream
        };

        try
        {
          stream.Position = 0;
          await apiClient.PostToConnectionAsync(postConnectionRequest);
          context.Logger.LogInformation($"Posted to connection {count}: {connectionId}");
          count++;
        }
        catch (AmazonServiceException e)
        {
          // API Gateway returns a status of 410 GONE then the connection is no
          // longer available. If this happens, delete the identifier
          // from our DynamoDB table.
          if (e.StatusCode == HttpStatusCode.Gone)
          {
            context.Logger.LogInformation($"Deleting gone connection: {connectionId}");
            var ddbDeleteRequest = new DeleteItemRequest
            {
              TableName = ConnectionMappingTable,
              Key = new Dictionary<string, AttributeValue>
              {
                {ConnectionIdField, new AttributeValue {S = connectionId}}
              }
            };

            await DDBClient.DeleteItemAsync(ddbDeleteRequest);
          }
          else
          {
            context.Logger.LogError(
              $"Error posting message to {connectionId}: {e.Message}");
            context.Logger.LogInformation(e.StackTrace);
          }
        }
        catch (Exception ex)
        {
          context.Logger.LogError($"Bugger, something fecked up: {ex.Message}");
          context.Logger.LogInformation(ex.StackTrace);
        }
      }

      return new APIGatewayProxyResponse
      {
        StatusCode = (int)HttpStatusCode.OK, Body = "Data sent to " + count + " connection" + (count == 1 ? "" : "s")
      };
    }
    catch (Exception e)
    {
      context.Logger.LogInformation("Error Sending Message: " + e.Message);
      context.Logger.LogInformation(e.StackTrace);
      return new APIGatewayProxyResponse
      {
        StatusCode = (int)HttpStatusCode.InternalServerError, Body = $"Failed to send message: {e.Message}"
      };
    }
profile picture
专家
已提问 5 个月前55 查看次数
1 回答
0

【以下的回答经过翻译处理】 通过在创建 Api 客户端时添加凭证,我解决了这个问题。不要问我为什么 - 我本以为它应该从角色中获取这些:

this.ApiGatewayManagementApiClientFactory = (Func<string, AmazonApiGatewayManagementApiClient>)((endpoint) =>
    {
      AWSCredentials awsCredentials = new EnvironmentVariablesAWSCredentials();
      return new AmazonApiGatewayManagementApiClient(awsCredentials, new AmazonApiGatewayManagementApiConfig
      {
        ServiceURL = endpoint
      });
    });
profile picture
专家
已回答 5 个月前

您未登录。 登录 发布回答。

一个好的回答可以清楚地解答问题和提供建设性反馈,并能促进提问者的职业发展。

回答问题的准则