From: "NAKAMURA, Hiroshi" Date: 1999-06-08T11:51:06+09:00 Subject: [ruby-list:14907] Re: HTTP Client with Ruby なひです. > From: TAKAHASHI Masayoshi [mailto:maki@inac.co.jp] > Sent: Tuesday, June 08, 1999 12:19 AM > > HTTP/1.1 だと Host ヘッダが使えるのは大きいと思うです。 > > えっと、クライアントがHTTP/1.0のリクエストを送っても、Hostヘッダに > 対応したサーバならちゃんとHostヘッダみてくれませんか? 実装依存ですが,見てくれそうな気がしますね. HTTP/1.0(RFC1945)には,Hostフィールドについての記述がないので... どこ見たらいいのやら. RFC2068にも記述はなさそうだし(アタリマエか...^^; えーと,結局なひは, 「Hostヘッダが使えるのは大きい」の意味がわかってないような気がします. > > テスト環境がない(未だにHTTP/1.0のサイトってどこだろう ^^;) > > biglobeです……。 > # たとえば、 http://www2c.biglobe.ne.jp/~hosoda/ とか(^^; おー,びぐろーぶさん.Netscape-Commerce/1.1か... 数年前に一部システムづくりの お手伝いした頃から,ウェブサーバ変わってないかも.^^; ということで,テスト環境が見つかったので, http-access-0.0.1のPatch作ってみました. ただしhttp-access.rb本体と,url-parse.rbだけです. wbrowser等はチェックしてません. # 状態遷移は...これでいいのかな...自信なし. ヘッダ区切りがCRLFでなくLFのみ,というサーバに対応しちゃってますが, この部分は不要かもしれません. 正しいヘッダを誤って解釈する可能性があります. > # 素直に青山さんのコード借りれば良かったかしらん(^^;; 用途限定なら,その方がいいかもしれませんね.^^; / / / diff -ur http-access-0.0.1.dist/http-access.rb http-access-0.0.1/http-access.rb --- http-access-0.0.1.dist/http-access.rb Wed Mar 3 16:23:02 1999 +++ http-access-0.0.1/http-access.rb Tue Jun 8 11:34:55 1999 @@ -29,7 +29,7 @@ def initialize(host, port=HTTP_Port, proxy=nil) @host = host - @port = port + @port = port || HTTP_Port @state = :INIT @requests = [] @uagent = format("HTTPAccess/0.0.1 (%s; %s)", @@ -54,8 +54,8 @@ header = {} unless header.kind_of? Hash header['Host'] = @host unless header['Host'] header['User-Agent'] = @uagent unless header['User-Agent'] - #header['Connection'] = 'Keep-Alive' unless header['Connection'] - #header['Accept'] = '*/*' unless header['Accept'] + header['Connection'] = 'Keep-Alive' unless header['Connection'] + header['Accept'] = '*/*' unless header['Accept'] header.each {|k, v| @socket.putheader(k, v) } @@ -97,8 +97,8 @@ req = @requests.shift - @status_line = @socket.gets("\r\n") - unless /(HTTP\/1\.\d+)\s+(\d\d\d)\s+(.*)/ =~ @status_line + @status_line = @socket.gets + unless /^(HTTP\/1\.\d+)\s+(\d\d\d)\s+(.*)\r?$/ =~ @status_line raise HTTPBadResponse end @http_version = $1 @@ -107,7 +107,7 @@ @next_connection = true if @http_version == 'HTTP/1.1' @headers = [] - until (line = @socket.gets("\r\n")) == "\r\n" + until (line = @socket.gets) =~ /^\r?$/ if line == /^\s/ @headers[-1] << line else @@ -117,6 +117,7 @@ @content_length = nil @chunked = false + @next_connection = false @headers.each {|line| case line when /^Content-Length:\s+(\d+)/i @@ -139,6 +140,11 @@ @state = :DATA if req[0] == 'HEAD' @content_length = 0 + if @next_connection + @state = :WAIT + else + close + end end @next_connection = false unless @content_length @@ -148,7 +154,7 @@ def get_header(&block) get_response if @state == :META - raise HTTPInvalidState, 'state != DATA' unless @state == :DATA + #raise HTTPInvalidState, 'state != DATA' unless @state == :DATA if block @headers.each {|line| block.call(line) @@ -179,6 +185,11 @@ else read_body(maxbytes) end + if @next_connection + @state = :WAIT + else + close + end end def read_body(maxbytes=nil) @@ -254,11 +265,22 @@ url = URL.new(urlstr) #exit - h = HTTPAccess.new(url.netloc) + h = HTTPAccess.new(url.host, url.port) + h.request_head(url.path) + h.get_response + h.get_header {|line| p line} + # h.request_head(url.path) + h.get_response + h.get_header {|line| p line} + # h.request_get(url.path, 'User-Agent'=>'FooBar/1.0') h.get_response h.get_header {|line| p line} + h.get_data(8192) {|data| p data} + # + h.request_get(url.path, 'User-Agent'=>'FooBar/1.0') h.get_response + h.get_header {|line| p line} h.get_data(8192) {|data| p data} end diff -ur http-access-0.0.1.dist/url-parse.rb http-access-0.0.1/url-parse.rb --- http-access-0.0.1.dist/url-parse.rb Wed Mar 3 16:20:08 1999 +++ http-access-0.0.1/url-parse.rb Tue Jun 8 10:17:41 1999 @@ -1,6 +1,6 @@ # Parse URLs. class URL - attr_reader :urlstr, :scheme, :netloc, :path, :params, :query, :fragment + attr_reader :urlstr, :scheme, :netloc, :host, :port, :path, :params, :query, :fragment Uses_netloc = ['ftp', 'http', 'gopher', 'nntp', 'telnet', 'wais', 'https', 'shttp', 'snews', 'prospero', ''] @@ -14,15 +14,20 @@ # [scheme]://[netloc]/[path];[params]?[query]#[fragment] def parse(url, scheme = nil, allow_fragments = true) @scheme = scheme - @netloc = @params = @query = @fragment = nil + @netloc = @host = @port = @params = @query = @fragment = nil if url =~ /^([-+\.\w]+):/ @scheme, url = $1, $' #' end if url =~ /^(\/\/)?([^\/]+)/ && Uses_netloc.include?(@scheme) - # //[netloc] + # //[netloc] a.k.a. hostport ::= host [ : port ] in RFC1630 @netloc, url = $2, $' #' + if @netloc =~ /^([^:]+):(\d*)$/ # Is this valid like 'http://foo:/bar'? + @host, @port = $1, $2 + else + @host = @netloc + end elsif url =~ /^(\/|~)/ @scheme = 'file' else