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.
1cd YOUR_PROJECT_FOLDER2amplify add api
When prompted select the following options:
1> REST2> Create a new Lambda function3> Serverless express function4> Restrict API access? Yes5> 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:
1amplify 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:
1target :'YOUR-APP-NAME' do2 use_frameworks!3
4 # For API5 pod 'AWSAPIGateway'6 # other pods7end
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.
1import AWSAPIGateway2import AWSMobileClient3
4 // ViewController or application context . . .5
6func doInvokeAPI() {7 // change the method name, or path or the query string parameters here as desired8 let httpMethodName = "POST"9 // change to any valid path you configured in the API10 let URLString = "/items"11 let queryStringParameters = ["key1":"{value1}"]12 let headerParameters = [13 "Content-Type": "application/json",14 "Accept": "application/json"15 ]16
17 let httpBody = "{ \n " +18 "\"key1\":\"value1\", \n " +19 "\"key2\":\"value2\", \n " +20 "\"key3\":\"value3\"\n}"21
22 // Construct the request object23 let apiRequest = AWSAPIGatewayRequest(httpMethod: httpMethodName,24 urlString: URLString,25 queryParameters: queryStringParameters,26 headerParameters: headerParameters,27 httpBody: httpBody)28
29 // Create a service configuration30 let serviceConfiguration = AWSServiceConfiguration(region: AWSRegionType.USEast1,31 credentialsProvider: AWSMobileClient.default())32
33 // Initialize the API client using the service configuration34 xyz123useamplifyabcdClient.registerClient(withConfiguration: serviceConfiguration!, forKey: "CloudLogicAPIKey")35
36 // Fetch the Cloud Logic client to be used for invocation37 let invocationClient = xyz123useamplifyabcdClient.client(forKey: "CloudLogicAPIKey")38
39 invocationClient.invoke(apiRequest).continueWith { (task: AWSTask) -> Any? in40 if let error = task.error {41 print("Error occurred: \(error)")42 // Handle error here43 return nil44 }45
46 // Handle successful result here47 let result = task.result!48 let responseString = String(data: result.responseData!, encoding: .utf8)49
50 print(responseString)51 print(result.statusCode)52
53 return nil54 }55}
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:
1//New overloaded function that gets Cognito User Pools tokens2func doInvokeAPI(){3 AWSMobileClient.default().getTokens { (tokens, err) in4 self.doInvokeAPI(token: tokens!.idToken!.tokenString!)5 }6}7
8//Updated function with arguments and code updates9func doInvokeAPI(token:String) {10
11 let headerParameters = [12 //other headers13 "Authorization" : token14 ]15
16 let serviceConfiguration = AWSServiceConfiguration(region: AWSRegionType.USEast1,17 credentialsProvider: nil)18
19}
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.