本エントリで紹介するhttp-client, http-client-tlsライブラリの機能:
- 単純なHTTP GETリクエスト
- 主要な型の説明
- Managerのカスタマイズ
- https
- proxy設定
- タイムアウト値の設定
- Requestのカスタマイズ
- ベーシック認証
- リクエストヘッダ
- Responseの操作
- ストリーミング受信
- レスポンスヘッダの参照
- エラーハンドリング
単純なHTTP GETリクエスト
{-# LANGUAGE OverloadedStrings #-} import Network.HTTP.Client import Network.HTTP.Types.Status (statusCode) main :: IO () main = do manager <- newManager defaultManagerSettings request <- parseRequest "http://httpbin.org/get" response <- httpLbs request manager putStrLn $ "The status code was: " ++ (show $ statusCode $ responseStatus response) print $ responseBody response
デフォルトManagerと、"http://httpbin/org/get"へのRequestを生成し、それらを引数にhttpLbsを呼び出して、サーバーからのResponseを得てその内容を表示するサンプルです。
文字列リテラルをRequest, ByteStringに変換する目的でOverloadedStrings言語拡張を利用しています。
主要な型の説明:
- Manager
- Managerはサーバーとの間に生成するコネクションの管理するもの。
- 複数サーバーのコネクションを管理する前提で実装されており、クライアントの中では1つのインスタンスを共有することが推奨されている。
- Managerに対しては以下のような設定ができる。デフォルト設定を併記。
- プロキシ設定:環境変数(http_proxy)の値を利用
- TLS(https):サポートなし
- 1サーバーあたりのkeep-aliveコネクション維持数: 10
- 最大同時オープンコネクション数: 512
- 受信タイムアウト: 30秒
- Request
- 特定サーバーに対して送信する1つのリクエストを表す型。
- parseRequest関数などでHTTP METHOD, URIを指定してインスタンスを生成する。
- Request単位の細かい設定ができる
- ベーシック認証情報(アカウント&パスワード)
- プロキシ設定、プロキシ認証情報
- クエリストリング、bodyなどの送信データ
- HTTPメソッド(GET, POST, DELETEなど)、ヘッダ は生成したRequestインスタンスに対して、record構文で設定する
- メソッドのデフォルトはGET
- Content-Length, Transfer-Encoding, Accept-Encodingが自動で設定される
- Response
- サーバーに送信したRequestに対応するサーバーからのレスポンスを表す型。HTTPステータスコード、レスポンスヘッダ、レスポンスボディなどを取り出すことができます。
Managerのカスタマイズ
defaultManagerSettingsの代わりにtlsManagerSettingsを用いてManagerを生成することでhttps通信が可能になります。 以下のサンプルではhttps対応に加えて、プロキシサーバーとして"127.0.0.1:8080"をManagerに設定しています。{-# LANGUAGE OverloadedStrings #-} import Network.HTTP.Client import Network.HTTP.Types.Status (statusCode) import Network.HTTP.Client.TLS (tlsManagerSettings) -- 新たにimport文を追加 main :: IO () main = do -- manageSetProxyでデフォルトのプロキシ設定を上書く。 -- tlsManagerSettingsを利用するとこでhttps通信が可能になる。 manager <- newManager $ managerSetProxy (useProxy $ Proxy "127.0.0.1" 8080) tlsManagerSettings request <- parseRequest "https://httpbin.org/get" -- https通信に変更 response <- httpLbs request manager putStrLn $ "The status code was: " ++ (show $ statusCode $ responseStatus response) print $ responseBody response
プロキシの設定:
- デフォルトの挙動。環境変数(http_proxy/https_proxy) を参照する。
- defaultProxy :: ProxyOverride
- プロキシサーバーの設定を無視して通信する。
- noProxy :: ProxyOverride
- コードで明示的にプロキシサーバーを設定する。
- useProxy :: Proxy -> ProxyOverride
レコード構文でManagerSettings値を生成する方法:
非公開APIを利用するため、オススメの方法ではありませんが以下のようにレコード構文を用いることで、Managerの細かい設定をカスタマイズすることができます。import Network.HTTP.Client.Internal -- tlsManagerSettingsをベースにmanagerResponseTimeoutを30→5秒に、 -- managerConnCountを10→3に変更 mySettings :: ManagerSettings mySettings = tlsManagerSettings { managerResponseTimeout = responseTimeoutMicro 5000000 , managerConnCount = 3 }
Requestのカスタマイズ
以下のコードはRequestに対して、リクエストヘッダ、クエリーパラメタ、ベーシック認証情報を設定するサンプルです。Requestに対して設定できる項目の詳細は、Request type and fieldsを参照してください。{-# LANGUAGE OverloadedStrings #-} import Network.HTTP.Client import Network.HTTP.Types.Status (statusCode) main :: IO () main = do manager <- newManager defaultManagerSettings initialRequest <- parseRequest "http://httpbin.org/anything" let request = initialRequest { method = "POST" -- "GET", "PUT", "DELETE"などのメソッドを指定 , queryString = "foo=bar&xxx=yyy" -- parseRequestのuriに記述してもよい , requestHeaders = -- ヘッダはタプル(名前、値)のリストで指定 [ ("User-Agent", "New Agent!") , ("Content-Type", "text/plain") , ("Added-Header", "hoge") ] , requestBody = "body string." } let authRequest = applyBasicAuth "user" "pass" request -- ベーシック認証情報付与 response <- httpLbs authRequest manager putStrLn $ "The status code was: " ++ (show $ statusCode $ responseStatus response) print $ responseBody response
Responseの操作
httpLbs関数はRequestとManagerを引数にとり、IO (Response ByteString)を返します。Response型クラスの関数で、Responseからステータスコード、レスポンスヘッダなどの情報を取り出すことができます。ResonseのAPIリファレンスはこちら。httpLbsは全データを受信しますが、大きなデータをレスポンスとして受信する場合はhttpLbsの代わりに、withResponseとbrReadを利用して逐次受信することが推奨されています。以下にそのサンプルを記載します。
{-# LANGUAGE OverloadedStrings #-} import Network.HTTP.Client import Network.HTTP.Types.Status (statusCode) import qualified Data.ByteString as B main :: IO () main = do manager <- newManager defaultManagerSettings request <- parseRequest "http://httpbin.org/get" withResponse request manager receiveResponse receiveResponse :: Response BodyReader -> IO () receiveResponse response = do putStrLn $ "response version: " ++ (show $ responseVersion response) putStrLn $ "status code: " ++ (show $ statusCode $ responseStatus response) putStrLn $ "response header: " ++ (show $ responseHeaders response) -- receive body data block by block let loop = do bs <- brRead $ responseBody response if B.null bs then putStrLn "\nFinished response body" else do print bs loop loop
エラーハンドリング
以下は、urlのパース(parseRequest)、及び、サーバーとの通信(httpLbs)のエラーハンドリングを行うサンプルです。これらの関数はエラー時にはHttpExceptionをスローします。サンプルではtry関数を用い、Left eでスローされたHttpExceptionの情報を表示しています。{-# LANGUAGE OverloadedStrings #-} import Network.HTTP.Client import Network.HTTP.Types.Status (statusCode) import Control.Exception (try) import System.Environment (getArgs) createRequest :: [String] -> IO Request createRequest [] = do putStrLn "NOTE: no argument is given. so use not existing url." parseRequest "http://unknown-host:80/" -- valid but not exists createRequest args = do let url = head args eRequest <- try $ parseRequest url case eRequest of Left e -> do print (e :: HttpException) putStrLn $ "given url (1st argument) is invalid: " ++ url error "error!" Right request -> return $ request main :: IO () main = do args <- getArgs manager <- newManager defaultManagerSettings request <- createRequest args eResponse <- try $ httpLbs request manager case eResponse of Left e -> do print (e :: HttpException) putStrLn $ "cannot reach server with given url: " ++ (head args) Right response -> do putStrLn $ "The status code was: " ++ (show $ statusCode $ responseStatus response) print $ responseBody response
他のライブラリ:
参考:
- http-clientライブラリ
- Hackage - Network.HTTP.Client
- http-client-tlsライブラリ
- Hackage - Network.HTTP.Client.TLS
- テストサービス
0 件のコメント:
コメントを投稿