Я следовал двум учебникам API Gateway для двух разных REST API, которые вызывают AWS Lambda. Вот ссылка на Calc API, которая является темой этого поста.
В каждом случае тестовые вызовы через Консоль AWS работают отлично. Но когда я генерирую iOS Swift SDK из развернутой вкладки этапа «Создание SDK», распаковываю и импортирую в мой проект Xcode, элемент defaultClient
отсутствует в <API-Name>Client.swift
.
Файл README.md в каждом случае говорит, что он должен быть там:
# Use the SDK in your project
1. Grab the `defaultClient` from your code
let client = <API-Name>Client.defaultClient()
1. You can now call your method using the client SDK
Но в <API-Name>Client.swift
.
НЕТ
defaultClient
.
UPDATE
defaultClient
нет, но есть default
(с обратными галочками вокруг него, потому что default
- зарезервированное слово в Swift). Поэтому я заменил это в вызове REST API ... и это сработало! Я понятия не имею, почему ... Я не знаю, что означают эти галочки в Свифте ... и если кто-то может мне это объяснить, прекрасно. Но я проверил через API Gateway, что API был вызван успешно; и я проверил через Cloudwatch, что функция Lambda возвращает правильное значение.
Вот мой код, который вызывает API:
@IBAction func userInvokeApi(_ sender: UIButton) {
print("You clicked invoke api...")
let client = SVTLambdaGateClient.default()
client.calcGet(operand2: "3", _operator: "+", operand1: "5").continueWith{ (task: AWSTask?) -> AnyObject? in
if let error = task?.error {
print("Error occurred: \(error)")
return nil
}
if let result = task?.result {
// Do something with result
print("The result is... \(result)")
}
return nil
}
}
Однако я еще не понимаю структуру данных, возвращаемых на Клиента. Вот что я получаю:
You clicked invoke api...
The result is... <AmplifyRestApiTest.Empty: 0x600002020770> {
}
Вот полное содержимое сгенерированного файла <API-Name>Client.swift
(некоторые комментарии удалены). Я думаю, что возможно, что README больше не синхронизируется с генерацией SDK.
import AWSCore
import AWSAPIGateway
public class SVTLambdaGateClient: AWSAPIGatewayClient {
static let AWSInfoClientKey = "SVTLambdaGateClient"
private static let _serviceClients = AWSSynchronizedMutableDictionary()
private static let _defaultClient:SVTLambdaGateClient = {
var serviceConfiguration: AWSServiceConfiguration? = nil
let serviceInfo = AWSInfo.default().defaultServiceInfo(AWSInfoClientKey)
if let serviceInfo = serviceInfo {
serviceConfiguration = AWSServiceConfiguration(region: serviceInfo.region, credentialsProvider: serviceInfo.cognitoCredentialsProvider)
} else if (AWSServiceManager.default().defaultServiceConfiguration != nil) {
serviceConfiguration = AWSServiceManager.default().defaultServiceConfiguration
} else {
serviceConfiguration = AWSServiceConfiguration(region: .Unknown, credentialsProvider: nil)
}
return SVTLambdaGateClient(configuration: serviceConfiguration!)
}()
/**
Returns the singleton service client. If the singleton object does not exist, the SDK instantiates the default service client with `defaultServiceConfiguration` from `AWSServiceManager.defaultServiceManager()`. The reference to this object is maintained by the SDK, and you do not need to retain it manually.
@return The default service client.
*/
public class func `default`() -> SVTLambdaGateClient{
return _defaultClient
}
/**
Creates a service client with the given service configuration and registers it for the key.
@param configuration A service configuration object.
@param key A string to identify the service client.
*/
public class func registerClient(withConfiguration configuration: AWSServiceConfiguration, forKey key: String){
_serviceClients.setObject(SVTLambdaGateClient(configuration: configuration), forKey: key as NSString);
}
/**
Retrieves the service client associated with the key. You need to call `registerClient(withConfiguration:configuration, forKey:)` before invoking this method or alternatively, set the configuration in your application's `info.plist` file. If `registerClientWithConfiguration(configuration, forKey:)` has not been called in advance or if a configuration is not present in the `info.plist` file of the app, this method returns `nil`.
Then call the following to get the service client:
let serviceClient = SVTLambdaGateClient.client(forKey: "USWest2SVTLambdaGateClient")
@param key A string to identify the service client.
@return An instance of the service client.
*/
public class func client(forKey key: String) -> SVTLambdaGateClient {
objc_sync_enter(self)
if let client: SVTLambdaGateClient = _serviceClients.object(forKey: key) as? SVTLambdaGateClient {
objc_sync_exit(self)
return client
}
let serviceInfo = AWSInfo.default().defaultServiceInfo(AWSInfoClientKey)
if let serviceInfo = serviceInfo {
let serviceConfiguration = AWSServiceConfiguration(region: serviceInfo.region, credentialsProvider: serviceInfo.cognitoCredentialsProvider)
SVTLambdaGateClient.registerClient(withConfiguration: serviceConfiguration!, forKey: key)
}
objc_sync_exit(self)
return _serviceClients.object(forKey: key) as! SVTLambdaGateClient;
}
/**
Removes the service client associated with the key and release it.
@param key A string to identify the service client.
*/
public class func removeClient(forKey key: String) -> Void{
_serviceClients.remove(key)
}
init(configuration: AWSServiceConfiguration) {
super.init()
self.configuration = configuration.copy() as! AWSServiceConfiguration
var URLString: String = "https://<my-api-id>.execute-api.us-east-2.amazonaws.com/test"
if URLString.hasSuffix("/") {
URLString = URLString.substring(to: URLString.index(before: URLString.endIndex))
}
self.configuration.endpoint = AWSEndpoint(region: configuration.regionType, service: .APIGateway, url: URL(string: URLString))
let signer: AWSSignatureV4Signer = AWSSignatureV4Signer(credentialsProvider: configuration.credentialsProvider, endpoint: self.configuration.endpoint)
if let endpoint = self.configuration.endpoint {
self.configuration.baseURL = endpoint.url
}
self.configuration.requestInterceptors = [AWSNetworkingRequestInterceptor(), signer]
}
/*
@param operand2
@param _operator
@param operand1
return type: Empty
*/
public func calcGet(operand2: String, _operator: String, operand1: String) -> AWSTask<Empty> {
let headerParameters = [
"Content-Type": "application/json",
"Accept": "application/json",
]
var queryParameters:[String:Any] = [:]
queryParameters["operand2"] = operand2
queryParameters["operator"] = _operator
queryParameters["operand1"] = operand1
let pathParameters:[String:Any] = [:]
return self.invokeHTTPRequest("GET", urlString: "/calc", pathParameters: pathParameters, queryParameters: queryParameters, headerParameters: headerParameters, body: nil, responseClass: Empty.self) as! AWSTask<Empty>
}
/*
@param body
return type: Empty
*/
public func calcPost(body: SVTInput) -> AWSTask<Empty> {
let headerParameters = [
"Content-Type": "application/json",
"Accept": "application/json",
]
let queryParameters:[String:Any] = [:]
let pathParameters:[String:Any] = [:]
return self.invokeHTTPRequest("POST", urlString: "/calc", pathParameters: pathParameters, queryParameters: queryParameters, headerParameters: headerParameters, body: body, responseClass: Empty.self) as! AWSTask<Empty>
}
/*
@param operand2
@param _operator
@param operand1
return type: SVTResult
*/
public func calcOperand1Operand2OperatorGet(operand2: String, _operator: String, operand1: String) -> AWSTask<SVTResult> {
let headerParameters = [
"Content-Type": "application/json",
"Accept": "application/json",
]
let queryParameters:[String:Any] = [:]
var pathParameters:[String:Any] = [:]
pathParameters["operand2"] = operand2
pathParameters["operator"] = _operator
pathParameters["operand1"] = operand1
return self.invokeHTTPRequest("GET", urlString: "/calc/{operand1}/{operand2}/{operator}", pathParameters: pathParameters, queryParameters: queryParameters, headerParameters: headerParameters, body: nil, responseClass: SVTResult.self) as! AWSTask<SVTResult>
}
Любая помощь с благодарностью!