はじめに
このトピックでは、HTTPDNS SDK for iOSを統合する方法について説明します。
CocoaPodsを使用して、プロジェクトの依存関係を管理できます。
SDKの最新バージョンは、
iOS Deployment Target 10.0以降をサポートしています。SDKは静的ライブラリとしてパッケージ化されています。
エミュレーターでは
x86_64およびarm64アーキテクチャを、実機ではarm64アーキテクチャをサポートしています。
手順1:SDK をアプリケーションに追加
1. Master リポジトリと Alibaba Cloud リポジトリの指定
iOS 向け HTTPDNS SDK およびその他の iOS 向け EMAS SDK は、Alibaba Cloud EMAS が管理する公式 GitHub リポジトリで公開されています。Podfile にリポジトリのアドレスを含める必要があります。
source 'https://github.com/CocoaPods/Specs.git'
source 'https://github.com/aliyun/aliyun-specs.git'2. 依存関係の追加
HTTPDNS iOS SDK を使用するターゲットに、次の依存関係を追加します。
use_framework!
pod 'AlicloudHTTPDNS', 'x.x.x'依存関係の例で使用されている最新の SDK バージョン番号については、リリースノートのドキュメントをご参照ください。
3. 依存関係のインストール
ターミナルで、Podfile が含まれているフォルダに移動します。次のコマンドを実行して、依存関係をインストールします。
pod install --repo-updateインストールが完了したら、.xcworkspace ファイルを使用してプロジェクトを再度開いてください。
ステップ 2: SDK を使用する
1. ヘッダーファイルのインポート
HTTPDNS を使用するコードファイルにヘッダーファイルをインポートします。
#import <AlicloudHttpDNS/AlicloudHttpDNS.h>import AlicloudHttpDNS2. HTTPDNS インスタンスの作成と設定
-[AppDelegate application:didFinishLaunchingWithOptions:] メソッドで、グローバル HTTPDNS インスタンスを作成し、設定します。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// アプリケーション起動後のカスタマイズのためのオーバーライドポイント。
// Alibaba Cloud HTTPDNS コンソールで割り当てられた AccountId を使用して、グローバルインスタンスを作成します。
// インスタンスはグローバルで一度だけ初期化する必要があります。コンソールから認証キーを取得し、初期化時に secretKey を設定します。
HttpDnsService *httpdns = [[HttpDnsService alloc] initWithAccountID:<Your AccountId> secretKey:@"<Your SecretKey>"];
// デバッグとトラブルシューティングのためにログ記録を有効にします。
[httpdns setLogEnabled:NO];
// ドメイン名の名前解決リクエストに HTTPS を使用するかどうかを指定します。
[httpdns setHTTPSRequestEnabled:YES];
// 起動ノードを設定します。シナリオに基づいて起動ノードを選択します。
[httpdns setRegion:ALICLOUD_HTTPDNS_SINGAPORE_REGION_KEY];
// 永続キャッシュを有効にして、アプリが最後のアクティブセッションからローカルにキャッシュされた IP アドレスを再利用できるようにします。これにより、アプリ起動後のドメイン名の名前解決結果の取得が高速化されます。
[httpdns setPersistentCacheIPEnabled:YES];
// 期限切れの IP アドレスの使用を許可します。ドメイン名の IP 設定が安定している場合は、この機能を有効にすることで名前解決の効率を向上させることができます。
[httpdns setReuseExpiredIPEnabled:YES];
// HTTPDNS の基盤となるネットワークリクエストのタイムアウト期間を設定します。単位:秒。
[httpdns setNetworkingTimeoutInterval:2];
return YES;
}func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// アプリケーション起動後のカスタマイズのためのオーバーライドポイント。
// Alibaba Cloud HTTPDNS コンソールで割り当てられた AccountId を使用して、グローバルインスタンスを作成します。
// インスタンスはグローバルで一度だけ初期化する必要があります。コンソールから認証キーを取得し、初期化時に secretKey を設定します。
let httpdns = HttpDnsService(accountID: <Your AccountId>, secretKey: "<Your SecretKey>")
// デバッグとトラブルシューティングのためにログ記録を有効にします。
httpdns.setLogEnabled(false)
// ドメイン名の名前解決リクエストに HTTPS を使用するかどうかを指定します。
httpdns.setHTTPSRequestEnabled(true)
// 起動サービスノードを設定します。シナリオに基づいて起動ノードを選択します。
httpdns.setRegion(ALICLOUD_HTTPDNS_SINGAPORE_REGION_KEY)
// 永続キャッシュを有効にして、アプリが最後のアクティブセッションからローカルにキャッシュされた IP アドレスを再利用できるようにします。これにより、アプリ起動後のドメイン名の名前解決結果の取得が高速化されます。
httpdns.setPersistentCacheIPEnabled(true)
// 期限切れの IP アドレスの使用を許可します。ドメイン名の IP 設定が安定している場合は、この機能を有効にすることで名前解決の効率を向上させることができます。
httpdns.setReuseExpiredIPEnabled(true)
// IPv6 アドレスの名前解決をサポートするかどうかを指定します。このスイッチをオンにした場合にのみ、名前解決インターフェイスはドメイン名の IPv6 アドレスを解決して返すことができます。
httpdns.setIPv6Enabled(true)
return true
}setPersistentCacheIPEnabled:YESとsetReuseExpiredIPEnabled:YESを有効にすると、オプティミスティック DNS キャッシュが実装されます。この機能は、名前解決の結果を永続的に保存し、期限切れの IP アドレスの使用を許可することで、ほとんどの DNS 名前解決をローカルで完了させることができます。その結果、ファーストスクリーンローディングとリクエストのパフォーマンスが向上します。名前解決された IP アドレスが頻繁に変更されないビジネスドメイン名の場合は、この機能を有効にすることを推奨します。詳細については、「永続キャッシュの有効化」および「期限切れの IP アドレスの使用許可」インターフェイスの説明をご参照ください。setHTTPSRequestEnabled パラメーターを `true` に設定すると、コストが増加します。詳細については、「製品の課金」ドキュメントをご参照ください。
ドメイン名情報または SDNS パラメーターに対して高いセキュリティ要件がある場合は、「初期化インターフェイス」を介して `aesSecretKey` を設定することで、暗号化機能を有効にできます。コンテンツの暗号化を有効にすると、コストが増加します。詳細については、「製品の課金」ドキュメントをご参照ください。
「事前解決インターフェイス」を使用してドメイン名の事前解決を有効にします。これにより、オプティミスティック DNS キャッシュのヒット率が大幅に向上し、ほとんどの名前解決リクエストがローカルキャッシュから直接返されるようになり、リアルタイムの名前解決によるレイテンシーが削減されます。ただし、事前解決は名前解決リクエストの数を増加させます。パフォーマンスとコストの最適なバランスを達成するために、コアビジネスドメイン名または頻繁にアクセスされるドメイン名に対してのみこの機能を有効にすることを推奨します。
デフォルトでは、`setRegion` は中国本土のサービスノードを使用します。ご利用のアプリケーションが中国以外で HTTPDNS を使用する必要がある場合は、この SDK の起動サービスノードを明示的に設定して、名前解決の効率を向上させることができます。詳細については、「リージョンノードの設定」をご参照ください。
3. サービスインスタンスの取得
HTTPDNS SDK for iOS は、グローバルサービスインスタンスを介して名前解決サービスを提供します。インスタンスは、以下の方法で取得します。
HttpDnsService *httpdns = [HttpDnsService sharedInstance];let httpdns = HttpDnsService.sharedInstance()4. ドメイン名の名前解決
HTTPDNS は、事前解決、同期解決、非同期解決、同期非ブロッキング解決など、複数のドメイン名の名前解決メソッドを提供します。次の例では、同期非ブロッキング解決インターフェイスを使用します。
HttpDnsService *httpdns = [HttpDnsService sharedInstance];
HttpdnsResult *result = [httpdns resolveHostSyncNonBlocking:@"www.aliyun.com" byIpType:HttpdnsQueryIPTypeAuto];
if (result) {
// ドメイン名の名前解決結果を使用します。
} else {
// 同期非ブロッキングインターフェイスは、キャッシュ内に有効な解決結果が見つからない場合、最速の解決速度を確保するためにすぐに null を返します。新しい解決リクエストはバックグラウンドで開始されます。
// したがって、LocalDNS 名前解決にフォールバックするか、完全なドメイン名をネットワークライブラリに直接渡す準備をする必要があります。
// 同期インターフェイスまたはコールバックベースのインターフェイスを使用して、HTTPDNS の解決結果を確実に取得できます。
}let httpdns = HttpDnsService.sharedInstance()
if let result = httpdns.resolveHostSyncNonBlocking("www.aliyun.com", by: HttpdnsQueryIPType.auto) {
// ドメイン名の名前解決結果を使用します。
} else {
// 同期非ブロッキングインターフェイスは、キャッシュ内に有効な解決結果が見つからない場合、最速の解決速度を確保するためにすぐに null を返します。新しい解決リクエストはバックグラウンドで開始されます。
// したがって、LocalDNS 名前解決にフォールバックするか、完全なドメイン名をネットワークライブラリに直接渡す準備をする必要があります。
// 同期インターフェイスまたはコールバックベースのインターフェイスを使用して、HTTPDNS の解決結果を確実に取得できます。
}ビジネスシナリオに基づいて、ドメイン名の名前解決インターフェイスを選択してください。
戻り値が常に
nilの場合は、Alibaba Cloud HTTPDNS コンソールにドメイン名を追加したかどうかを確認してください。ネットワーク異常により戻り値が
nilになった場合にビジネスプロセスが影響を受けないように、LocalDNS名前解決にフォールバックしてください。
5. 名前解決結果の活用
名前解決結果は、状況に応じて異なります。
空の結果。同期非ブロッキングインターフェイスを使用した場合、またはネットワーク例外が発生した場合に該当します。
IPv4 アドレスのみ。オンプレミスネットワークが IPv4 シングルスタック環境であり、リクエストタイプが IPv4 として指定されている場合、またはドメイン名に対して IPv4 アドレスのみが設定されている場合に該当します。
IPv6 アドレスのみ。IPv6 が有効化されており、IPv6 アドレスの解決が明示的に指定されている場合に該当します。ただし、現時点における IPv6 の普及率を考慮すると、このシナリオは稀です。
IPv4 アドレスおよび IPv6 アドレスの両方。IPv6 が有効化されており、デュアルスタックアドレス解決が指定されている場合、またはデュアルスタック環境において自動ネットワークタイプ検出が指定され、かつドメイン名に対して IPv4 アドレスおよび IPv6 アドレスの両方が設定されている場合に該当します。
本例では、IPv6 解決が有効化されており、要求される IP タイプは Both に設定されています。ドメイン名に対して IPv4 アドレスおよび IPv6 アドレスの両方が設定されている場合、解決結果には両方のアドレスが含まれます。したがって、IPv4 アドレスを優先する場合は、以下のコードに示すように、解決結果を処理してください。
HttpDnsService *httpdns = [HttpDnsService sharedInstance];
HttpdnsResult *result = [httpdns resolveHostSyncNonBlocking:@"www.aliyun.com" byIpType:HttpdnsQueryIPTypeAuto];
if (!result) {
// 有効な IP アドレスがありません。デフォルトの処理にフォールバックします。
}
if (result.hasIpv4Address) {
NSString *ip = result.firstIpv4Address;
// IP アドレスを使用します。
NSArray<NSString *> *ips = result.ips;
// IP アドレス一覧を使用します。
} else if (result.hasIpv6Address) {
NSString *ip = result.firstIpv6Address;
// IP アドレスを使用します。
NSArray<NSString *> *ips = result.ipv6s;
// IP アドレス一覧を使用します。
} else {
// 有効な IP アドレスがありません。デフォルトの処理にフォールバックします。
}let httpdns = HttpDnsService.sharedInstance()
if let result = httpdns.resolveHostSyncNonBlocking("www.aliyun.com", by: HttpdnsQueryIPType.auto) {
if (result.hasIpv4Address()) {
let ip = result.firstIpv4Address()
// IP アドレスを使用します。
let ipList = result.ips
// IP アドレス一覧を使用します。
} else if (result.hasIpv6Address()) {
let ip = result.firstIpv6Address()
// IP アドレスを使用します。
let ipList = result.ipv6s
// IP アドレス一覧を使用します。
} else {
// 有効な IP アドレスがありません。デフォルトの処理にフォールバックします。
}
} else {
// 有効な IP アドレスがありません。デフォルトの処理にフォールバックします。
}サンプルコード
HTTPDNS SDK for iOS の統合方法を示すサンプルプロジェクトについては、「HTTPDNS iOS デモ」をご参照ください。
注意事項
フォールバックコードの記述
フォールバックコードは、HTTPDNS が期待される結果を取得できなかった場合に対応します。通常は、名前解決に LocalDNS を使用するようにフォールバックできます。つまり、元のドメイン名をネットワークライブラリに渡し、ローカル DNS を使ってドメイン名を解決させます。
HTTPDNS から取得した IP アドレスと sessionId の記録
解決の問題をトラブルシューティングするためのソリューションを提供しています。HTTPDNS から取得した IP アドレスおよび sessionId をログに記録する必要があります。詳細については、「セッション追跡ソリューションを使用して解決例外をトラブルシューティングする方法」をご参照ください。
HTTP リクエストヘッダーの HOST フィールドの設定
標準的な HTTP プロトコルでは、サーバーは HTTP リクエストヘッダー内の `HOST` フィールドの値を要求されたドメイン名として解析します。HTTPDNS を使用すると、リクエスト URL のホスト部分を HTTPDNS で取得した IP アドレスに置き換える必要が生じる場合があります。その後、標準的なネットワークライブラリはこの IP アドレスを HTTP リクエストヘッダーの `HOST` フィールドに割り当てます。これにより、サーバー側でドメイン名ではなく IP アドレスが送られてくるため、解析エラーが発生する可能性があります。
この問題を解決するには、HTTP リクエストの `HOST` フィールドの値を明示的に設定する必要があります。以下のコードはその簡単な例です。
- (void)sampleRequestUsingHttpdns { HttpDnsService *httpdns = [HttpDnsService sharedInstance]; NSString *originalUrlStr = @"http://www.aliyun.com/"; NSURL* url = [NSURL URLWithString:originalUrlStr]; // 同期インターフェイスを使用して IP アドレスを取得します。 HttpdnsResult* result = [httpdns resolveHostSyncNonBlocking:url.host byIpType:HttpdnsQueryIPTypeAuto]; NSLog(@"resolve result: %@", result); NSString *validIp = nil; if (result) { if (result.hasIpv4Address) { validIp = result.firstIpv4Address; } } NSMutableURLRequest *request; if (validIp) { // HTTPDNS から IP アドレスを取得しました。URL を置き換え、Host ヘッダーを設定します。 NSRange hostFirstRange = [originalUrlStr rangeOfString:url.host]; NSString* newUrl = [originalUrlStr stringByReplacingCharactersInRange:hostFirstRange withString:validIp]; request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:newUrl]]; // リクエストの HOST フィールドを設定します。 [request setValue:url.host forHTTPHeaderField:@"host"]; } else { // フォールバック処理の例です。 // HTTPDNS から IP アドレスを取得できませんでした。元の URL を使用してネットワークリクエストを行います。 request = [[NSMutableURLRequest alloc] initWithURL:url]; } // リクエストを送信します。 NSURLSession *session = [NSURLSession sharedSession]; NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (error) { NSLog(@"error: %@", error); } else { NSLog(@"response: %@", response); } }]; [task resume]; }func sampleRequestUsingHttpdns() { let httpdns = HttpDnsService.sharedInstance() let originalUrlStr = "http://www.aliyun.com/" let url = URL(string: originalUrlStr)! // 同期インターフェイスを使用して IP アドレスを取得します。 let result = httpdns.resolveHostSyncNonBlocking(url.host!, by: HttpdnsQueryIPType.auto) print("resolve result: \(result?.description ?? "")") var validIp: String? if let result = result { if result.hasIpv4Address() { validIp = result.firstIpv4Address() } } var request: URLRequest if let validIp = validIp { // HTTPDNS から IP アドレスを取得しました。URL を置き換え、Host ヘッダーを設定します。 let hostFirstRange = originalUrlStr.firstRange(of: url.host!)! let newUrl = originalUrlStr.replacingCharacters(in: hostFirstRange, with: validIp) request = URLRequest(url: URL(string: newUrl)!) // リクエストの HOST フィールドを設定します。 request.setValue(url.host!, forHTTPHeaderField: "host") } else { // フォールバック処理の例です。 // HTTPDNS から IP アドレスを取得できませんでした。元の URL を使用してネットワークリクエストを行います。 request = URLRequest(url: url) } // リクエストを送信します。 let session = URLSession.shared let task = session.dataTask(with: request) { (data, response, error) in if let error = error { print("error: \(error)") } else { print("response: \(response?.description ?? "")") } } task.resume() }重要この簡単な例では、以下の点にもご注意ください。
この例では名前解決が成功した場合のみを示しており、フォールバックロジックは考慮していません。
簡略化のため、この例では HTTP アドレスへのリクエストを行っています。そのため、アクセスを許可するために
NSAllowsArbitraryLoadsをInfo.plistに設定する必要があります。リクエスト先のアドレスが HTTPS の場合は、本ドキュメント後半の HTTPS シナリオに関するガイダンスをご参照ください。
Cookie フィールド
一部のネットワークライブラリは、Cookie の自動保存および管理機能をサポートしています。HTTPDNS を使用して IP アドレスを含む URL に対してリクエストを行うと、一部のネットワークライブラリが URL 内の IP アドレスを Cookie のドメイン名として保存してしまうことがあります(HTTP リクエストヘッダーの `HOST` フィールドの値ではなく)。これにより、Cookie の管理および利用に問題が生じる可能性があります。そのため、自動 Cookie 管理機能を無効にする必要があります。この機能はデフォルトで無効になっています。
HTTPS、WebView、SNI シナリオ
HTTPS シナリオについては、iOS のネイティブ シナリオで HTTPDNS を使用するをご参照ください。
プロキシとの併用
中間の HTTP プロキシが存在する場合、クライアントが開始するリクエストのリクエストラインには絶対パス形式の URL が使用されます。HTTPDNS を有効にして IP アドレスを含む URL を使用してアクセスすると、中間プロキシはその IP アドレスを識別し、実際の `HOST` 情報として宛先サーバーに渡します。これにより、実際の `HOST` 情報を欠いた HTTP リクエストを受け取った宛先サーバーは正常に処理できなくなります。Mobile Gateway では、この問題を解決するために独自プロトコルフィールドである
X-Online-Hostを提供しています。例を以下に示します。Destination URL: http://www.aliyun.com/product/oss/ IP address of www.aliyun.com resolved by HTTPDNS: X.X.X.X Proxy: 10.0.0.172:80 Your HTTP request header: GET http://X.X.X.X/product/oss/ HTTP/1.1 # プロキシ経由で開始される HTTP リクエストのリクエストラインは絶対パス形式です。 Host: www.aliyun.com # このヘッダーはプロキシゲートウェイによって無視されます。プロキシゲートウェイはリクエストラインの絶対パス内のホストフィールド(X.X.X.X)をオリジンサーバーのホストとして使用します。 X-Online-Host: www.aliyun.com # このヘッダーは Mobile Gateway が追加する非公開ヘッダーであり、実際の Host を伝達するために使用されます。オリジンサーバー側でこの非公開ヘッダーを認識するよう設定する必要があります。以下の方法で
X-Online-Hostリクエストヘッダーフィールドを設定し、サーバー側でこの非公開ヘッダーフィールドを解析するよう設定してください。[request setValue:url.host forHTTPHeaderField:@"X-Online-Host"];説明ほとんどのシナリオでは、現在ご利用のデバイスでネットワークプロキシが有効になっているかどうかを確認できます。プロキシが有効になっている場合は、ドメイン名解決に HTTPDNS を使用しないでください。