「http://」のAPIを実行できるようにする(Swift)

## はじめに

[この記事](https://qiita.com/uhooi/items/f731f558c1e5226e08b4)でAPIクライアントを実装したのでさっそく使おうと思ったのですが、以下のエラーが発生して落ちてしまいました。

エラーとその訳を転記します。

```log
App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.
App Transport Security(ATS)は安全でないため、平文HTTP(http://)リソースの負荷をブロックしました。 一時的な例外は、アプリのInfo.plistファイルで設定できます。
```

```log
since it does not conform to ATS policy
ATSポリシーに準拠していないため
```

どうやらHTTP通信は安全でないのでデフォルトではブロックするようです。HTTPS通信はブロックしません。

`Info.plist` で設定すれば通信できるとのことなので、その方法を紹介します。

## 環境

- OS：macOS High Sierra 10.13.1
- Xcode：9.2
- Swift：4.0.3

## 解決策

解決策は大きく分けて2つあります。

### ①ATSを無効にする

#### メリット

- __ドメインを指定せずに全てのAPIが使える__  
HTTP/HTTPSの両方の通信を全て許可することになるため、ドメインを指定せずに全てのAPIが使えます。  
「http://」のAPIを多数使うアプリではこちらの解決策を検討してもいいかもしれません。

#### デメリット

- __安全性が低下する__  
全てのHTTP通信を許可することになるため、安全性が低下します。  
具体的には、通信を盗聴・改ざんされるリスクが高まります。

#### `Info.plist` の設定

App Transport Security Settings > Allow Arbitrary Loads の値を `YES` に指定すると、ATSが無効になります。
<img width="499" alt="スクリーンショット_2018-07-22_14_23_37.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/138245/ce96aa06-9e4d-ac9e-509f-2a5e4d9a5fcf.jpeg">

### ②ATSを有効のまま、通信を許可するドメインを指定する

#### メリット

- __安全性の低下を防げる__  
指定したドメインのみHTTP通信を許可するため、安全性の低下を防げます。

#### デメリット

- __ドメインの指定が手間になる__  
「http://」のAPIを多数使うアプリの場合、全てのドメインを手動で指定しなければいけないので手間がかかります。

#### `Info.plist` の設定

|名前|キー|タイプ|説明|
|:--|:--|:--|:--|
|App Transport Security Settings|NSAppTransportSecurity|Dictionary|ATS設定のトップ|
|　Allow Arbitrary Loads|NSAllowsArbitraryLoads|Boolean|全てのHTTP通信を許可する|
|　Allow Arbitrary Loads in Web Content|NSAllowsArbitraryLoadsInWebContent|Boolean|WebViewのみ全てのHTTP通信を許可する|
|　Exception Domains|NSExceptionDomains|Dictionary|例外ドメインのトップ|
|　　{ドメイン}|名前と同様|Dictionary|例外に指定するドメイン|
|　　　NSIncludesSubdomains|名前と同様|Boolean|サブドメインを含める|
|　　　NSTemporaryExceptionAllowsInsecureHTTPLoads|名前と同様|Boolean|対象ドメインのHTTP通信を許可する|
|　　　NSExceptionMinimumTLSVersion|名前と同様|String|TBD|
|　　　NSTemporaryExceptionRequiresForwardSecrecy|名前と同様|Boolean|TBD|
|　　　NSRequiresCertificateTransparency|名前と同様|Boolean|TBD|

例
郵便番号検索API
http://zipcloud.ibsnet.co.jp/
のHTTP通信を許可する
<img width="501" alt="スクリーンショット_2018-07-19_23_03_22.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/138245/48dd419b-9013-e380-859e-d8130739c67d.jpeg">

例では `ibsnet.co.jp` のサブドメインを含めHTTP通信を許可しています。

## 結論

以下が望ましいです。
HTTP通信したいドメインが少ない→解決策②
多い→解決策①も検討

## 参考リンク

- [NSAppTransportSecurity - 情報プロパティリスト| アップルデベロッパ向けドキュメント](https://developer.apple.com/documentation/bundleresources/information_property_list/nsapptransportsecurity)
- [NSExceptionDomains - NSAppTransportSecurity | Apple Developer Documentation](https://developer.apple.com/documentation/bundleresources/information_property_list/nsapptransportsecurity/nsexceptiondomains)
- [iOS9でHTTP通信ができない時の解決法 - Qiita](https://qiita.com/akatsuki174/items/176886ac9f695e2f3d29)
- [iOS9 ATS問題 - Qiita](https://qiita.com/yanayanalte/items/e6d83c12af77fa238a58)
- [[Swift3]無闇やたらにAllow Arbitrary Loadsするのはもうやめよう](https://picolica.com/2017/06/27/swift3-dont-allow-arbitrary-loads/)
- [Xcode - ATSをallowにしてもhttp://にアクセスできない｜teratail](https://teratail.com/questions/84468)  
`Allow Arbitrary Loads in Web Content` をONにすると `Allow Arbitrary Loads` の設定が無視されるようになるようです。