How to invoke an AWS Lambda function in Swift

I can't find any documentation or examples on how to invoke a Lambda function in Swift but I've tried to extrapolate from the documentation using Objective-C and I'm still getting errors:

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

It appears that I'm not passing in the parameters to the function correctly when I invoke the lambda function from swift because the script tries to write to DynamoDB but one of the parameters is empty (this lambda script works when I invoke it in 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
    })

Answers


You need to set the payload parameter to a map containing the data you want to pass.

    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's answer gives me multiple compile-time errors, but I've had success with this version:

First, I have an initialization function with access credentials. Note that this is not the recommended secure access method for production code, but it is fine for testing and other purposes. It also assumes you have a Constants.swift file where you define the listed constants:

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
    }

For the remainder we can provide a version similar to the previous version. I removed the 'let task' because 'task' is not used in his example. Additionally, I've included the logical outline of some JSON parsing that you are likely to be doing inside the invoke task. Finally, I've changed to a continueWithBlock(). If you use a continueWithSuccessBlock() you will not enter this block when Amazon Lambda reaches its timeout window or if something else goes wrong with the request and typically you do want these situations to be handled here.

    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; 
         }    
    }

Tested and verified as functional on Swift 2.2 in Xcode 7.3.


Need Your Help

how to call JS function when radiobutton list selected index changed dynamically

c# javascript jquery asp.net radiobuttonlist

i have few radio button lists and i need to change the selected index of few lists depending upon other radio button selection so for that i wrote something like below and i am calling some JS func...