Last active
November 4, 2017 10:04
-
-
Save takasek/6954c501810b8443cb0eb469711aa5e4 to your computer and use it in GitHub Desktop.
AWS API Gateway(SDK version ≧2.6)の自動生成コードを、ちゃんとコンパイルが通るSwiftyなコードで置き換える ref: http://qiita.com/takasek/items/112f866386d4594dc313
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
init(configuration: AWSServiceConfiguration) { | |
super.init() | |
var urlString = "https://xxxxxxxxxx.execute-api.{region}.amazonaws.com/{stage名}" | |
if urlString.hasSuffix("/") { | |
urlString = String(urlString.dropLast()) | |
} | |
self.configuration = AWSServiceConfiguration( | |
region: configuration.regionType, | |
endpoint: AWSEndpoint(region: configuration.regionType, service: .APIGateway, url: URL(string: urlString)), | |
credentialsProvider: configuration.credentialsProvider | |
) | |
let signer = AWSSignatureV4Signer(credentialsProvider: self.configuration.credentialsProvider, endpoint: self.configuration.endpoint)! | |
if let endpoint = self.configuration.endpoint { | |
self.configuration.baseURL = endpoint.url | |
} | |
self.configuration.requestInterceptors = [AWSNetworkingRequestInterceptor(), signer] | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// API Gatewayの自動生成コードをラップする構造体 | |
struct APIGateway { | |
enum Method: String { | |
case GET | |
case POST | |
case PUT | |
case DELETE | |
case HEAD | |
case PATCH | |
case OPTIONS | |
} | |
enum DecodingError: Swift.Error { | |
case unknown | |
} | |
enum Result<T> { | |
case success(T) | |
case error(Swift.Error) | |
} | |
/// 作成したAPI/ステージなどの環境に応じて書き替える | |
fileprivate typealias GeneratedClient = {PREFIX}{API名}Client | |
private static let clientKey = "適当な文字列" | |
/// didFinishLaunchingWithOptionsで呼ぶやつ | |
static func register() { | |
let credentialProvider = AWSCognitoCredentialsProvider(regionType: .APNortheast1, identityPoolId: "ap-northeast-1:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") | |
let configuration = AWSServiceConfiguration(region: .APNortheast1, credentialsProvider: credentialProvider)! | |
GeneratedClient.registerClient(withConfiguration: configuration, forKey: clientKey) | |
} | |
fileprivate static var generated: GeneratedClient { | |
return GeneratedClient.client(forKey: clientKey) | |
} | |
} | |
/// AWSAPIGatewayRequest, AWSTaskをラップしてSwiftyにAPI定義を記述するためのプロトコル | |
protocol APIGatewayRequest { | |
associatedtype Response | |
var httpMethod: APIGateway.Method { get } | |
var urlString: String { get } | |
var queryParameters: [AnyHashable: Any] { get } | |
var headerParameters: [AnyHashable: Any] { get } | |
var httpBody: Any? { get } | |
} | |
extension APIGatewayRequest { | |
var headerParameters: [AnyHashable: Any] { | |
return [ | |
"Content-Type": "application/json", | |
"Accept": "application/json", | |
] | |
} | |
var queryParameters: [AnyHashable: Any] { return [:] } | |
var httpBody: Any? { return nil } | |
private var awsRequest: AWSAPIGatewayRequest { | |
return AWSAPIGatewayRequest( | |
httpMethod: httpMethod.rawValue, | |
urlString: urlString, | |
queryParameters: queryParameters, | |
headerParameters: headerParameters, | |
httpBody: httpBody | |
) | |
} | |
} | |
/// レスポンスが必要なエンドポイントに使う。Codableを活用する。 | |
extension APIGatewayRequest where Response: Decodable { | |
func invoke(completion: @escaping (APIGateway.Result<Response>) -> Void) { | |
APIGateway.generated.invoke(awsRequest).continueWith(block: { | |
if let data = $0.result?.responseData { | |
do { | |
let t = try JSONDecoder().decode(Response.self, from: data) | |
completion(.success(t)) | |
} catch(let e) { | |
completion(.error(e)) | |
} | |
} else { | |
completion(.error($0.error ?? APIGateway.DecodingError.unknown)) | |
} | |
return nil | |
}) | |
} | |
} | |
/// レスポンスが不要なエンドポイントに使う | |
extension APIGatewayRequest where Response == Void { | |
func invoke(completion: @escaping (APIGateway.Result<Void>) -> Void) { | |
APIGateway.generated.invoke(awsRequest).continueWith(block: { | |
if $0.result?.responseData != nil { | |
completion(.success(Void())) | |
} else { | |
completion(.error($0.error ?? APIGateway.DecodingError.unknown)) | |
} | |
return nil | |
}) | |
} | |
} | |
// MARK: - RxSwift.Singleに寄せたい場合は以下を使う | |
import RxSwift | |
extension Single { | |
static func from<T: APIGatewayRequest>(_ request: T) -> Single<Element> where T.Response == Element, T.Response: Decodable { | |
return Single<Element>.create { emitter in | |
request.invoke { | |
switch $0 { | |
case .success(let t): emitter(.success(t)) | |
case .error(let t): emitter(.error(t)) | |
} | |
} | |
return Disposables.create() | |
} | |
} | |
static func from<T: APIGatewayRequest>(_ request: T) -> Single<Element> where T.Response == Element, T.Response == Void { | |
return Single<Element>.create { emitter in | |
request.invoke { | |
switch $0 { | |
case .success(let t): emitter(.success(t)) | |
case .error(let t): emitter(.error(t)) | |
} | |
} | |
return Disposables.create() | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { | |
APIGateway.register() | |
return true | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Pure Swift struct brought as the response from APIGateway. | |
struct Hoge: Codable { | |
let id: Int | |
let userID: Int | |
let url: URL | |
private enum CodingKeys: String, CodingKey { | |
case id | |
case userID = "user_id" | |
case url | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct HogeGetRequest: APIGatewayRequest { | |
typealias Response = [Hoge] | |
let httpMethod: APIGateway.Method = .GET | |
let urlString = "/hoges" | |
let queryParameters: [AnyHashable: Any] | |
init(userID: Int) { | |
queryParameters = [ | |
"user_id": userID | |
] | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 通信後の処理をコールバックで記述 | |
HogeGetRequest(userID: 1).invoke { | |
switch $0 { | |
case .success(let hoges): print(hoges) | |
case .error(let error): print(error) | |
} | |
} | |
// RxSwiftを使っているならこうも書ける | |
Single.from(HogeGetRequest(userID: 1)) | |
.subscribe(onSuccess: { hoges in | |
print(hoges) | |
}) | |
.disposed(by: disposeBag) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct HogePostRequest: APIGatewayRequest { | |
typealias Response = Void | |
let httpMethod: APIGateway.Method = .POST | |
let urlString = "/hoges" | |
let httpBody: Any? | |
struct Parameters: Encodable { | |
let url: URL | |
} | |
init(parameters: Parameters) { | |
httpBody = try! JSONEncoder().encode(parameters) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 通信後の処理をコールバックで記述 | |
HogePostRequest(parameters: .init( | |
url: URL(string: "https://aws.amazon.com")! | |
)) | |
.invoke { | |
switch $0 { | |
case .success: () // Void | |
case .error(let error): print(error) | |
} | |
} | |
// RxSwiftを使っているならこうも書ける | |
Single.from(HogePostRequest(parameters: .init( | |
url: URL(string: "https://aws.amazon.com")! | |
))) | |
.subscribe() | |
.disposed(by: disposeBag) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment