Upgrade to Pro — share decks privately, control downloads, hide ads and more …

[English ver]実録 Let's build a simple Rack compatible server

[English ver]実録 Let's build a simple Rack compatible server

More Decks by Misaki Shioi(塩井美咲/しおい)

Other Decks in Programming

Transcript

  1. ʜBOEIFSFJUJT 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
  2. 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 $SFBUFBOFXTFSWFSTPDLFU "DDFQUBOJODPNJOHDPOOFDUJPO (FUBSFRVFTUNFTTBHF %JTQMBZSFRVFTUNFTTBHFUPTFSWFSTJEF 1SPWJTJPOBMSFTQPOTFNFTTBHF %JTQMBZSFTQPOTFNFTTBHFUPDMJFOUTJEF ʜBOEIFSFJUJT
  3. #VU

  4. 5IJTTFSWFSDBO`USVOBQQMJDBUJPO⚠ 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 5IFSF`TOPBQQ 4BNFNFTTBHFJTEJTQMBZFE FBDIUJNFZPVBDDFTTFE
  5. 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 )FSFJTB3BDLBQQGPSWFSJpDBUJPO app/sample.ru
  6. 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 4UBUVT‎)5510, )FBEFS‎$POUFOU5ZQFUFYUIUNM #PEZ‎EJW I)FMMPI Q5IJTBQQJTʜQ EJW app/sample.ru )FSFJTB3BDLBQQGPSWFSJpDBUJPO 8IFOZPVSVOʜ
  7. 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 *NQMFNFOUBUJPOPG)BOEMFS SFGTUIJO SFRVJSF3BDL)BOEMFS
  8. 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 5PSFHJTUFSUIFTFSWFSUP3BDL)BOEMFSNPEVMF ࢀߟɿIUUQTHJUIVCDPNNBDPVSOPZFSUIJO *NQMFNFOUBUJPOPG)BOEMFS SFGTUIJO
  9. 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 5IFNFUIPEUPTUBSUUIFTFSWFS *NQMFNFOUBUJPOPG)BOEMFS SFGTUIJO
  10. 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 4FUUIFIPTUQPSUCZFOWJSPONFOU  ˞DPOOFDUUPMPDBMIPTUCZEFGBVMU ࢀߟɿIUUQTHJUIVCDPNNBDPVSOPZFSUIJO *NQMFNFOUBUJPOPG)BOEMFS SFGTUIJO
  11. 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 "SHTUPJOJUJBMJ[FUIFTFSWFS ⚡)PTU ⚡1PSU ⚡3BDLBQQMJDBUJPO ࢀߟɿIUUQTHJUIVCDPNNBDPVSOPZFSUIJO *NQMFNFOUBUJPOPG)BOEMFS SFGTUIJO
  12. 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 *OTUBOUJBUF OFX TUBSU TUBSU  UIFTFSWFS 4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFS  ࢀߟɿIUUQTHJUIVCDPNNBDPVSOPZFSUIJO *NQMFNFOUBUJPOPG)BOEMFS SFGTUIJO
  13. 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 *NQMFNFOUBUJPOPGUIFTFSWFS0WFSBMM ʜ .PWFPSJHJOBMJNQMFNFOUBUJPOPGUIFTFSWFS UP4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFSDMBTT
  14. 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 27 end 28 end 29 end simple_rack_compatible_server.rb ʜ *OTUBOUJBUFXJUIBSHTGSPN)BOEMFS ⚡IPTU ⚡QPSU ⚡3BDLBQQMJDBUJPO "EEUIFGPMMPXJOHDIBOHFT UPUIFPSJHJOBM)551TFSWFS  4FFUIFOFYUTMJEFGPSNPSFEFUBJMTʜ *NQMFNFOUBUJPOPGUIFTFSWFS0WFSBMM
  15. 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 DIBOHFTᶄ $BMMUIF3BDLBQQMJDBUJPO BOEHFUUIFSFUVSOWBMVFT DIBOHFTᶅ (FOFSBUFBSFTQPOTFNFTTBHF GSPNUIFSFUVSOWBMVFT *NQMFNFOUBUJPOPGUIFTFSWFSTUBSU DIBOHFTᶃ 4FUUIFIPTUQPSU GSPN)BOEMFS
  16. #VU

  17. 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 8IBUTIPVME*EPʜ 8IBUBSHTEPFTUIFDBMMNFUIPEOFFE ⚠ 4PNFFOWJSPONFOUWBSJBCMFT IBWFUPCFIFSF
  18. 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 1SPWJTJPOBMMZ "OFNQUZ)BTIPCKFDU
  19. ⚡SBDLWFSTJPO‎3BDLWFSTJPO BO"SSBZPCKFDU  ⚡SBDLJOQVU‎*OQVUTUSFBN  BO*0MJLFPCKFDU  ⚡SBDLFSSPST‎&SSPSTUSFBN  BOPCKFDUSFTQPOTFUPQVUTXSJUFqVTI

     ⚡SBDLNVMUJQSPDFTT‎8IFUIFSUIFBQQMJDBUJPOJTJOWPLFE CZNVMUJQMFQSPDFTTFTTJNVMUBOFPVTMZ ⚡SBDLNVMUJUISFBE‎8IFUIFSUIFBQQMJDBUJPOJTJOWPLFE CZNVMUJQMFUISFBETJOUIFTBNFQSPDFTT BUUIFTBNFUJNF ⚡SBDLSVO@PODF‎'PSBTFSWFSCBTFEPO$(* ⚡SBDLVSM@TDIFNF‎63*TDIFNF IUUQPSIUUQT 3BDLTQFDJpDWBSJBCMFT
  20. 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 %FpOFFOWNFUIPESFGTUP3BDL-JOU %ZOBNJDBMMZHFOFSBUFEWBSJBCMFTGSPNUIFSFRVFTU PSEFGBVMUWBMVF
  21. 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 (FOFSBUFWBSJBCMFTGSPNUIFSFRVFTUNFTTBHF "EEDPEFTUPHFOFSBUFWBSJBCMFT
  22. 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‎)551NFUIPE ˏTDIFNF‎63*TDIFNF (FOFSBUFWBSJBCMFTGSPNUIFSFRVFTUNFTTBHF
  23. 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‎1BUIPGSFRVFTUFE63- !RVFSZ‎2VFSZTUSJOH (FOFSBUFWBSJBCMFTGSPNUIFSFRVFTUNFTTBHF
  24. 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‎*OQVUTUSFBN 3FRVFTUCPEZ (FOFSBUFWBSJBCMFTGSPNUIFSFRVFTUNFTTBHF
  25. 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 *BMTPBEEFEMPHTUPEJTQMBZ (FOFSBUFWBSJBCMFTGSPNUIFSFRVFTUNFTTBHF
  26. 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 )FSFUIFSFTQPOTFNFTTBHFJT 8IBU*XBTFYQFDUJOHJT [“<div><h1>Hello.</h1><p>This app is …</p></div>”] $BMMUIF3BDLBQQHFUUIFSFUVSOWBMVFT <4UBUVT \)FBEFS^ <#PEZ>>
  27. 8IBUJTJOTJEF!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
  28. 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 *U`TBOJOTUBODFPG3BDL#PEZ1SPYZ 8IBUJTJOTJEF!CPEZ
  29. 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 "OEUIJTJTXIBU*XBOU )PXDBO*HFUUIJTʜ 8IBUJTJOTJEF!CPEZ
  30. 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> 5SJFEUPDBMM!CPEZ
  31. 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> 4PGBSʜ 4IPVME*LFFQDBMMJOHVOUJM UIFSFTQPOTFCPEZJUTFMG JTSFUVSOFE CPEZ BOJOTUBODFPG3BDL-JOU  5SJFEUPDBMM!CPEZ
  32. 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 (FUSFTQPOTFCPEZVTJOHFBDINFUIPE … $BMMFBDINFUIPEUP!CPEZ BOEHFOFSBUFBO"SSBZPCKFDU $POWFSUUPBTUSJOHBUUIFFOE
  33. 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 $BMMCPEZNFUIPE … $BMMUIFCPEZNFUIPE
  34. 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 ⚡SFRVJSFTPDLFUMJCSBSZ ⚡*OJUJBMJ[FSFRVJSFEJOTUBODFWBSJBCMFT
  35. 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 ⚡1SPWJEFUIFWBSJBCMFTSFRVJSFEUPDBMMUIF3BDLBQQ
  36. 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 ⚡4UBSUMPPQJOH ⚡"DDFQUBOJODPNJOHDPOOFDUJPO ⚡$SFBUFBOFXTFSWFSTPDLFU ⚡%JTQMBZBTUBSUJOHNFTTBHF
  37. 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 ⚡(FUUIFSFRVFTUNFTTBHF ⚡(FOFSBUFWBSJBCMFTGPSDBMMJOH3BDLBQQ ⚡%JTQMBZMPHUPUIFTFSWFSTJEF
  38. 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 ⚡$BMMUIF3BDLBQQ(FUUIFSFUVSOFEWBMVFT ⚡(FOFSBUFUIFSFTQPOTFNFTTBHF GSPNUIFSFUVSOFEWBMVF0VUQVUJU ⚡$MPTFUIFTPDLFU
  39. 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