実録 Let's build a simple Rack compatible server

実録 Let's build a simple Rack compatible server

Transcript

  1. 9.

    ग़དྷ্͕ͬͨͷ͕ͪ͜Β 1 require ‘socket’ 2 3 server = TCPServer.new(‘localhost’, 5000)

    4 5 loop do 6 client = server.accept 7 request = client.readpartial(2048) 8 9 puts request 10 11 client.puts response <<~MESSAGE 12 HTTP/1.1 200 OK\r\n 13 Content-Type: text/plain\r\n 14 \r\n 15 Hello!\r\n 16 MESSAGE 17 end TPDLFUϥΠϒϥϦΛSFRVJSF
  2. 10.

    1 require ‘socket’ 2 3 server = TCPServer.new(‘localhost’, 5000) 4

    5 loop do 6 client = server.accept 7 request = client.readpartial(2048) 8 9 puts request 10 11 client.puts response <<~MESSAGE 12 HTTP/1.1 200 OK\r\n 13 Content-Type: text/plain\r\n 14 \r\n 15 Hello!\r\n 16 MESSAGE 17 end αʔόʔ઀ଓΛPQFO ΫϥΠΞϯτ͔Βͷ઀ଓཁٻΛड͚෇͚Δ ϦΫΤετϝοηʔδΛಡΈࠐΉ ϦΫΤετϝοηʔδΛαʔόʔଆʹग़ྗ ద౰ͳϨεϙϯεϝοηʔδ ϨεϙϯεϝοηʔδΛΫϥΠΞϯτଆʹग़ྗ ग़དྷ্͕ͬͨͷ͕ͪ͜Β
  3. 13.
  4. 14.

    ಈతͳΞϓϦέʔγϣϯʹ͸ରԠ͍ͯ͠ͳ͍⚠ 1 require ‘socket’ 2 3 server = TCPServer.new(‘localhost’, 5000)

    4 5 loop do 6 client = server.accept 7 request = client.readpartial(2048) 8 9 puts request 10 11 client.puts response <<~MESSAGE 12 HTTP/1.1 200 OK\r\n 13 Content-Type: text/plain\r\n 14 \r\n 15 Hello!\r\n 16 MESSAGE 17 end ͦ΋ͦ΋ ΞϓϦέʔγϣϯ͕ ଘࡏ͠ͳ͍ ΞΫηε͢Δͨͼɺຖճ ಉ͡Ϩεϙϯεϝοηʔδ͕ ग़ྗ͞ΕΔ
  5. 17.

    1 require ‘rack’ 2 require_relative ‘../server/simple_rack_compatible_server’ 3 4 class App

    5 def call(env) 6 [ 7 200, 8 { ‘Content-Type’ => ‘text/html’ }, 9 [“<div><h1>Hello.</h1><p>This app is running on .…</p></div>”] 10 ] 11 end 12 end 13 14 run App.new ݕূ༻ͷ3BDLΞϓϦέʔγϣϯ͕ͪ͜Β app/sample.ru
  6. 18.

    1 require ‘rack’ 2 require_relative ‘../server/simple_rack_compatible_server’ 3 4 class App

    5 def call(env) 6 [ 7 200, 8 { ‘Content-Type’ => ‘text/html’ }, 9 [“<div><h1>Hello.</h1><p>This app is running on .…</p></div>”] 10 ] 11 end 12 end 13 14 run App.new εςʔλε‎)5510, ϔομ‎$POUFOU5ZQFUFYUIUNM ϘσΟ‎EJW I)FMMPI Q5IJTBQQJTʜQ EJW ݕূ༻ͷ3BDLΞϓϦέʔγϣϯ͕ͪ͜Β app/sample.ru ࣮ߦ͢Δͱʜ
  7. 22.

    1 require ‘rack/handler’ 2 3 module Rack 4 module Handler

    5 class SimpleRackCompatibleServer 6 def self.run(app, options = {}) 7 environment = ENV[‘RACK_ENV’] || ‘development’ 8 default_host = environment == ‘development’ ? ‘localhost’ : ‘0.0.0.0’ 9 10 host = options.delete(:Host) || default_host 11 port = options.delete(:Port) || 9292 12 args = [host, port, app] 13 ::SimpleRackCompatibleServer::Server.new(*args).start 14 end 15 end 16 17 register :simple_rack_compatible_server, SimpleRackCompatibleServer 18 end 19 end ࢀߟɿIUUQTHJUIVCDPNNBDPVSOPZFSUIJO rack/handler/simple_rack_compatible_server.rb ϋϯυϥʔΛ࣮૷ ࢀߟ5IJO 3BDL)BOEMFSϞδϡʔϧΛSFRVJSF
  8. 23.

    1 require ‘rack/handler’ 2 3 module Rack 4 module Handler

    5 class SimpleRackCompatibleServer 6 def self.run(app, options = {}) 7 environment = ENV[‘RACK_ENV’] || ‘development’ 8 default_host = environment == ‘development’ ? ‘localhost’ : ‘0.0.0.0’ 9 10 host = options.delete(:Host) || default_host 11 port = options.delete(:Port) || 9292 12 args = [host, port, app] 13 ::SimpleRackCompatibleServer::Server.new(*args).start 14 end 15 end 16 17 register :simple_rack_compatible_server, SimpleRackCompatibleServer 18 end 19 end rack/handler/simple_rack_compatible_server.rb 3BDL)BOEMFSϞδϡʔϧʹαʔόʔΛొ࿥͢Δ ࢀߟɿIUUQTHJUIVCDPNNBDPVSOPZFSUIJO ϋϯυϥʔΛ࣮૷ ࢀߟ5IJO
  9. 24.

    1 require ‘rack/handler’ 2 3 module Rack 4 module Handler

    5 class SimpleRackCompatibleServer 6 def self.run(app, options = {}) 7 environment = ENV[‘RACK_ENV’] || ‘development’ 8 default_host = environment == ‘development’ ? ‘localhost’ : ‘0.0.0.0’ 9 10 host = options.delete(:Host) || default_host 11 port = options.delete(:Port) || 9292 12 args = [host, port, app] 13 ::SimpleRackCompatibleServer::Server.new(*args).start 14 end 15 end 16 17 register :simple_rack_compatible_server, SimpleRackCompatibleServer 18 end 19 end rack/handler/simple_rack_compatible_server.rb ࢀߟɿIUUQTHJUIVCDPNNBDPVSOPZFSUIJO αʔόʔΛىಈ͢Δϝιου ϋϯυϥʔΛ࣮૷ ࢀߟ5IJO
  10. 25.

    1 require ‘rack/handler’ 2 3 module Rack 4 module Handler

    5 class SimpleRackCompatibleServer 6 def self.run(app, options = {}) 7 environment = ENV[‘RACK_ENV’] || ‘development’ 8 default_host = environment == ‘development’ ? ‘localhost’ : ‘0.0.0.0’ 9 10 host = options.delete(:Host) || default_host 11 port = options.delete(:Port) || 9292 12 13 14 end 15 end 16 17 18 end 19 end rack/handler/simple_rack_compatible_server.rb ࣮ߦ؀ڥ͔Βϗετͱϙʔτ൪߸Λઃఆ͢Δ  ˞σϑΥϧτͰMPDBMIPTUʹ઀ଓ ࢀߟɿIUUQTHJUIVCDPNNBDPVSOPZFSUIJO ϋϯυϥʔΛ࣮૷ ࢀߟ5IJO
  11. 26.

    1 require ‘rack/handler’ 2 3 module Rack 4 module Handler

    5 class SimpleRackCompatibleServer 6 def self.run(app, options = {}) 7 environment = ENV[‘RACK_ENV’] || ‘development’ 8 default_host = environment == ‘development’ ? ‘localhost’ : ‘0.0.0.0’ 9 10 host = options.delete(:Host) || default_host 11 port = options.delete(:Port) || 9292 12 args = [host, port, app] 13 14 end 15 end 16 17 18 end 19 end rack/handler/simple_rack_compatible_server.rb αʔόʔʹ౉͢Ҿ਺Λ༻ҙ͢Δ ⚡ϗετ ⚡ϙʔτ൪߸ ⚡3BDLΞϓϦέʔγϣϯຊମ ࢀߟɿIUUQTHJUIVCDPNNBDPVSOPZFSUIJO ϋϯυϥʔΛ࣮૷ ࢀߟ5IJO
  12. 27.

    1 require ‘rack/handler’ 2 3 module Rack 4 module Handler

    5 class SimpleRackCompatibleServer 6 def self.run(app, options = {}) 7 environment = ENV[‘RACK_ENV’] || ‘development’ 8 default_host = environment == ‘development’ ? ‘localhost’ : ‘0.0.0.0’ 9 10 host = options.delete(:Host) || default_host 11 port = options.delete(:Port) || 9292 12 args = [host, port, app] 13 ::SimpleRackCompatibleServer::Server.new(*args).start 14 end 15 end 16 17 18 end 19 end rack/handler/simple_rack_compatible_server.rb αʔόʔ 4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFS Λ ΠϯελϯεԽ͠ OFX ɺىಈ͢Δ TUBSU  ࢀߟɿIUUQTHJUIVCDPNNBDPVSOPZFSUIJO ϋϯυϥʔΛ࣮૷ ࢀߟ5IJO
  13. 28.

    1 require ‘socket’ 2 3 module SimpleRackCompatibleServer 4 class Server

    5 def initialize(*args) 6 @host, @port, @app = args 7 end 8 9 def start 26 end 27 end 28 end simple_rack_compatible_server.rb αʔόʔΛ࣮૷શମ૾ ʜ ϋϯυϥʔ͔ΒҾ͖ܧ͍ͩ ⚡ϗετ ⚡ϙʔτ൪߸ ⚡3BDLΞϓϦέʔγϣϯຊମ ͰΠϯελϯεΛॳظԽ͢Δ ݩʑͷ)551αʔόʔͷॲཧʹ ͭͷมߋ఺Λ௥Ճ  ৄ͘͠͸࣍ͷεϥΠυ
  14. 29.

    9 def start 10 server = TCPServer.new(@host, @port) 11 12

    loop do 13 client = server.accept 14 request = client.readpartial(2048) 15 16 @status, @header, @body = @app.call 17 18 puts request 19 20 client.puts <<~MESSAGE 21 #{‘HTTP/1.1 200 OK’ if @status.eql? 200}\r\n 22 #{@header.map { |k, v| [k, v].join(’: ’) }.join(“\r\n”)}\r\n 23 \r\n 24 #{@body} 25 MESSAGE 26 end simple_rack_compatible_server.rb มߋ఺ᶄ 3BDLΞϓϦέʔγϣϯ࣮ߦ ฦΓ஋Λऔಘ͢Δ มߋ఺ᶅ ฦΓ஋͔ΒϨεϙϯεϝοηʔδΛੜ੒ αʔόʔΛ࣮૷TUBSUϝιου มߋ఺ᶃ ϋϯυϥʔ͔Β౉ͨ͠ ϗετͱϙʔτ൪߸Λઃఆ
  15. 30.
  16. 31.

    9 def start 10 server = TCPServer.new(@host, @port) 11 12

    loop do 13 client = server.accept 14 request = client.readpartial(2048) 15 16 @status, @header, @body = @app.call(???) 17 18 puts request 19 20 client.puts <<~MESSAGE 21 #{‘HTTP/1.1 200 OK’ if @status.eql? 200}\r\n 22 #{@header.map { |k, v| [k, v].join(’: ’) }.join(“\r\n”)}\r\n 23 \r\n 24 #{@body} 25 MESSAGE 26 end simple_rack_compatible_server.rb Ͳ͏͠Α͏ʜ DBMMϝιουʹ౉͢Ҿ਺͕Θ͔Βͳ͍⚠ ؀ڥม਺ΛϋογϡͷܗͰ ೖΕΔඞཁ͕͋Δ
  17. 32.

    9 def start 10 server = TCPServer.new(@host, @port) 11 12

    loop do 13 client = server.accept 14 request = client.readpartial(2048) 15 16 @status, @header, @body = @app.call({ }) 17 18 puts request 19 20 client.puts <<~MESSAGE 21 #{‘HTTP/1.1 200 OK’ if @status.eql? 200}\r\n 22 #{@header.map { |k, v| [k, v].join(’: ’) }.join(“\r\n”)}\r\n 23 \r\n 24 #{@body} 25 MESSAGE 26 end simple_rack_compatible_server.rb Θ͔Βͳ͍ͷͰ ۭϋογϡΛ ೖΕͯΈ·ͨ͠
  18. 39.

    ⚡SBDLWFSTJPO‎3BDLͷόʔδϣϯ ഑ྻ  ⚡SBDLJOQVU‎ೖྗετϦʔϜ  *0ϥΠΫͳΦϒδΣΫτ  ⚡SBDLFSSPST‎ΤϥʔετϦʔϜ  QVUTXSJUFqVTIΛݺ΂ΔΦϒδΣΫτ

     ⚡SBDLNVMUJQSPDFTT‎ΞϓϦέʔγϣϯ͕ෳ਺ͷϓϩηεʹΑͬͯ ಉ࣌ʹݺͼग़͞ΕΔ͔Ͳ͏͔ ⚡SBDLNVMUJUISFBE‎ΞϓϦέʔγϣϯ͕ ಉ͡ϓϩηε಺ͷෳ਺ͷεϨουʹΑͬͯ ಉ࣌ʹݺͼग़͞ΕΔ͔Ͳ͏͔ ⚡SBDLSVO@PODF‎ΞϓϦέʔγϣϯ͕ͦͷϓϩηεͷ࣮ߦதʹ Ұ౓͚ͩݺͼग़͞ΕΔ͔Ͳ͏͔  $(*ϕʔεͷαʔόʔͰͷΈUSVFʹͳΔ  ⚡SBDLVSM@TDIFNF‎63*εΩʔϜ IUUQPSIUUQT 3BDL؀ڥݻ༗ͷ؀ڥม਺
  19. 40.

    18 def env 19 { 20 ‘PATH_INFO’ => @path ||

    ‘/’, 21 ‘QUERY_STRING’ => @query || ‘’, 22 ‘METHOD’ => @method || ‘GET’, 23 ‘SERVER_NAME’ => ‘simple_rack_compatible_server’, 24 ‘SERVER_PORT’ => @port.to_s, 25 ‘rack.version’ => Rack::VERSION, 26 ‘rack.input’ => StringIO.new(@input || ‘’).set_encoding(‘ASCII_8BIT’), 27 ‘rack.errors’ => $stderr, 28 ‘rack.multiprocess’ => false, 29 ‘rack.multithread’ => false, 30 ‘rack.run_once’ => false, 31 ‘rack.url_scheme’ => @scheme&.downcase&.slice(/http[a-z]*/) || ‘http’ 32 } 33 end simple_rack_compatible_server.rb 3BDL-JOUΛࢀߟʹ؀ڥม਺Λઃఆ ϦΫΤετ͔Βಈతʹੜ੒ͨ͠؀ڥม਺ PSσϑΥϧτ஋
  20. 41.

    35 def start 36 server = TCPServer.new(@host, @port) 37 38

    loop do 39 client = server.accept 40 41 request = client.readpartial(2048).split(“\r\n”) 42 @method, path, @scheme = request.first.split 43 @path, @query = path.split(‘?’) 44 @input = request.index(‘’) ? request[request.index(‘’) + 1] : ‘’ 45 46 puts “Received request message: #{@method} #{@path} #{@scheme}” 47 48 @status, @header, @body = @app.call(env) 49 50 client.puts <<~MESSAGE 51 # … simple_rack_compatible_server.rb ϦΫΤετϝοηʔδ͔Β؀ڥม਺Λੜ੒ ؀ڥม਺Λੜ੒͢ΔίʔυΛ௥Ճ
  21. 42.

    35 def start 36 server = TCPServer.new(@host, @port) 37 38

    loop do 39 client = server.accept 40 41 request = client.readpartial(2048).split(“\r\n”) 42 @method, path, @scheme = request.first.split 43 44 45 46 47 48 49 50 51 simple_rack_compatible_server.rb !NFUIPE‎)551ϝιου ˏTDIFNB‎63*εΩʔϜ ϦΫΤετϝοηʔδ͔Β؀ڥม਺Λੜ੒
  22. 43.

    35 def start 36 server = TCPServer.new(@host, @port) 37 38

    loop do 39 client = server.accept 40 41 request = client.readpartial(2048).split(“\r\n”) 42 @method, path, @scheme = request.first.split 43 @path, @query = path.split(‘?’) 44 45 46 47 48 49 50 51 simple_rack_compatible_server.rb !QBUI‎ϦΫΤετ63-ͷύε !RVFSZ‎ΫΤϦจࣈྻ ϦΫΤετϝοηʔδ͔Β؀ڥม਺Λੜ੒
  23. 44.

    35 def start 36 server = TCPServer.new(@host, @port) 37 38

    loop do 39 client = server.accept 40 41 request = client.readpartial(2048).split(“\r\n”) 42 @method, path, @scheme = request.first.split 43 @path, @query = path.split(‘?’) 44 @input = request.index(‘’) ? request[request.index(‘’) + 1] : ‘’ 45 46 47 48 49 50 51 simple_rack_compatible_server.rb !JOQVU‎ೖྗετϦʔϜ ϦΫΤετϘσΟ ϦΫΤετϝοηʔδ͔Β؀ڥม਺Λੜ੒
  24. 45.

    35 def start 36 server = TCPServer.new(@host, @port) 37 38

    loop do 39 client = server.accept 40 41 request = client.readpartial(2048).split(“\r\n”) 42 @method, path, @scheme = request.first.split 43 @path, @query = path.split(‘?’) 44 @input = request.index(‘’) ? request[request.index(‘’) + 1] : ‘’ 45 46 puts “Received request message: #{@method} #{@path} #{@scheme}” 47 48 49 50 51 simple_rack_compatible_server.rb ͔ͤͬ͘ͳͷͰϩά ΋ग़ྗ ϦΫΤετϝοηʔδ͔Β؀ڥม਺Λੜ੒
  25. 52.

    35 def start 36 server = TCPServer.new(@host, @port) 37 38

    loop do … 47 48 @status, @header, @body = @app.call(env) 49 50 client.puts <<~MESSAGE 51 #{‘HTTP/1.1 200 OK’ if @status.eql? 200}\r\n 52 #{@header.map { |k, v| [k, v].join(’: ’) }.join(“\r\n”)}\r\n 53 \r\n 54 #{@body} 55 MESSAGE 56 end 57 end simple_rack_compatible_server.rb Ϩεϙϯεϝοηʔδ͸Ͳ͏ͳ͍ͬͯΔʁ ཧ૝ͷϨεϙϯεϘσΟ͸ [“<div><h1>Hello.</h1><p>This app is …</p></div>”] 3BDLΞϓϦέʔγϣϯΛ࣮ߦͯ͠ฦΓ஋Λऔಘ ‎<εςʔλείʔυ \ϔομ^ <ϘσΟ>>
  26. 53.

    !CPEZͷத਎͸Ͳ͏ͳ͍ͬͯΔʁ JSC 4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFSYʜ QQ!CPEZ 3BDL#PEZ1SPYZYʜ !CMPDL 1SPDYʜ!ʜSBDLMJCSBDLDPNNPO@MPHHFSSC  !CPEZ 3BDL-JOUYʜ

    !BQQ 3BDL5FNQpMF3FBQFSYʜ!BQQ"QQYʜ  !CPEZ 3BDL#PEZ1SPYZYʜ !CMPDL 1SPDYʜ!ʜSBDLMJCSBDLUFNQpMF@SFBQFSSC  !CPEZ <lEJWI)FMMPIQ5IJTBQQJTSVOOJOHPOʜQEJWz>  !DMPTFEGBMTF
  27. 54.

    !CPEZͷத਎͸Ͳ͏ͳ͍ͬͯΔʁ JSC 4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFSYʜ QQ!CPEZ 3BDL#PEZ1SPYZYʜ !CMPDL 1SPDYʜ!ʜSBDLMJCSBDLDPNNPO@MPHHFSSC  !CPEZ 3BDL-JOUYʜ

    !BQQ 3BDL5FNQpMF3FBQFSYʜ!BQQ"QQYʜ  !CPEZ 3BDL#PEZ1SPYZYʜ !CMPDL 1SPDYʜ!ʜSBDLMJCSBDLUFNQpMF@SFBQFSSC  !CPEZ <lEJWI)FMMPIQ5IJTBQQJTSVOOJOHʜQEJWz>  !DMPTFEGBMTF 3BDL#PEZ1SPYZͷΠϯελϯεʂ
  28. 55.

    JSC 4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFSYʜ QQ!CPEZ 3BDL#PEZ1SPYZYʜ !CMPDL 1SPDYʜ!ʜSBDLMJCSBDLDPNNPO@MPHHFSSC  !CPEZ 3BDL-JOUYʜ !BQQ

    3BDL5FNQpMF3FBQFSYʜ!BQQ"QQYʜ  !CPEZ 3BDL#PEZ1SPYZYʜ !CMPDL 1SPDYʜ!ʜSBDLMJCSBDLUFNQpMF@SFBQFSSC  !CPEZ <lEJWI)FMMPIQ5IJTBQQJTʜQEJWz>  !DMPTFEGBMTF ͋Δ औΓग़͠ํ͕Θ͔Βͳ͍ʜ  !CPEZͷத਎͸Ͳ͏ͳ͍ͬͯΔʁ
  29. 56.

    !CPEZΛDBMMͯ͠Έ·ͨ͠ JSC 4JNQMF3BDL$PNQBUJCMF4FSWFSTFSWʜ QQ!CPEZDBMM FOW  <  \$POUFOU5ZQFUFYUIUNM^ 

    3BDL-JOUYʜ !BQQ 3BDL5FNQpMF3FBQFSYʜ!BQQ"QQYʜ  !CPEZ 3BDL#PEZ1SPYZYʜ !CMPDL 1SPDYʜ!ʜSBDLMJCSBDLUFNQpMF@SFBQFSSC  !CPEZ <EJWI)FMMPIQ5IJTBQQJTʜQEJW>  !DMPTFEGBMTF  !DPOUFOU@MFOHUIOJM  !IFBE@SFRVFTUGBMTF>
  30. 57.

    !CPEZΛDBMMͯ͠Έ·ͨ͠ JSC 4JNQMF3BDL$PNQBUJCMF4FSWFSTFSWFʜ QQ!CPEZDBMM FOW  <  \$POUFOU5ZQFUFYUIUNM^ 

    3BDL-JOUYʜ !BQQ 3BDL5FNQpMF3FBQFSYʜ!BQQ"QQYʜ  !CPEZ 3BDL#PEZ1SPYZYʜ !CMPDL 1SPDYʜ!ʜSBDLMJCSBDLUFNQpMF@SFBQFSSC  !CPEZ <lEJWI)FMMPIQ5IJTBQQJTʜQEJWz>  !DMPTFEGBMTF  !DPOUFOU@MFOHUIOJM  !IFBE@SFRVFTUGBMTF> ԕ͍ʜ ϨεϙϯεϘσΟͦͷ΋ͷ͕ औಘͰ͖ΔΑ͏ʹͳΔ·Ͱ ԆʑDBMM͠ଓ͚Δ͔͠ͳ͍ʜʁʁ ϘσΟ 3BDL-JOUͷΠϯελϯε 
  31. 61.

    1 require ‘socket’ 2 3 module SimpleRackCompatibleServer 4 class Server

    69 def body 70 res_body = [] 71 @body.each { |body| res_body << body } 72 res_body.join(“\n”) 73 end 74 end 75 end simple_rack_compatible_server.rb FBDIΛ࢖ͬͯϨεϙϯεϘσΟΛऔΓग़͢ … !CPEZʹFBDIΛݺͼ഑ྻͱͯ͠୅ೖ͠௚͢ ࠷ޙʹจࣈྻʹ௚͢
  32. 62.

    35 def start 48 @status, @header, @body = @app.call(env) 49

    50 client.puts <<~MESSAGE 51 #{‘HTTP/1.1 200 OK’ if @status.eql? 200}\r\n 52 #{@header.map { |k, v| [k, v].join(’: ’) }.join(“\r\n”)}\r\n 53 \r\n 54 #{body} 55 MESSAGE 56 end 57 end simple_rack_compatible_server.rb ϨεϙϯεϘσΟΛݺͼग़͢ … CPEZϝιουΛݺͿ
  33. 67.

    1 require ‘socket’ 2 3 module SimpleRackCompatibleServer 4 class Server

    5 def initialize(*args) 6 @host, @port, @app = args 7 @method = nil 8 @path = nil 9 @scheme = nil 10 @query = nil 11 @input = nil 12 @status = nil 13 @header = nil 14 @body = nil 15 end simple_rack_compatible_server.rb 4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFSJOJUJBMJ[F ⚡TPDLFUϥΠϒϥϦΛSFRVJSF ⚡ඞཁͳΠϯελϯεม਺ΛॳظԽ
  34. 68.

    18 def env 19 { 20 ‘PATH_INFO’ => @path ||

    ‘/’, 21 ‘QUERY_STRING’ => @query || ‘’, 22 ‘METHOD’ => @method || ‘GET’, 23 ‘SERVER_NAME’ => ‘simple_rack_campatible_server’, 24 ‘SERVER_PORT’ => @port.to_s, 25 ‘rack.version’ => Rack::VERSION, 26 ‘rack.input’ => StringIO.new(@input || ‘’).set_encoding(‘ASCII_8BIT’), 27 ‘rack.errors’ => $stderr, 28 ‘rack.multiprocess’ => false, 29 ‘rack.multithread’ => false, 30 ‘rack.run_once’ => false, 31 ‘rack.url_scheme’ => @scheme&.downcase&.slice(/http[a-z]*/) || ‘http’ 32 } 33 end simple_rack_compatible_server.rb 4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFSFOW ⚡3BDLΞϓϦέʔγϣϯͷ࣮ߦʹඞཁͳ؀ڥม਺Λ༻ҙ
  35. 69.

    35 def start 36 server = TCPServer.new(@host, @port) 37 38

    puts <<~MESSAGE 39 #{@app} is running on #{@host}: #{@port} 40 => Use Ctrl-C to stop 41 MESSAGE 42 43 loop do 44 client = server.accept 60 end 61 end simple_rack_compatible_server.rb … 4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFSTUBSU ⚡ϧʔϓॲཧΛ։࢝͢Δ ⚡ΫϥΠΞϯτ͔Βͷ઀ଓཁٻΛड͚෇͚Δ ⚡αʔόʔ઀ଓΛ։࢝͢Δ ⚡։࢝ϝοηʔδΛग़ྗ͢Δ
  36. 70.

    46 begin 47 request = client.readpartial(2048).split(“\r\n”) 48 @method, path, @scheme

    = request.first.split 49 @path, @query = path.split(‘?’) 50 @input = request.index(‘’) ? request[request.index(‘’) + 1] : ‘’ 51 52 puts “Received request message: #{@method} #{@path} #{@schema}” 53 54 55 56 57 58 59 end simple_rack_compatible_server.rb 4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFSTUBSU ⚡ϦΫΤετϝοηʔδΛಡΈࠐΉ ⚡3BDLΞϓϦέʔγϣϯͷ࣮ߦʹඞཁͳ؀ڥม਺Λੜ੒͢Δ ⚡αʔόʔʹϩάΛग़ྗ͢Δ
  37. 71.

    46 begin 47 48 49 50 51 52 53 54

    @status, @header, @body = @app.call(env) 55 56 client.puts [status, header, ‘’, body].join(“\r\n”) 57 ensure 58 client.close 59 end simple_rack_compatible_server.rb 4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFSTUBSU ⚡3BDLΞϓϦέʔγϣϯΛ࣮ߦ͠ɺฦΓ஋Λऔಘ͢Δ ⚡ฦΓ஋͔ΒϨεϙϯεϝοηʔδΛੜ੒͠ɺग़ྗ͢Δ ⚡ιέοτΛด͡Δ
  38. 72.

    46 begin 47 48 49 50 51 52 53 54

    55 56 client.puts [status, header, ‘’, body].join(“\r\n”) 57 ensure 58 client.close 59 end simple_rack_compatible_server.rb 4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFSTUBSU 67 def status 68 case @status 69 when 200 70 “#{@schema} 200 OK” 82 def header 83 @header.map { |k, v| [k, v].join(’: ’) }.join(“\r\n”) 84 end 86 def body 87 res_body = [] 88 @body.each { |body| res_body << body } 89 res_body.join(“\n”) 90 end