Note

3年後の自分のために書いています

実装から学ぶ HTTP 通信 〜 Ruby 標準ライブラリ編〜

社内勉強会のコピペ。


HTTP とは

HTML など をやり取りする時の決まりごと

Web は URL で指定した HTML など を HTTP という決まりごとに沿ってやり取りしている

詳しくは Webを支える技術 という本に書いてあります

今日話すこと

  • Ruby の標準ライブラリで HTTP 通信がどう実装されているかをコードリーディングしながら見ていきます(Ruby の話が若干多めかも?)

今日話さないこと

登場する標準ライブラリ

先に結論

HTTP 通信は実装的にはネットワーク越しに(ソケットを通して?)ファイルの読み書きをしているだけ!

たとえばこんなコード

require 'webrick'

srv = WEBrick::HTTPServer.new({ :DocumentRoot => './',
                                :BindAddress => '127.0.0.1',
                                :Port => 20080})
srv.mount('/', WEBrick::HTTPServlet::FileHandler, 'index.html')
trap("INT"){ srv.shutdown }
srv.start
<div>
  Hello!
</div>
require 'net/http'
require 'uri'

uri = URI.parse('http://localhost:20080/')
puts Net::HTTP.get(uri)

実行するとこうなります

$ ruby http_server.rb
[2019-03-22 07:40:24] INFO  WEBrick 1.4.2
[2019-03-22 07:40:24] INFO  ruby 2.5.3 (2018-10-18) [x86_64-darwin18]
[2019-03-22 07:40:24] INFO  WEBrick::HTTPServer#start: pid=1786 port=20080

$ ruby http_client.rb
<div>
  Hello!
</div>

この時何が起きているか、実装を覗いてみる。

Webrick サーバ起動まで@webrick

URI のパース@uri

HTTP クライアントが TCP コネクションを開くとこまで@nethttp

HTTP (GET) リクエスト送信まで@nethttp

HTTP リクエストのパースまで@webrick

HTTP レスポンスの作成まで@webrick

HTTP クライアントでレスポンスを表示するまで@nethttp

  • HTTP#transport_request に戻って HTTPResponse.read_new とかでレスポンスを読み込む
  • 読み込まれたレスポンスがいろいろ通って HTTP.get の中の #get_response の返り値としてもどってきて、その body を取り出している…!!!

結論

HTTP 通信は実装的にはネットワーク越しに(ソケットを通して?)ファイルの読み書きをしているだけ!