HTTPクライアントの実装
Webを支える技術を読んでいます。
Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)
- 作者: 山本陽平
- 出版社/メーカー: 技術評論社
- 発売日: 2010/04/08
- メディア: 単行本(ソフトカバー)
- 購入: 143人 クリック: 4,320回
- この商品を含むブログ (181件) を見る
Webエンジニアなら知ってて当然の基礎の基礎が載っている本です。
この前基礎の基礎を聞かれた時ハッキリと答えられなくて悔しかったので読んでいます。
今回はhttpリクエスト周りです。
httpリクエスト投げるコード書いた
オブジェクト指向っぽく書きました。(書いたつもりです)
optionsメソッド投げて返ってきたAllowed Methodから動的にメソッドを生成すると面白そうですね。
optionsメソッドをそもそも受け付けないサーバーがあるからキツそうですけど・・・
require 'socket' class HttpClient attr_accessor :uri, :port, :path def initialize(uri, path, port) @uri = uri @path = path @port = port #@socket = TCPSocket.open(uri, port) end [:get, :post, :put, :delete, :head, :options].each do |method| define_method(method) do |content = nil, type = "text/plain"| @socket = TCPSocket.open(uri, port) #修正 : ソケットのopenを各メソッドに任せる。 @socket << "#{method.to_s.swapcase} #{self.path} HTTP/1.1\r\n" @socket << "Host: #{self.uri}\r\n" @socket << "Content-Type: #{type}; charset=utf-8\r\n" unless content.nil? @socket << "Content-Length: #{content.length}\r\n" @socket << "\r\n#{content}" end @socket << "Connection: close\r\n" @socket << "\r\n" puts @socket.read @socket.close end end end HttpClient.new("example.com", "/", 80).get HttpClient.new("example.com", "/", 80).post("こんにちは") HttpClient.new("example.com", "/", 80).options
各ヘッダーの意味
Host: #{ホスト名}
このホストにリクエスト投げるぞという意味です。Content-Type: #{タイプ}; charset=utf-8
文字コードとタイプの指定です。ここからはMIMEコード(メディアタイプ)の指定です。Content-Length:
その名の通りメッセージのサイズです。
最初Content-Lengthヘッダーを付けずにexample.comにpost投げつけたら以下のメッセージが返ってきました。
HTTP/1.0 411 Length Required Content-Type: text/html Content-Length: 357 Connection: close Date: Fri, 29 Apr 2016 09:52:50 GMT Server: ECSF (pae/3788)
Content-Length付けてリクエスト送信すると正常にレスポンスが返ってきました
HTTP/1.0 200 OK Accept-Ranges: bytes Cache-Control: max-age=604800 Content-Type: text/html Date: Fri, 29 Apr 2016 09:55:32 GMT Etag: "359670651" Expires: Fri, 06 May 2016 09:55:32 GMT Last-Modified: Fri, 09 Aug 2013 23:54:35 GMT Server: EOS (lax004/2816) Content-Length: 1270 Connection: close
405 Not Allowedが返ってくると思ったんですがちゃんとpostされてますね。空を切っている感。
HTTP/1.0とHTTP/1.1の違い
最初HTTP/1.1でレスポンスが返ってくるのが遅くて困っていました。
調べると以下のヘッダーが足りなかったみたいです。
Connection: close
Connectionヘッダーについて
HTTP/1.0とHTTP/1.1で変わった点に接続の継続性があります。これを表すのがConnectionヘッダーになります。具体的には、
Connection: keep-aliveにすると繋ぎっぱなしになり、 Connection: closeにするとTCPコネクションが閉じます。
HTTP/1.0では要求ごとに接続されていたのですが、HTTP/1.1ではコネクションを閉じない限り接続が続きます。つまりデフォルトでkeep-aliveになりました。
つまり、タイムアウトになるまでTCPコネクション繋ぎっぱなしにしていたことがレスポンスが遅かった原因です。
Connection: closeを書いていないリクエストのレスポンスにはConnection: closeが含まれていません。コネクションはサーバーアプリケーションが切ったようです。
HTTP/1.1 200 OK Allow: OPTIONS, GET, HEAD, POST Cache-Control: max-age=604800 Date: Fri, 29 Apr 2016 11:43:16 GMT Expires: Fri, 06 May 2016 11:43:16 GMT Server: EOS (lax004/280C) x-ec-custom-error: 1 Content-Length: 0
チャンクやキャッシュは次回にします。
参考
http://www.cresc.co.jp/tech/java/Servlet_Tutorial/Lesson_36.htm