some points for HTTP client on native applications (1)
はじめに
HTTP は利用頻度が高いネットワークプロトコルの一つだと思います。HTTP サーバを書くことはそんなに多くないと思いますが、HTTP クライアントは何らかの形で利用したり実装したりしたことがある人は多いのではないでしょうか。今回は、ネイティブアプリでの HTTP クライアントを利用・実装することに焦点を絞ります。
多少経験のあるプログラマなら、HTTP クライアントを自分で実装したいとはあまり思わないはずです*1。HTTP は、仕組みとしてはシンプルですがいざ実装しようとすると中々大変です。ソケットを使ってデータ転送をする処理や、HTTP リクエストの妥当性検証*2や生成、レスポンスの解析、ステータスコードの正しいハンドリング、データのバッファリング・・・。さらに、国際化ドメイン名、キープアライブ、リダイレクト、認証*3、プロキシ解決*4、プロキシ越え、HTTPS なんかも考え始めると頭が爆発しそうになるからです。フルスタックの HTTP クライアントを実装するのは非常に大変です。
ライブラリを使おう
そうなると、偉大なる先達が作ってきたものを利用しようという方向に頭が働きます。幸い、HTTP クライアントのライブラリは数多く存在します。
- プラットフォーム標準搭載のライブラリ
- Windows
- WinInet
- WinHTTP
- Cocoa
- NSURLConnection
- NSURLDownload
- Core Foundation
- Windows
- プラットフォーム非依存のライブラリ
libcurl を使おう
大抵の場合、libcurl で事足ります。マルチプラットフォーム対応している優れものです。ただし、libcurl には以下の機能・問題がないので注意が必要です。
- プロキシに Digest 認証が必要な場合、HTTPS 通信がエラーコード CURLE_RECV_ERROR ( 56 ) で失敗する
- curl-Bugs-845941 fetching https, curl returns code 56 on 407 from proxy
- 結構古くから存在するバグだが、最新の libcurl でも修正されていない
- バージョン 7.21.3 で確認
- プロキシ解決機能がない
- Unix 系 OS 以外でのルート証明書のインポート機能がない
というわけで、プロキシに Digest 認証が必要な環境で HTTPS 通信がしたい、という場合、現状の libcurl を利用することはできません。上記で挙げたプラットフォーム標準搭載のライブラリは、どれもうまく処理してくれます。
プロキシ解決
プロキシ環境をサポートする場合、まず最初にやるべきことはプロキシ解決です。プロキシ解決は、どのプロキシサーバを利用するかを決定します。ないならないで利用しません。Internet Explorer や Google Chrome を利用している方なら、ステータスバーに「プロキシを解決しています」というメッセージが表示されていることに気づいている方もいると思いますが、あれのことですね。
プロキシ解決は、アプリケーション固有のプロキシ設定を用いる場合と、プラットフォームが持つ設定を踏襲する場合があります。前者はここでは特に触れず、後者に焦点を絞ります。
Windows や Mac OS X では、プロキシ解決を以下の手順で行うことができます。
- プロキシの自動検出
- プロキシの自動構成
プロキシの自動検出は、Web Proxy Autodiscovery Protocol ( WPAD ) に基づいて行われます。大雑把にいうと、DHCP または DNS サーバに置いてある自動構成スクリプトファイルを持ってくる感じです。
WinINet なら、DetectAutoProxyUrl() を呼び出すことでこれが行えます。オプションとして、DHCP を用いるか、DNS の A レコードを用いるか、どちらもかを選択できます。呼び出すと、以下のような通信が発生します。
- DHCP を用いる場合
DHCP サーバがこれに応答するように構成されていない場合、 この API の実行に10秒以上かかることがあります。エラーコードは ERROR_NO_TOKEN ( 1008 ) などです。また、1 秒程度で完了することもあります。
DNS サーバがこれに応答するように構成されていない場合、 この API の実行に 5 秒程度かかることがあります。エラーコードは WSAHOST_NOT_FOUND ( 11001 ) などです。
自力で実装するなら、ちょっとした DHCP クライアントを書く必要があるってことですね。また、自動構成スクリプトのダウンロード自体にも HTTP が必要という罠があります。
こうして、自動検出が完了したら次は自動構成スクリプトを解釈します。
次回へ続きます。