はじめに
このトピックでは、iOS 用 HTTPDNS SDK の統合方法について説明します。
プロジェクトの依存関係は 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'この例を、リリースノートの最新バージョン番号を使用するように更新してください。
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. サービスインスタンスの取得
iOS 用 HTTPDNS SDK は、グローバルサービスインスタンスを介してドメイン名解決サービスを提供します。インスタンスは次のように取得できます。
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 アドレスがありません。デフォルトのロジックにフォールバックします。
}サンプルコード
iOS 用 HTTPDNS SDK の統合方法を示すサンプルプロジェクトについては、「HTTPDNS iOS Demo」をご参照ください。
注意事項
フォールバックコードの記述
フォールバックコードは、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) { // IP アドレスは HTTPDNS から取得されます。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 { // これはフォールバックの処理方法を示しています。 // IP アドレスを HTTPDNS から取得できません。元の 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 { // IP アドレスは HTTPDNS から取得されます。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 { // これはフォールバックの処理方法を示しています。 // IP アドレスを HTTPDNS から取得できません。元の 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 アドレスをリクエストします。したがって、アクセスを許可するために
Info.plistでNSAllowsArbitraryLoadsを構成する必要があります。リクエストアドレスが HTTPS アドレスの場合は、このドキュメントの後半にある HTTPS シナリオのガイダンスをご参照ください。
Cookie フィールド
一部のネットワークライブラリは、自動的な Cookie のストレージと管理をサポートしています。HTTPDNS を使用して IP アドレスを含む URL にリクエストを行うと、一部のネットワークライブラリは、HTTP リクエストヘッダーの `HOST` フィールドの値ではなく、URL の IP アドレスを Cookie のドメイン名として保存する場合があります。これにより、Cookie の管理と使用に問題が発生する可能性があります。したがって、自動 Cookie 管理機能を無効にする必要があります。この機能はデフォルトで無効になっています。
HTTPS、WebView、および SNI のシナリオ
HTTPS シナリオについては、「iOS のネイティブシナリオで HTTPDNS を使用する」をご参照ください。
プロキシでの使用
中間 HTTP プロキシが存在する場合、クライアントが開始したリクエストのリクエストラインは絶対パス URL を使用します。HTTPDNS を有効にして IP アドレスを含む URL でアクセスすると、中間プロキシは IP アドレスを識別し、それを実際の `HOST` 情報として宛先サーバーに渡します。宛先サーバーは、実際の `HOST` 情報がない HTTP リクエストを処理できません。Mobile Gateway は、この問題を解決するために独自プロトコルフィールド
X-Online-Hostを提供します。例:宛先 URL: http://www.aliyun.com/product/oss/ HTTPDNS によって解決された www.aliyun.com の IP アドレス: X.X.X.X プロキシ: 10.0.0.172:80 HTTP リクエストヘッダー: GET http://X.X.X.X/product/oss/ HTTP/1.1 # プロキシ経由で開始された HTTP リクエストのリクエストラインは絶対パスです。 Host: www.aliyun.com # このヘッダーはプロキシゲートウェイによって無視されます。プロキシゲートウェイは、リクエストラインの絶対パスにある host フィールドをオリジンサーバーのホストとして使用します。これは X.X.X.X です。 X-Online-Host: www.aliyun.com # このヘッダーは、実際の Host を送信するために Mobile Gateway によって追加されたプライベートヘッダーです。オリジンサーバーは、このプライベートヘッダーを認識して実際の Host 情報を取得するように構成する必要があります。X-Online-Hostリクエストヘッダーフィールドを以下のメソッドを使用して設定します。次に、サーバーがこのプライベートヘッダーフィールドを解析するように構成します。[request setValue:url.host forHTTPHeaderField:@"X-Online-Host"];説明ほとんどのシナリオでは、現在のデバイスでネットワークプロキシが有効になっているかどうかを確認できます。プロキシが有効になっている場合は、ドメイン名解決に HTTPDNS を使用しないでください。