be-kan's blog

今しかできない勉強をする。

RubyでHTTPサーバを立てる①

主にこちらの内容の翻訳になります

blog.appsignal.com

また、この投稿の続きを書きました。
RubyでHTTPサーバを立てる② - be-kan's blog




内容的には、以下の4つです。

TCPサーバを立てる

TCPクライアントを作成する

・HTTPサーバを立てる

・HTTPサーバの中でRack Appを動かす

当内容、GitHubソースコードをあげています。
https://github.com/be-kan/http_server_in_ruby/blob/master/README.md


 

TCPサーバを立てる

require 'socket'
server = TCPServer.new(5678)

while session = server.accept
  session.puts "hello time is #{Time.now}"
  session.close
end

上記のコードでは、ポート5678番を開けて、クライアントから接続されるのを待っています。
クライアントから接続があると、クライアントにメッセージを送り、接続を切って次の接続を待つ、というようなコードになっています。


TCPクライアントを作成する

equire 'socket'
server = TCPSocket.new 'localhost', 5678

while line = server.gets
  puts line
end

server.close

上記のコードでは、ポート5678番に接続するクライアントを作成しています。
サーバに接続すると、先ほどのコードによりクライアントに「hello~」というメッセージが送信されており(つまりクライアントはサーバからそのメッセージを受け取り)、それを表示し、サーバとの接続を切ります。


試しにやってみましょう。

$ ruby tcp_server.rb

でサーバを立てた後、

$ ruby tcp_client.rb

とすると、メッセージが返って来るはずです!

HTTPサーバを立てる。

require 'socket'
server = TCPServer.new 5678

while session = server.accept
  request = session.gets
  puts request

  session.print "HTTP/1.1 200\r\n"
  session.print "Content-Type: text/html\r\n"
  session.print "\r\n" 
  session.print "Hello world! The time is #{Time.now}"

  session.close
end

HTTPサーバと言っても、TCPサーバとほとんど変わりません。
異なるのは、HTTPサーバではHTTPプロトコルでメッセージをやり取りする、というところです。
上記のコードでは、そのプロトコル(通信の約束事・フォーマットのようなもの)を手動で書いています。


HTTPサーバの中でRack Appを動かす

require 'socket'
require 'rack'
require 'rack/lobster'

app = Rack::Lobster.new
server = TCPServer.new 5678

while session = server.accept
  request = session.gets
  puts request

  method, full_path = request.split(' ')
  path, query = full_path.split('?')

  status, headers, body = app.call({
    'REQUEST_METHOD' => method,
    'PATH_INFO' => path,
    'QUERY_STRING' => query
  })

  session.print "HTTP/1.1 #{status}\r\n"
  
  headers.each do |key, value|
    session.print "#{key}: #{value}\r\n"
  end

  session.print "\r\n"
  
  body.each do |part|
    session.print part
  end

  session.close
end

このサーバをブラウザで開くと、以下のような画面になるはずです。

f:id:kambe3141:20180524012413p:plain

「flip!」をクリックすると、TCPサーバにリクエストが送られます。TCPサーバは、送られてきたリクエストをmethod, path, queryに分解します。
そして分解したmethodなどを、Rack Appに送り、Rack Appからstatus, headers, bodyを受け取ります。
実際に送られたパラメータの値は以下です。

{
  'REQUEST_METHOD' => 'GET',
  'PATH_INFO' => '/',
  'QUERY_STRING' => '?flip=left'
}

そして、TCPサーバは、Rackから受け取った情報を、クライアント側に送っています。



次回は、HTTPサーバの中でRailsを動かしてみたいと思います!