Slide 1

Slide 1 text

.JTBLJ4IJPJ!DPF@ 'FC 0FEP3VCZ,BJHJ ࣮࿥ -FU`TCVJMEBTJNQMF 3BDLDPNQBUJCMFTFSWFS⚡⚡⚡

Slide 2

Slide 2 text

"CPVUNF .JTBLJ4IJPJ ͓͍͠ !DPF@ ⚡8FCQSPHSBNNFS ⚡#FMPOHTUP"TBLVTBSC 5BNBSC 'VLVPLBSC ⚡*UTCFFOZFBSBOEBIBMG TJODF*KPJOFE"TBLVTBSCNFFUVQGPSUIFpSTUUJNF ⚡#VJMUBXFCTFSWFSSFDFOUMZ

Slide 3

Slide 3 text

.JTBLJ4IJPJ ͓͍͠ !DPF@ ⚡8FCQSPHSBNNFS ⚡#FMPOHTUP"TBLVTBSC 5BNBSC 'VLVPLBSC ⚡*UTCFFOZFBSBOEBIBMG TJODF*KPJOFE"TBLVTBSCNFFUVQGPSUIFpSTUUJNF ⚡#VJMUBXFCTFSWFSSFDFOUMZ "CPVUNF ‐5PEBZ`TUIFNF

Slide 4

Slide 4 text

BU 3VCZ$POG/BTIWJMMF /PWFNCFS

Slide 5

Slide 5 text

l-FU`TCVJMEBTJNQMF)551TFSWFSz XIJDIJTBWFSZJOUFSFTUJOHUBML CZ&45)&30-"56/%&!FTUIFS ग़యɿIUUQTOPUJTUFTUIFSD(V(+MFUTCVJMEBTJNQMFIUUQTFSWFSXJUISVCZ

Slide 6

Slide 6 text

ʜJTJOUSPEVDFECZ!JHBJHB`TUXFFU ग़యɿIUUQTUXJUUFSDPNJHBJHBTUBUVT T

Slide 7

Slide 7 text

ʜJTJOUSPEVDFECZ!VE[VSB GSPN'VLVPLBSC CZUXFFU UPNF ग़యɿIUUQTUXJUUFSDPNVE[VSBTUBUVT T ˞NF

Slide 8

Slide 8 text

4P XJUIUIFSFGFSFODFUPUIFTMJEF *CVJMUBTJNQMF)551TFSWFS

Slide 9

Slide 9 text

ʜ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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

DVSMMPDBMIPTU )PTU1PSUXIJDIBSFPQFOFE

Slide 12

Slide 12 text

*UXPSLT POTFSWFSTJEF PODMJFOUTJEF 3FRVFTUNFTTBHF JTEJTQMBZFE 3FTQPOTFCPEZ JTEJTQMBZFE

Slide 13

Slide 13 text

#VU

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

*EMJLFUPNBLFUIJTTFSWFS 3BDLDPNQBUJCMF

Slide 16

Slide 16 text

4P *USJFEUPCVJME BTJNQMF3BDLDPNQBUJCMFTFSWFS XIJDIJTOBNFE 4JNQMF3BDL$PNQBUJCMF4FSWFS

Slide 17

Slide 17 text

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 [“

Hello.

This app is running on .…

”] 10 ] 11 end 12 end 13 14 run App.new )FSFJTB3BDLBQQGPSWFSJpDBUJPO app/sample.ru

Slide 18

Slide 18 text

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 [“

Hello.

This app is running on .…

”] 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ʜ

Slide 19

Slide 19 text

)PX3BDLBQQMJDBUJPOTUBSUT 6TFSFYFDVUFTSBDLVQ )BOEMFSJTDBMMFE 4FSWFSJTSFHJTUFSFEUP)BOEMFS 4FSWFSTUBSUTUPSVO )BOEMFSTUBSUT4FSWFS 5IFTFSWFS DPOOFDUFEUP3BDL 4FSWFSSVOT3BDLBQQ 4UBSU 4FSWFSDBMMT3BDLBQQ

Slide 20

Slide 20 text

JOUIFTFSWFS JO3BDL)BOEMFSNPEVMF JOUIFTFSWFS JO3BDL 6TFSFYFDVUFTSBDLVQ )BOEMFSJTDBMMFE 4FSWFSJTSFHJTUFSFEUP)BOEMFS 4FSWFSTUBSUTUPSVO )BOEMFSTUBSUT4FSWFS 4FSWFSDBMMT3BDLBQQ )PX3BDLBQQMJDBUJPOTUBSUT

Slide 21

Slide 21 text

3FRVJSFNFOUPG3BDLDPNQBUJCMFTFSWFS *UIPVHIUBCPVUUIFSFRVJSFNFOUTGPSUIFTFSWFS CBTFEPOIPX3BDLBQQTUBSUT ᶃ)BOEMFS 3BDL)BOEMFS4JNQMF3BDL$PNQBUJCMF4FSWFS ⚡5PSFHJTUFSUIFTFSWFSUP3BDL)BOEMFSNPEVMF ⚡5PTUBSUUIFTFSWFS ᶄ4FSWFS 4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFS ⚡5PSFDFJWFBSFRVFTUNFTTBHF ⚡5PDBMM3BDLBQQMJDBUJPO ⚡5PSFUVSOBSFTQPOTFNFTTBHF

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

#VU

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

SBDLVQTTJNQMF@SBDL@DPNQBUJCMF@TFSWFS "OZXBZʜ

Slide 35

Slide 35 text

‎(PUMPUTPGFSSPST ☠☠☠

Slide 36

Slide 36 text

*UTFFNTUIFSF`SFSFRVJSFEWBSJBCMFT FOWNJTTJOHSFRVJSFELFZ3&26&45@.&5)0% 3BDL-JOU-JOU&SSPS

Slide 37

Slide 37 text

rack/lib/rack/lint.rb 4FF3BDL-JOUDMBTT

Slide 38

Slide 38 text

rack/lib/rack/lint.rb &YQMBOBUJPOTBCPVUSFRVJSFEWBSJBCMFT ʜ 4FF3BDL-JOUDMBTT

Slide 39

Slide 39 text

⚡1"5)@*/'0‎1BUIPGSFRVFTUFE63- ⚡26&3:@453*/(‎2VFSZTUSJOH ⚡.&5)0%‎)551NFUIPE ⚡4&37&3@/".&‎5PCVJMEB63-XJUI 4$3*15@/".&1"5)@*/'0 ⚡4&37&3@1035‎5PCVJMEB63-XJUI 4$3*15@/".&1"5)@*/'0 7BSJBCMFTEFpOFEJO1&1 1&1‎1ZUIPO8FC4FSWFS(BUFXBZ*OUFSGBDFW IUUQTXXXQZUIPOPSHEFWQFQTQFQ

Slide 40

Slide 40 text

⚡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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

SBDLVQTTJNQMF@SBDL@DPNQBUJCMF@TFSWFS "HBJOʜ

Slide 48

Slide 48 text

‎*UXPSLT 3FDFJWFESFRVFTUNFTTBHF(&5)551 3BDL-JOU-JOU&SSPSFSSPSDMFBSFE BOEMPHTBSFEJTQMBZFE BUNZUFSNJOBM

Slide 49

Slide 49 text

BU%FW5PPMTPGNZCSPXTFS 4UBUVTDPEFBOE)FBEFSSFUVSOFEGSPN3BDLBQQ BSFTVDDFTTGVMMZPVUQVUUPUIFDMJFOUTJEF )FBEFS $POUFOU5ZQFUFYUIUNM 4UBUVTDPEF

Slide 50

Slide 50 text

"OEUIFSFTQPOTFCPEZJTʜ

Slide 51

Slide 51 text

"OEUIFSFTQPOTFCPEZJTʜ

Slide 52

Slide 52 text

4PNFUIJOH`TXSPOH 0, /( SBDLCPEZQSPYZ %0.TIPVMECFHFOFSBUFE GSPNSFTQPOTFCPEZ

Slide 53

Slide 53 text

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 [“

Hello.

This app is …

”] $BMMUIF3BDLBQQHFUUIFSFUVSOWBMVFT <4UBUVT \)FBEFS^ <#PEZ>>

Slide 54

Slide 54 text

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 !DMPTFEGBMTF

Slide 55

Slide 55 text

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 !DMPTFEGBMTF *U`TBOJOTUBODFPG3BDL#PEZ1SPYZ 8IBUJTJOTJEF!CPEZ

Slide 56

Slide 56 text

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 !DMPTFEGBMTF "OEUIJTJTXIBU*XBOU )PXDBO*HFUUIJTʜ 8IBUJTJOTJEF!CPEZ

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

JSC 4JNQMF3BDL$PNQBUJCMF4FSWFSTFSWFʜ QQ!CPEZDBMM FOW < \$POUFOU5ZQFUFYUIUNM^ 3BDL-JOUYʜ !BQQ 3BDL5FNQpMF3FBQFSYʜ!BQQ"QQYʜ !CPEZ 3BDL#PEZ1SPYZYʜ !CMPDL 1SPDYʜ!ʜSBDLMJCSBDLUFNQpMF@SFBQFSSC !CPEZ !DMPTFEGBMTF !DPOUFOU@MFOHUIOJM !IFBE@SFRVFTUGBMTF> 4PGBSʜ 4IPVME*LFFQDBMMJOHVOUJM UIFSFTQPOTFCPEZJUTFMG JTSFUVSOFE CPEZ BOJOTUBODFPG3BDL-JOU 5SJFEUPDBMM!CPEZ

Slide 59

Slide 59 text

*HPUBIJOUGSPN5BLBIBTIJTBO 5IFDBMMNFUIPESFUVSOTBO"SSBZPCKFDU XJUIFMFNFOUTBOEUIFUIJSEJTCPEZ "OECPEZJTBOPCKFDUSFTQPOEUP FBDINFUIPE UP@QBUINFUIPEBOETPPOʜ

Slide 60

Slide 60 text

*HPUBIJOUGSPN5BLBIBTIJTBO 5IFDBMMNFUIPESFUVSOTBO"SSBZPCKFDU XJUIFMFNFOUTBOEUIFUIJSEJTCPEZ "OECPEZJTBOPCKFDUSFTQPOEUP FBDINFUIPE UP@QBUINFUIPEBOETPPOʜ ʜFBDINFUIPE

Slide 61

Slide 61 text

3BDL#PCZ1SPYZFBDI 3BDL#PCZ1SPYZIBTFBDINFUIPE 5IJTNJHIUCFVTFGVM

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

SBDLVQTTJNQMF@SBDL@DPNQBUJCMF@TFSWFS "HBJOBOEBHBJO

Slide 65

Slide 65 text

BOEʜ

Slide 66

Slide 66 text

*UXPSLT 3FTQPOTFCPEZJTBMTPEJTQMBZFE

Slide 67

Slide 67 text

5IFTUBUVTDPEF IFBEFS BOECPEZBSF BMMPVUQVUUPUIFDMJFOUTJEF *UXPSLT 4UBUVT‎)5510, )FBEFS‎$POUFOU5ZQFUFYUIUNM #PEZ‎EJW I)FMMPI Q5IJTBQQJTʜQ EJW

Slide 68

Slide 68 text

5IJTJTUIFpYFEWFSTJPO⚡

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

͓ർΕ༷Ͱͨ͠✨

Slide 76

Slide 76 text

ը૾ɿIUUQTUXJUUFSDPNUFOEFSMPWF ग़యɿIUUQTTQFBLFSEFDLDPNUFOEFSMPWFHBPEVOBLPEP "BSPOTBOɹɹɹɹ

Slide 77

Slide 77 text

.ZJNQSFTTJPOBGUFSJNQMFNFOUBUJPO 3BDLΛ࢖ͬͯ 3BDLDPNQBUJCMFͳ 8FCαʔόʔΛ࡞Δͷ͸ ָ

Slide 78

Slide 78 text

"OEBMTPʜ ⚡5IFSFBSFTUJMMBMPUPGUIJOHTUPUIJOLBCPVU BTJUJTTUJMMQSPWJTJPOBMMZJNQMFNFOUFE *OQVU 1BSBMMFMJ[BUJPO 1FSGPSNBODFʜ ⚡*`EMPWFUPLOPXNPSFBOENPSFBCPVU3BDL ⚡*`NXBJUJOHGPSZPVSSFWJFX IUUQTHJUIVCDPNTIJPJNNTJNQMF@SBDL@DPNQBUJCMF@TFSWFS

Slide 79

Slide 79 text

3BDL͸ָɹ

Slide 80

Slide 80 text

3BDL͸ָ͍͠ʂ

Slide 81

Slide 81 text

͓ΘΓʹ⚡⚡⚡

Slide 82

Slide 82 text

"CPVUNF BHBJO

Slide 83

Slide 83 text

%PZPVSFNFNCFSXIBUIBQQFOFE ZFBSBOEBIBMGBHP

Slide 84

Slide 84 text

4FQ 0FEP3VCZ,BJHJ ը૾ɿIUUQTSFHJPOBMSVCZLBJHJPSHPFEP

Slide 85

Slide 85 text

.ZpSTUUJNFGPS"TBLVTBSC ʜJTEBZTCFGPSF UIFQSFWJPVT0FEP3VCZ,BJHJ GSPNUIFFTBPG"TBLVTBSC "OE*BQQMJFEGPSJUBUUIBUUJNFSJHIUBXBZ ୈճ ը૾ɿIUUQTBTBLVTBSCFTBJPQPTUT

Slide 86

Slide 86 text

ը૾ɿIUUQTSFHJPOBMSVCZLBJHJPSHPFEP 5IFQSFWJPVT0FEP3VCZLBJHJ

Slide 87

Slide 87 text

XBTBHSFBUUJNF ը૾ɿIUUQTSFHJPOBMSVCZLBJHJPSHPFEP 5IFQSFWJPVT0FEP3VCZLBJHJ

Slide 88

Slide 88 text

,FZOPUF +POBOTBOʮ)PXUPCFσΧʯ ը૾ɿIUUQTSFHJPOBMSVCZLBJHJPSHPFEP 5IFQSFWJPVT0FEP3VCZLBJHJ

Slide 89

Slide 89 text

,FZOPUF +POBOTBOʮ)PXUPCFσΧʯ Have your heroes ը૾ɿIUUQTSFHJPOBMSVCZLBJHJPSHPFEP 5IFQSFWJPVT0FEP3VCZLBJHJ

Slide 90

Slide 90 text

'PSNF ZFBSBOEBIBMGBHP 5IFQFPQMFJO"TBLVTBSC XFSFSFBMlIFSPFTz

Slide 91

Slide 91 text

/PX BOEBIBMGZFBSTMBUFS 5IFZBSFBMTP QFFSTJOUIFTBNFDPNNVOJUZ

Slide 92

Slide 92 text

5BMLBCPVU3VCZ FUD ✨ 8SJUFDPEFT+ )BWFBEFMJDJPVTEJTIFTFUD 'PSNF "TBLVTBSCJTXIFSF 3VCZJTUTHBUIFS UPNBLFΘ͍Θ͍BOEFOKPZ

Slide 93

Slide 93 text

"TBLVTBSC͸ָ͍͠ʂ

Slide 94

Slide 94 text

4QFDJBM5IBOLT✨ JOTQJSFEGSPN !FTUIFS !UFOEFSMPWFUIF3BDLUFBN ŠŠ !JHBJHB!VE[VSB !UBLBIBTIJN!PLVSBNBTBGVNJ !UIFKPOBOTIPX"TBLVTBSC'VLVPLBSC "OEUIBOLZPVGPSMJTUFOJOH⚡⚡⚡