REST API
Overview
The Amplify CLI deploys REST APIs and handlers using Amazon API Gateway and AWS Lambda.
The API category will perform SDK code generation which, when used with the AWSMobileClient
can be used for creating signed requests for Amazon API Gateway when the service Authorization is set to AWS_IAM
or when using a Cognito User Pools Authorizer.
See the authentication section for more details for using the AWSMobileClient
in your application.
Set Up Your Backend
In a terminal window, navigate to your project folder (the folder that contains your app .Xcodeproj
file), and add the SDK to your app.
cd YOUR_PROJECT_FOLDERamplify add api
When prompted select the following options:
> REST> Create a new Lambda function> Serverless express function> Restrict API access? Yes> Who should have access? Authenticated and Guest users
When configuration of your API is complete, the CLI displays a message confirming that you have configured local CLI metadata for this category. You can confirm this by running amplify status
. Finally deploy your changes to the cloud:
amplify push
Once the deployment completes a folder called generated-src
will be added in the folder directory. This is the client SDK that you will add to your project in the next section.
Connect to Your Backend
Add AWSAPIGateway
to your Podfile:
target :'YOUR-APP-NAME' do use_frameworks!
# For API pod 'AWSAPIGateway' # other podsend
Run pod install --repo-update
and then add the generated-src
folder and awsconfiguration.json
file to your project (File->Add Files to ..->Add) and then build your project, ensuring there are no issues.
Next, set the bridging header for Swift in your project settings. Double-click your project name in the Xcode Project Navigator, choose the Build Settings tab and search for Objective-C Bridging Header
. Enter generated-src/Bridging_Header.h
This is needed because the AWS generated code has some Objective-C code which requires bridging to be used for Swift. If you already have a bridging header in your app, you can just append an extra line to it: #import "AWSApiGatewayBridge.h"
instead of above step.
The generated files determine the name of your client when making API calls. In the generated-src
folder, files ending with name *Client.swift
are the names of your client (without .swift extension). The path of the client code file is:
./generated-src/YOUR_API_RESOURCE_NAME+YOUR_APP_NAME+Client.swift
So, for an app named useamplify
with an API resource named xyz123
, the path of the code file might be ./generated-src/xyz123useamplifyabcdClient.swift. The API client name would be xyz123useamplifyabcdClient
and you would use it in your code with xyz123useamplifyabcdClient.registerClient()
and xyz123useamplifyabcdClient.client()
.
Find the resource name of your API by running amplify status
. Copy your API client name to use when invoking the API in the following sections.
IAM authorization
To invoke an API Gateway endpoint from your application, import AWSAPIGateway
and use the generated client class, model, and resource paths as in the below example with YOUR_API_CLIENT_NAME
replaced from the previous section. For AWS IAM authorization use the AWSMobileClient
as outlined in the authentication section.
import AWSAPIGatewayimport AWSMobileClient
// ViewController or application context . . .
func doInvokeAPI() { // change the method name, or path or the query string parameters here as desired let httpMethodName = "POST" // change to any valid path you configured in the API let URLString = "/items" let queryStringParameters = ["key1":"{value1}"] let headerParameters = [ "Content-Type": "application/json", "Accept": "application/json" ]
let httpBody = "{ \n " + "\"key1\":\"value1\", \n " + "\"key2\":\"value2\", \n " + "\"key3\":\"value3\"\n}"
// Construct the request object let apiRequest = AWSAPIGatewayRequest(httpMethod: httpMethodName, urlString: URLString, queryParameters: queryStringParameters, headerParameters: headerParameters, httpBody: httpBody)
// Create a service configuration let serviceConfiguration = AWSServiceConfiguration(region: AWSRegionType.USEast1, credentialsProvider: AWSMobileClient.default())
// Initialize the API client using the service configuration xyz123useamplifyabcdClient.registerClient(withConfiguration: serviceConfiguration!, forKey: "CloudLogicAPIKey")
// Fetch the Cloud Logic client to be used for invocation let invocationClient = xyz123useamplifyabcdClient.client(forKey: "CloudLogicAPIKey")
invocationClient.invoke(apiRequest).continueWith { (task: AWSTask) -> Any? in if let error = task.error { print("Error occurred: \(error)") // Handle error here return nil }
// Handle successful result here let result = task.result! let responseString = String(data: result.responseData!, encoding: .utf8)
print(responseString) print(result.statusCode)
return nil }}
You can then invoke this method with self.doInvokeAPI()
from your application code.
Cognito User Pools authorization
When invoking an API Gateway endpoint with Cognito User Pools authorizer, you can leverage the AWSMobileClient
to dynamically refresh and pass tokens to your endpoint. Using the example from the previous section, update the doInvokeAPI()
so that it takes an argument of token:String
. Next, add a header of "Authorization" : token
and set the service configuration to have credentialsProvider: nil
. Finally, overload the doInvokeAPI()
with a new definition that gets the Cognito User Pools token from the AWSMobileClient
as below:
//New overloaded function that gets Cognito User Pools tokensfunc doInvokeAPI(){ AWSMobileClient.default().getTokens { (tokens, err) in self.doInvokeAPI(token: tokens!.idToken!.tokenString!) }}
//Updated function with arguments and code updatesfunc doInvokeAPI(token:String) {
let headerParameters = [ //other headers "Authorization" : token ]
let serviceConfiguration = AWSServiceConfiguration(region: AWSRegionType.USEast1, credentialsProvider: nil)
}
You can then invoke this method with self.doInvokeAPI()
from your application code and it will pass the IdToken from Cognito User Pools as an Authorization
header.