=begin = net/http.rb version 1.2.3 == このライブラリについて 汎用データ転送プロトコル HTTP を扱うライブラリです。 実装は [RFC2616] (()) に 基いています。 == 使用例 === ウェブサーバからドキュメントを得る (GET) require 'net/http' Net::HTTP.start( 'some.www.server', 80 ) {|http| response , = http.get('/index.html') puts response.body } また以下は同じ意味で短く書いたものです。 require 'net/http' Net::HTTP.get_print 'some.www.server', '/index.html' === フォームの情報を送信する (POST) require 'net/http' Net::HTTP.start( 'some.www.server', 80 ) {|http| response , = http.post( '/cgi-bin/any.rhtml', 'querytype=subject&target=ruby' ) } === プロクシ経由のアクセス Net::HTTP のクラスメソッド Net::HTTP.Proxy は、常にプロクシ経由で 接続するような動作をする、新しいクラスを作成して返します。このクラスは Net::HTTP を継承しているので Net::HTTP と全く同じように使えます。 require 'net/http' $proxy_addr = 'your.proxy.addr' $proxy_port = 8080 : Net::HTTP::Proxy($proxy_addr, $proxy_port).start( 'some.www.server' ) {|http| # always connect to your.proxy.addr:8080 : } また Net::HTTP.Proxy は第一引数が nil だと Net::HTTP 自身を返すので 上のコードのように書いておけばプロクシなしの場合にも対応できます。 === リダイレクトに対応する require 'net/http' Net::HTTP.version_1_1 host = 'www.ruby-lang.org' path = '/' begin Net::HTTP.start( host, 80 ) {|http| response , = http.get(path) print response.body } rescue Net::ProtoRetriableError => err if m = %r.match( err.response['location'] ) then host = m[1].strip path = m.post_match retry end end この例では URL からホスト名を得るのにいいかげんな方法を使っていますが、 将来 URI クラスが標準添付になればもっと簡単になるはずです。 === Basic 認証 require 'net/http' Net::HTTP.start( 'auth.some.domain' ) {|http| response , = http.get( '/need-auth.cgi', 'Authentication' => ["#{account}:#{password}"].pack('m').strip ) print response.body } バージョン 1.2 (Ruby 1.7 以降に添付) では次のように書けます。 require 'net/http' req = Net::HTTP::Get.new('/need-auth.cgi') req.basic_auth 'account', 'password' Net::HTTP.start( 'auth.some.domain' ) {|http| response = http.request(req) print response.body } == 新しい仕様への変更と移行措置について Ruby 1.6 に入っているのが http.rb 1.1 で 1.7 以降が 1.2 ですが、 この間ではかなり大きく仕様が変わります。そこで突然に仕様を変更 するのでなく、両方の実装を並存させる時期を設けることにしました。 メソッド HTTP.version_1_2、HTTP.version_1_1 を呼ぶと そのあとに生成される Net::HTTP オブジェクトはそれぞれの バージョンの仕様で動作するようになります。以下は使用例です。 # example Net::HTTP.start {|http1| ...(http1 has 1.2 features)... } Net::HTTP.version_1_1 Net::HTTP.start {|http2| ...(http2 has 1.1 features)... } Net::HTTP.version_1_2 Net::HTTP.start {|http3| ...(http3 has 1.2 features)... } この機能はスレッドセーフではありません。 == class Net::HTTP === クラスメソッド : new( address, port = 80, proxy_addr = nil, proxy_port = nil ) 新しい HTTP オブジェクトを生成します。address は HTTP サーバーの FQDN で、 port は接続するポート番号です。このメソッドではまだ接続はしません。 proxy_addr を与えるとプロクシを介して接続するオブジェクトを生成します。 : start( address, port = 80, proxy_addr = nil, proxy_port = nil ) : start( address, port = 80, proxy_addr = nil, proxy_port = nil ) {|http| .... } 以下と同じです。 Net::HTTP.new(address, port, proxy_addr, proxy_port).start(&block) : get( address, path, port = 80 ) ホスト address の port 番ポートに接続して path の表現する エンティティを取得、文字列で返します。 : get_print( address, path, port = 80 ) ホスト address の port 番ポートに接続して path の表現する エンティティを取得したうえ、$stdout に << で出力します。 : Proxy( address, port = 80 ) 常に指定されたプロクシに接続するクラスを作成し返します。 このクラスは Net::HTTP を継承しているので Net::HTTP と全く 同じように使えます。 address が nil のときは Net::HTTP クラスをそのまま返します。 # example proxy_class = Net::HTTP::Proxy( 'proxy.foo.org', 8080 ) : proxy_class.start( 'www.ruby-lang.org' ) {|http| # connecting proxy.foo.org:8080 : } : proxy_class? 自身が (Proxy メソッドによって作成された) プロクシ用のクラスならば真。 : port HTTP のデフォルトポート (80)。 === メソッド : start : start {|http| .... } TCP コネクションを張り、HTTP セッションを開始します。 すでにセッションが開始していたら例外 IOError を発生します。 イテレータとして呼ばれた時はブロックの間だけセッションを接続し、 ブロック終了とともに自動的にセッションを閉じます。 : active? HTTP セッションが開始されていたら真。 : address 接続するアドレス : port 接続するポート番号 : open_timeout : open_timeout=(n) 接続時に待つ最大秒数。この秒数たってもコネクションが 開かなければ例外 TimeoutError を発生します。 : read_timeout : read_timeout=(n) 読みこみ (read(1) 一回) でブロックしてよい最大秒数。 この秒数たっても読みこめなければ例外 TimeoutError を発生します。 : finish HTTP セッションを終了します。セッション開始前にこのメソッドが 呼ばれた場合は例外 IOError を発生します。 : proxy? プロクシを介して接続するなら真。 : proxy_address プロクシ経由で接続する HTTP オブジェクトならプロクシのアドレス。 そうでないなら nil。 : proxy_port プロクシ経由で接続する HTTP オブジェクトならプロクシのポート。 そうでないなら nil。 : get( path, header = nil, dest = '' ) : get( path, header = nil ) {|str| .... } サーバ上の path にあるエンティティを取得し、dest に << メソッドを 使って書きこみます。また header が nil でなければリクエストを送る ときにその内容を HTTP ヘッダとして書きこみます。header はハッシュで、 「ヘッダ名 => 内容」のような形式でなければいけません。 返り値は、バージョン 1.1 では HTTPResponse と dest 二要素の配列です。 1.2 では HTTPResponse ただひとつのみです。 ブロックとともに呼ばれた時はエンティティボディを少しづつブロックに 与えます。 1.1 では 3xx (再試行可能なエラー)に対しても例外を発生します。この場合 HTTPResponse は例外オブジェクトから err.response で得ることができます。 一方 1.2 では全く例外を発生しません。 # version 1.1 (bundled with Ruby 1.6) response, body = http.get( '/index.html' ) # version 1.2 (bundled with Ruby 1.7 or later) response = http.get( '/index.html' ) # compatible in both version response , = http.get( '/index.html' ) response.body # using block File.open( 'save.txt', 'w' ) {|f| http.get( '/~foo/', nil ) do |str| f.write str end } # same effect File.open( 'save.txt', 'w' ) {|f| http.get '/~foo/', nil, f } : head( path, header = nil ) サーバ上の path にあるエンティティのヘッダのみを取得します。 また header が nil でなければリクエストを送るときにその内容を HTTP ヘッダとして書きこみます。header はハッシュで、 「ヘッダ名 => 内容」のような形式でなければいけません。 HTTPResponse オブジェクトを返します。 1.1 では 3xx (再試行可能なエラー)に対しても例外を発生します。この場合 HTTPResponse は例外オブジェクトから err.response で得ることができます。 一方 1.2 では全く例外を発生しません。 response = nil Net::HTTP.start( 'some.www.server', 80 ) {|http| response = http.head( '/index.html' ) } p response['content-type'] : post( path, data, header = nil, dest = '' ) : post( path, data, header = nil ) {|str| .... } サーバ上の path にあるエンティティに対し文字列 data を 送ります。レスポンスは << メソッドを使って dest に書き こまれます。header は get メソッドと同じです。 HTTPResponse オブジェクトと dest の配列を返します。 イテレータとして呼びだされたときはエンティティボディを少しづつ ブロックに与えます。 1.1 では 3xx (再試行可能なエラー)に対しても例外を発生します。この場合 HTTPResponse は例外オブジェクトから err.response で得ることができます。 一方 1.2 では全く例外を発生しません。 # version 1.1 response, body = http.post( '/cgi-bin/search.rb', 'querytype=subject&target=ruby' ) # version 1.2 response = http.post( '/cgi-bin/search.rb', 'querytype=subject&target=ruby' ) # compatible for both version response , = http.post( '/cgi-bin/search.rb', 'querytype=subject&target=ruby' ) # using block File.open( 'save.html', 'w' ) {|f| http.post( '/cgi-bin/search.rb', 'querytype=subject&target=ruby' ) do |str| f.write str end } # same effect File.open( 'save.html', 'w' ) {|f| http.post '/cgi-bin/search.rb', 'querytype=subject&target=ruby', nil, f } : get2( path, header = nil ) : get2( path, header = nil ) {|response| .... } path にあるエンティティを取得します。HTTPResponse オブジェクトを返します。 ブロックとともに呼び出されたときは、ブロック実行中は接続を 維持したまま HTTPResponse オブジェクトをブロックに渡します。 このメソッドはステータスに関らず例外を発生させません。 # example response = http.get2( '/index.html' ) p response['content-type'] puts response.body # body is already read # using block http.get2( '/index.html' ) {|response| p response['content-type'] response.read_body do |str| # read body now print str end } : post2( path, header = nil ) : post2( path, header = nil ) {|response| .... } path にあるエンティティを取得します。HTTPResponse オブジェクトを返します。 ブロックとともに呼び出されたときは、ボディを読みこむ前に HTTPResponse オブジェクトをブロックに渡します。 このメソッドはステータスに関らず例外を発生させません。 # example response = http.post2( '/cgi-bin/nice.rb', 'datadatadata...' ) p response.status puts response.body # body is already read # using block http.post2( '/cgi-bin/nice.rb', 'datadatadata...' ) {|response| p response.status p response['content-type'] response.read_body do |str| # read body now print str end } : request( request [, data] ) : request( request [, data] ) {|response| .... } リクエストオブジェクト request を送信します。POST の時は data も 与えられます。(POST 以外で data を与えると ArgumentError を発生します) ブロックとともに呼びだされたときはボディを読みこまずに HTTPResponse オブジェクトをブロックに与えます。 == class Net::HTTP::Get, Head, Post HTTP リクエストを抽象化するクラス。key はすべて大文字小文字を 区別しません。 === クラスメソッド : new HTTP リクエストオブジェクトを生成します。 === メソッド : self[ key ] key ヘッダフィールドの文字列。 key は大文字小文字を区別しません。 : self[ key ] = val key ヘッダフィールドに val をセットします。 key は大文字小文字を区別しません。 : each {|name, val| .... } ヘッダ名とその値に対するくりかえし。ヘッダ名は小文字で統一されます。 : basic_auth( account, password ) Authrization: ヘッダを basic auth 用にセットします。 : range Range: ヘッダの示す範囲を Range オブジェクトで返します。 : range = r : set_range( i, len ) 範囲を指定してエンティティを取得するためのヘッダ Range: をセットします。 r は Range オブジェクト、i, len は始点と長さです。 : content_length Content-Length: ヘッダの値 (整数)。 : content_range Content-Range: ヘッダの値 (Range)。 == class Net::HTTPResponse HTTP レスポンスのクラスです。 引数がヘッダフィールド名である場合、大文字小文字を区別しません。 === メソッド : self[ key ] key ヘッダフィールド(文字列)です。たとえばキー 'content-length' に対しては '2048' のような文字列が得られます。 key は大文字小文字を区別しません。 : self[ key ] = val key ヘッダフィールドを value に設定します。 key は大文字小文字を区別しません。 : key?( key ) key というヘッダフィールドがあれば真。 key は大文字小文字を区別しません。 : each {|name,value| .... } すべてのヘッダフィールド名とその値のペアに対するくりかえし。 : canonical_each {|name,value| .... } ヘッダフィールドの正式名とその値のペアに対して繰り返します。 : code HTTP のリザルトコードです。例えば '302' などです。 : message HTTP サーバがリザルトコードに付加して返すメッセージです。 例えば 'Not Found' などです。 : read_body( dest = '' ) エンティティボディを取得し dest に << メソッドを使って書きこみます。 同じ HTTPResponse オブジェクトに対して二回以上呼ばれた場合、 二回目からはなにもせずに一回目の返り値をそのまま返します。 : read_body {|str| .... } エンティティボディを少しづつ取得して順次ブロックに与えます。 : body エンティティボディです。read_body を呼んでいればその引数 dest、 呼んでいなければエンティティボディを文字列として読みこんで返します。 =end