リモートWebAPIを呼び出すアプリでReactiveCocoaを使用しています。ただし、特定のAPIホストから何かを取得する前に、アプリはユーザーの資格情報を提供し、APIトークンを取得する必要があります。このトークンは、後続のリクエストに署名するために使用されます。
この認証プロセスを抽象化して、API呼び出しを行うたびに自動的に行われるようにします。ユーザーの資格情報を含むAPIクライアントクラスがあると仮定します。
// getThing returns RACSignal yielding the data returned by GET /thing.
// if the apiClient instance doesn't already have a token, it must
// retrieve one before calling GET /thing
RAC(self.thing) = [apiClient getThing];
ReactiveCocoaを使用して、APIへの最初の(そして最初の)リクエストを透過的に取得し、副作用として、後続のリクエストが行われる前にAPIトークンを安全に保存するにはどうすればよいですか?
combineLatest:
また、複数の同時リクエストを開始するために使用(または同様)できること、およびトークンが取得されるのをすべて暗黙的に待機することも要件です。
RAC(self.tupleOfThisAndThat) = [RACSignal combineLatest:@[ [apiClient getThis], [apiClient getThat]]];
さらに、API呼び出しが行われたときに、retrieve-token要求がすでに実行中である場合、そのAPI呼び出しは、retrieve-token要求が完了するまで待機する必要があります。
私の部分的な解決策は次のとおりです。
基本的なパターンはflattenMap:
、トークンを生成するシグナルを、トークンが与えられると、目的のリクエストを実行し、API呼び出しの結果を生成するシグナルにマッピングするために使用されます。
いくつかの便利な拡張機能を想定していますNSURLRequest
:
- (RACSignal *)requestSignalWithURLRequest:(NSURLRequest *)urlRequest {
if ([urlRequest isSignedWithAToken])
return [self performURLRequest:urlRequest];
return [[self getToken] flattenMap:^ RACSignal * (id token) {
NSURLRequest *signedRequest = [urlRequest signedRequestWithToken:token];
assert([urlRequest isSignedWithAToken]);
return [self requestSignalWithURLRequest:signedRequest];
}
}
次に、のサブスクリプション実装について考えてみます-getToken
。
- 些細なケースでは、トークンがすでに取得されている場合、サブスクリプションはすぐにトークンを生成します。
- トークンが取得されていない場合、サブスクリプションはトークンを返す認証API呼び出しを延期します。
- 認証API呼び出しが実行中の場合は、認証API呼び出しをネットワーク上で繰り返さずに、別のオブザーバーを追加しても安全です。
ただし、これを行う方法がわかりません。また、トークンを安全に保管する方法と場所は?ある種の永続的/反復可能な信号?