如何在 Swift 中调用 AWS Lambda 函数

How to invoke an AWS Lambda function in Swift

我在 Swift 中找不到有关如何调用 Lambda 函数 的任何文档或示例,但我'我尝试使用 Objective-C 从文档中进行推断,但我仍然遇到错误:

"Error in myFunction: ValidationException: Supplied AttributeValue is empty, must contain exactly one of the supported datatypes"

当我从 swift 调用 lambda 函数时,我似乎没有将参数正确传递给函数,因为脚本试图写入 DynamoDB,但其中一个参数为空(此 lambda当我在 javascript/node).

中调用它时脚本工作
    let lambda = AWSLambda.defaultLambda()
    let request = AWSLambdaInvocationRequest()
    var context = [String: String]()
    let jsonString = "{\"email\":\"example@example.com\",\"name\":\"example\"}"
    let jsonData = jsonString.dataUsingEncoding(NSUTF8StringEncoding)
    request.clientContext = jsonData?.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.Encoding64CharacterLineLength)
    request.functionName = "myFunction"
    lambda.invoke(request).continueWithBlock( {
        (currentTask: AWSTask!) -> AWSTask in
        if (currentTask.error != nil) {
            // failed to execute.
            print("Error executing: ", currentTask.error)
            task.setError(currentTask.error)
        } else {
            print("token: ", currentTask.result)
            task.setResult(currentTask.result)
    }
        return currentTask
    })

您需要将 payload 参数设置为包含您要传递的数据的映射。

    let invocationRequest = AWSLambdaInvokerInvocationRequest()
    invocationRequest.functionName = "myFunction"
    invocationRequest.invocationType = AWSLambdaInvocationType.RequestResponse
    invocationRequest.payload = ["email" : "example@example.com", "name" : "example"]

    let lambdaInvoker = AWSLambdaInvoker.defaultLambdaInvoker()
    let task = lambdaInvoker.invoke(invocationRequest).continueWithSuccessBlock() { (task) -> AWSTask! in
        print("response: ", task.result)
    }

Ryan Fitzgerald 的回答给了我多个编译时错误,但我在这个版本上取得了成功:

首先,我有一个带有访问凭据的初始化函数。请注意,这不是推荐的用于生产代码的安全访问方法,但可以用于测试和其他目的。它还假定您有一个 Constants.swift 文件,您在其中定义了列出的常量:

func initializeLambda() {

        let credentialsProvider = AWSStaticCredentialsProvider.init(accessKey:Constants.AWS_ACCESS_KEY, secretKey: Constants.AWS_SECRET_KEY)
        let defaultServiceConfiguration = AWSServiceConfiguration(region: Constants.AWS_REGION, credentialsProvider: credentialsProvider)
        AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = defaultServiceConfiguration
    }

对于其余部分,我们可以提供与之前版本相似的版本。我删除了 'let task' 因为 'task' 在他的例子中没有使用。此外,我已经包含了您可能在调用任务中执行的一些 JSON 解析的逻辑概要。最后,我更改为 continueWithBlock()。如果您使用 continueWithSuccessBlock(),当 Amazon Lambda 达到超时 window 或请求出现其他问题时,您将不会进入此块,通常您确实希望在此处处理这些情况。

    self.initializeLambda() //Call our previously written initialization function
    let invocationRequest = AWSLambdaInvokerInvocationRequest()
    invocationRequest.functionName = "functionName"
    invocationRequest.invocationType = AWSLambdaInvocationType.RequestResponse
    invocationRequest.payload = ["key1" : "value1", "key2" : "value2"]
    let lambdaInvoker = AWSLambdaInvoker.defaultLambdaInvoker()
    lambdaInvoker.invoke(invocationRequest).continueWithBlock() { (task: AWSTask) -> AWSTask in
         print("response: ", task.result)
         //In here you'll likely be parsing a JSON payload
         if let payload: AnyObject = task.result?.payload {
              if let error: AnyObject = payload.objectForKey("error") {
                   //If there is an error key in the JSON dictionary...
              } else {
                   //If the JSON dictionary has no error key...
              }
         return task; 
         }    
    }

在 Xcode 7.3 中的 Swift 2.2 上测试和验证功能正常。

Ryan 两位的回答都很棒而且很有用,我只想补充一些额外的想法。

在大多数情况下,在调用 Lambda 之前,您可能需要进行身份验证,因此您遇到的错误不一定是因为您的 Lambda 调用,而是由于身份验证失败。但是,对于 AWS,有多种不同的身份验证方法,这将根据您拥有的凭证而改变。

Ryan Davis 向您展示了后端团队设置 AWS 访问密钥和 AWS 秘密密钥的一种方法。

就我而言,我必须使用 AWS Cognito Identity Pools 进行身份验证,并且还有用户池身份验证,因此您需要弄清楚您的团队为您提供了哪些凭据并阅读相应的身份验证文档。

由于我需要使用 AWS Cognito Identity Pools,我所拥有的只是区域和身份池 ID,因此在 Swift 5 AWS Cognito Identity 身份验证中池

let credentialsProvider = AWSCognitoCredentialsProvider(regionType: Constants.AWS_REGION,
                          identityPoolId: Constants.AWS_REGION.AWS_IDENTITY_POOL_ID)

let serviceConfiguration = AWSServiceConfiguration(region: Constants.AWS_REGION,
                           credentialsProvider: credentialsProvider)

AWSServiceManager.default().defaultServiceConfiguration = serviceConfiguration

然后 Lambda 调用或多或少保持不变,只是稍微更新了 Swift 5 语法:

if let invocationRequest = AWSLambdaInvokerInvocationRequest() {
      invocationRequest.functionName = "function_name"
      invocationRequest.invocationType = AWSLambdaInvocationType.requestResponse
      invocationRequest.payload = ["key_1": "value_1"]
      let lambdaInvoker = AWSLambdaInvoker.default()
      lambdaInvoker.invoke(invocationRequest) { (awsLambdaInvokerInvocationResponse, error) in
        
        guard let payload = awsLambdaInvokerInvocationResponse?.payload as? [String: String] else {
          
          // Handle error here
          return
        }
        
        if let userId = payload["message"] {
          print("USR Id: \(userId)")
        }
      }
    }

您需要根据 Lambda 返回给您的负载结构调整您的处理方式,在我的例子中是:

{
  "message": "user-id-8868-8475-8757"
}

最后,记得为您的用例导入所需的库,对于我上面的案例,我需要:

import AWSCore
import AWSLambda