Slide 1

Slide 1 text

.JTBLJ4IJPJ TIJPJNN!DPF@ 4FQ 3VCZ,BJHJ5BLFPVU 5PZDPM %F fi OFZPVSPXOBQQMJDBUJPOQSPUPDPM

Slide 2

Slide 2 text

"CPVUNF (JU)VC!TIJPJNN 5XJUUFS!DPF@ 8FCBQQMJDBUJPOEFWFMPQFSBU$BUBM *OD .FNCFSPG"TBLVTBSC'VLVPLBSC

Slide 3

Slide 3 text

"CPVUNF IUUQTSVCZLBJHJPSH ʜBOEXBTBIFMQFSTUB ff BU3VCZ,BJHJJO'VLVPLB

Slide 4

Slide 4 text

*`NWFSZIBQQZUPCFBTQFBLFSBU 3VCZ,BJHJ5BLFPVU

Slide 5

Slide 5 text

#ZUIFXBZ

Slide 6

Slide 6 text

8IBUEPZPVMJLFBCPVU 5$1*1QSPUPDPMTUBDL *ONZPQJOJPOʜ

Slide 7

Slide 7 text

5IFGBDUUIBUFBDIMBZFS EPFTJUTPXOKPC 5IFZEPOUDBSFXIBU PUIFSMBZFSTBSFEPJOH Application Layer Transport Layer Internet Layer Link Layer 8IBU*MJLFBCPVU5$1*1QSPUPDPMTUBDLᶃ 5$1*1QSPUPDPMTUBDL

Slide 8

Slide 8 text

8IBU*MJLFBCPVU5$1*1QSPUPDPMTUBDLᶄ /FUXPSLOPEF Application Layer Transport Layer Internet Layer Link Layer /FUXPSLOPEF Application Layer Transport Layer Internet Layer Link Layer 5IFGBDUUIBUMBZFSTPGUIFTBNFMFWFMPGUIFBCTUSBDUJPO DPNNVOJDBUFXJUIFBDIPUIFSVTJOHUIFTBNFQSPUPDPM

Slide 9

Slide 9 text

4P XIBUJTB JOUIFDPOUFYUPGDPNQVUFSOFUXPSL QSPUPDPM

Slide 10

Slide 10 text

*UJTBTFUPGSVMFTGPSDPNNVOJDBUJPO CFUXFFOOFUXPSLOPEFT

Slide 11

Slide 11 text

'PSFYBNQMF $MJFOU/PEF 4FSWFS/PEF 0O888 BDMJFOUBOEBTFSWFSBSFUSBOTNJUUJOH IZQFSNFEJBEPDVNFOUTVTJOH)551QSPUPDPM World Wide Web Transport Layer Internet Layer Link Layer World Wide Web Transport Layer Internet Layer Link Layer )551

Slide 12

Slide 12 text

'PSFYBNQMF $MJFOU/PEF 4FSWFS/PEF #VUUIFMBZFSTCFMPXUIFUSBOTQPSUMBZFSEPO`ULOPX XIBUUIFQSPUPDPMJTMJLF888JTVTJOH World Wide Web Transport Layer Internet Layer Link Layer World Wide Web Transport Layer Internet Layer Link Layer ˕

Slide 13

Slide 13 text

'PSFYBNQMF $MJFOU/PEF 4FSWFS/PEF 4UJMM UIFMBZFSTCFMPXUIFUSBOTQPSUMBZFSDBOUSBOTGFS XIBUFWFSEBUB888VTFT World Wide Web Transport Layer Internet Layer Link Layer World Wide Web Transport Layer Internet Layer Link Layer )551 )551

Slide 14

Slide 14 text

'PSFYBNQMF $MJFOU/PEF 4FSWFS/PEF "HBJO UIFOFUXPSLOPEFTDBODPNNVOJDBUFXJUIFBDIPUIFS BTMPOHBTUIFZCPUIVOEFSTUBOEUIFTBNFQSPUPDPM World Wide Web Transport Layer Internet Layer Link Layer World Wide Web Transport Layer Internet Layer Link Layer )551

Slide 15

Slide 15 text

'PSFYBNQMF $MJFOU/PEF 4FSWFS/PEF *OPUIFSXPSET UIFQSPUPDPMGPSDPNNVOJDBUJPOEPFTOU IBWFUPCF)551 BTMPOHBTUIFZVOEFSTUBOEJU World Wide Web Transport Layer Internet Layer Link Layer World Wide Web Transport Layer Internet Layer Link Layer ˕

Slide 16

Slide 16 text

4P *IBWFDSFBUFEBTNBMMGSBNFXPSL UIBUBMMPXTZPVUPDSFBUF ZPVSPXOQSPUPDPMGPSDPNNVOJDBUJPO CFUXFFOBDMJFOUBOEBTFSWFSPO888 JOTUFBEPG)551

Slide 17

Slide 17 text

*OUIJTGSBNFXPSL UIFQSPUPDPMZPVEF fi OFXPSLTBT BXSBQQFSGPSUIF)551 BOEDBOCFVTFEUPSVOBQQMJDBUJPOT

Slide 18

Slide 18 text

-FUTTFFIPXJUXPSLT

Slide 19

Slide 19 text

FH%VDLQSPUPDPM

Slide 20

Slide 20 text

FH%VDLQSPUPDPM RVBDL RVBDLQPTUTVTFS@JE *OUIJTQSPUPDPM BDMJFOUTQFBLTUPBTFSWFSXJUI RVBDL RVBDLQPTUTVTFS@JEz 5IFOUIFTFSWFSVOEFSTUBOETJU Client Server

Slide 21

Slide 21 text

4FSWFSFYFDVUFTUIFBQQMJDBUJPOBOESFUVSOTUIFSFTVMU PGUIFBQQMJDBUJPOFYFDVUJPOUPUIFDMJFOU Client Server Application )5510,ʜ FH%VDLQSPUPDPM

Slide 22

Slide 22 text

*UHPFTMJLFUIJT

Slide 23

Slide 23 text

$ toycol server 4UBSUVQBTFSWFSUIBUVOEFSTUBOET%VDLQSPUPDPM $ toycol client “quack, quack /posts<3user_id=1” 4FOESFRVFTUNFTTBHFCZ%VDLQSPUPDPMUPUIFTFSWFS FH%VDLQSPUPDPM

Slide 24

Slide 24 text

$ toycol server [Toycol] Start built-in server, listening on unix:///tmp/toycol.socket [Toycol] Start proxy server on duck protocol, listening on localhost:9292 => Use Ctrl-C to stop [Toycol] Received message: "quack, quack /posts<3user_id=1” [Toycol] Message has been translated to HTTP request message: "GET /posts? user_id=1 HTTP/1.1\r\nContent-Length: 0\r\n\r\n" [Toycol] Successed to Send HTTP request message to server [Toycol] Received response message from server: HTTP/1.1 200 OK [Toycol] Finished to response to client -PHTPOUIFTFSWFSTJEF

Slide 25

Slide 25 text

$ toycol client “quack, quack /posts<3user_id=1” [Toycol] Sent request message: quack, quack /posts<3user_id=1 --- [Toycol] Received response message: HTTP/1.1 200 OK Content-Type: text/html Content-Length: 32 quack quack, I am the No.1 duck -PHTPOUIFDMJFOUTJEF

Slide 26

Slide 26 text

)PXFWFS JOUIFSFBMXPSME UIFSFJT ZFU OPGVMM fl FEHFEXFCTFSWFS PSCSPXTFSJOUIFXPSMEUIBUSVOT POUIFQSPUPDPMZPVEFWJTFE 4P UIFQSPUPDPMEF fi OFE CZUIJTGSBNFXPSLJTJOGBDUBlUPZz

Slide 27

Slide 27 text

'PSUIJTSFBTPO *OBNFEUIJTGSBNFXPSLBTGPMMPXT

Slide 28

Slide 28 text

5PZ1SPUPDPM 5PZDPM

Slide 29

Slide 29 text

5PZ1SPUPDPM 5PZDPM IUUQTHJUIVCDPNTIJPJNNUPZDPM

Slide 30

Slide 30 text

*OEFFE 5PZDPMJTBGSBNFXPSLGPSUPZ )PXFWFS CZVTJOHUIJTGSBNFXPSL ZPVXJMMCF BCMFUPFYQFSJFODFBOEMFBSO )PXUIFBQQMJDBUJPOMBZFSJTDPOOFDUFEUP UIFUSBOTQPSUMBZFSz BOE)PXUIFBQQMJDBUJPOQSPUPDPMXPSLTPO UIFUSBOTQPSUMBZFS

Slide 31

Slide 31 text

5PEBZ *XPVMEMJLFUPTIBSFJUXJUIZPV

Slide 32

Slide 32 text

5PEBZTBHFOEB )PXUPVTF5PZDPM XJUIBFYBNQMFPGTJNQMFEF fi OJUJPOT *OUFSOBMJNQMFNFOUBUJPOPG5PZDPM "EWBODFEQSPUPDPMEF fi OJUJPOT

Slide 33

Slide 33 text

)PXUPVTF5PZDPM XJUIBFYBNQMFPGTJNQMFEF fi OJUJPOT

Slide 34

Slide 34 text

-FU`TEF fi OFBOFXQSPUPDPMXJUI5PZDPM BOETFFIPXJUXPSLTJOQSBDUJDF 5IJTUJNF MFUTDSFBUF BOFXQSPUPDPMOBNFE3VCZMJLF XPSLTXJUI3VCZMJLFTZOUBYQSPUPDPM

Slide 35

Slide 35 text

5PEF fi OFBOFXQSPUPDPM ZPVOFFEUPQSFQBSF UIJTGPMMPXJOHUXPJUFNT "DPO fi HVSBUJPO fi MF 'PSEF fi OJOHQSPUPDPM 5IJT fi MFOFFETUPCFOBNFE l1SPUPDPM fi MFzPSl1SPUPDPM fi MFSVCZMJLFzBOETPPO "3BDLDPNQBUJCMFBQQMJDBUJPO FHDPO fi HSV ᶃ1SFQBSFBDPO fi HVSBUJPO fi MFBBQQMJDBUJPO

Slide 36

Slide 36 text

ᶃ1SFQBSFBDPO fi HVSBUJPO fi MFBBQQMJDBUJPO :PVDBOFBTJMZDSFBUFUIFTFTLFMFUPOTCZVTJOH UPZDPMHFOFSBUFDPNNBOE $ toycol generate rubylike [Toycol] Generate Protocol fi le.rubylike in /path/to/current_directory [Toycol] Generate con fi g_rubylike.ru in /path/to/current_directory :PVDBOQBTTUIFQSPUPDPMOBNF BTBOBSHVNFOUUP UPZDPMHFOFSBUFDPNNBOE 6TFS

Slide 37

Slide 37 text

ᶄ%F fi OFZPVSQSPUPDPMJOUIF1SPUPDPM fi MF Toycol::Protocol.de fi ne(:rubylike) do request.path do |message| /['"](?.+)['"]/.match(message)[:path] end request.http_method do |message| case /\.(?[A-z]+)/.match(message)&.captures&. fi rst when "get" then "GET" else “Raise" end end additional_request_methods "Raise" custom_status_codes( 600 => "SyntaxError...", ) end 6TFS 1SPUPDPM fi MFSVCZMJLF /FYU EF fi OF3VCZMJLFQSPUPDPM JOUIF1SPUPDPM fi MF

Slide 38

Slide 38 text

Toycol::Protocol.de fi ne(:rubylike) do request.path do |message| /['"](?.+)['"]/.match(message)[:path] end request.http_method do |message| case /\.(?[A-z]+)/.match(message)&.captures&. fi rst when "get" then "GET" else “Raise" end end additional_request_methods "Raise" custom_status_codes( 600 => "SyntaxError...", ) end 6TFS 1SPUPDPM fi MFSVCZMJLF 1BTTUIFQSPUPDPMOBNFBTBOBSHVNFOU BOEBCMPDLGPSEF fi OJOHUIFQSPUPDPM UP5PZDPM1SPUPDPMEF fi OF ᶄ%F fi OFZPVSQSPUPDPMJOUIF1SPUPDPM fi MF

Slide 39

Slide 39 text

Toycol::Protocol.de fi ne(:rubylike) do request.path do |message| /['"](?.+)['"]/.match(message)[:path] end request.http_method do |message| case /\.(?[A-z]+)/.match(message)&.captures&. fi rst when "get" then "GET" else “Raise" end end additional_request_methods "Raise" custom_status_codes( 600 => "SyntaxError...", ) end 6TFS 1SPUPDPM fi MFSVCZMJLF :PVOFFEUPEF fi OFIPXUPQBSTF UIFSFRVFTUNFTTBHFJOUIFTFCMPDLTPG SFRVFTUQBUISFRVFTUIUUQ@NFUIPE ᶄ%F fi OFZPVSQSPUPDPMJOUIF1SPUPDPM fi MF

Slide 40

Slide 40 text

Toycol::Protocol.de fi ne(:rubylike) do request.path do |message| /['"](?.+)['"]/.match(message)[:path] end request.http_method do |message| case /\.(?[A-z]+)/.match(message)&.captures&. fi rst when "get" then "GET" else “Raise" end end additional_request_methods "Raise" custom_status_codes( 600 => "SyntaxError...", ) end 6TFS 1SPUPDPM fi MFSVCZMJLF #FTJEFT ZPVDBOEF fi OFZPVSPXOTUBUVTDPEFT CZBEEJUJPOBM@SFRVFTU@NFUIPET BEEOFXSFRVFTUNFUIPETCZ DVTUPN@TUBUVT@DPEFTNFUIPE ᶄ%F fi OFZPVSQSPUPDPMJOUIF1SPUPDPM fi MF

Slide 41

Slide 41 text

Toycol::Protocol.de fi ne(:rubylike) do request.path do |message| /['"](?.+)['"]/.match(message)[:path] end request.http_method do |message| case /\.(?[A-z]+)/.match(message)&.captures&. fi rst when "get" then "GET" else “Raise" end end additional_request_methods "Raise" custom_status_codes( 600 => "SyntaxError...", ) end 6TFS 1SPUPDPM fi MFSVCZMJLF *OUIJT3VCZMJLFQSPUPDPM *BEEFE3BJTFBTBOFXSFRVFTUNFUIPE BOEEF fi OFEBTBDVTUPNTUBUVTDPEF ᶄ%F fi OFZPVSQSPUPDPMJOUIF1SPUPDPM fi MF

Slide 42

Slide 42 text

Toycol::Protocol.de fi ne(:rubylike) do request.path do |message| /['"](?.+)['"]/.match(message)[:path] end request.http_method do |message| case /\.(?[A-z]+)/.match(message)&.captures&. fi rst when "get" then "GET" else “Raise" end end additional_request_methods "Raise" custom_status_codes( 600 => "SyntaxError...", ) end 6TFS 1SPUPDPM fi MFSVCZMJLF ᶄ%F fi OFZPVSQSPUPDPMJOUIF1SPUPDPM fi MF *GUIFSFRVFTUNFTTBHFJTTVDDFTTGVMMZQBSTFE UIFSFRVFTUNFUIPEJT(&5 PUIFSXJTFJUJT3BJTF

Slide 43

Slide 43 text

ᶅ#VJMEB3BDLDPNQBUJCMFBQQMJDBUJPO require "rack" require "toycol" Toycol::Protocol.use(:rubylike) class App def call(env) case env["REQUEST_METHOD"] when “GET” [200, { "Content-Type" => "text/html" }, [“I love Ruby!”\n”, ”I love RubyKaigi!\n”]] when “Raise” [600, { "Content-Type" => "text/html" }, [“Unexpected request message”]] end end end run App.new 6TFS DPO fi H@SVCZJMLFSV /FYU CVJMEB3BDLDPNQBUJCMFBQQMJDBUJPO UIBUSVOTPO3VCZMJLFQSPUPDPM

Slide 44

Slide 44 text

require "rack" require "toycol" Toycol::Protocol.use(:rubylike) class App def call(env) case env["REQUEST_METHOD"] when “GET” [200, { "Content-Type" => "text/html" }, [“I love Ruby!”\n”, ”I love RubyKaigi!\n”]] when “Raise” [600, { "Content-Type" => "text/html" }, [“Unexpected request message”]] end end end run App.new :PVOFFEUPSFRVJSFlUPZDPMz BOEDBMM5PZDPM1SPUPDPMVTFUPTQFDJGZ XIJDIQSPUPDPMZPVXPVMEMJLFUPVTF 6TFS DPO fi H@SVCZJMLFSV ᶅ#VJMEB3BDLDPNQBUJCMFBQQMJDBUJPO

Slide 45

Slide 45 text

require "rack" require "toycol" Toycol::Protocol.use(:rubylike) class App def call(env) case env["REQUEST_METHOD"] when “GET” [200, { "Content-Type" => "text/html" }, [“I love Ruby!”\n”, ”I love RubyKaigi!\n”]] when “Raise” [600, { "Content-Type" => "text/html" }, [“Unexpected request message”]] end end end run App.new *OUIJTBQQMJDBUJPO *EF fi OFEUPSFUVSO TUBUVTDPEFGPS(&5SFRVFTU BOETUBUVTDPEFGPS4ZOUBY&SSPSSFRVFTU 6TFS DPO fi H@SVCZJMLFSV ᶅ#VJMEB3BDLDPNQBUJCMFBQQMJDBUJPO

Slide 46

Slide 46 text

ᶆ3VOUIFTFSWFS4FOEBSFRVFTUNFTTBHF 5IFTFSWFSQSPHSBNUPSVOUIFQSPUPDPMBOEUIFDMJFOU QSPHSBNJOUPTFOEUIFSFRVFTUNFTTBHFCZUIFQSPUPDPM BSFCVJMUJOBTDPNNBOEMJOFUPPMT -FU`TTUBSUUIFTFSWFSTFOETPNFUIJOHUPSFRVFTU $ toycol client ??? (A request message by Rubylike protocol) $ toycol server con fi g_rubylike.ru 4FSWFS$-* $MJFOU$-*

Slide 47

Slide 47 text

-FUTTFOEBNFTTBHFUIBUTFFNTUPCF3VCZMJLFTZOUBY $ toycol client “‘/posts’.get” [Toycol] Sent request message: '/posts'.get --- [Toycol] Received response message: HTTP/1.1 200 OK Content-Type: text/html Content-Length: 31 I love Ruby! I love RubyKaigi! 5IJTJT3VCZMJLF JTO`UJU 5IFBQQMJDBUJPOSFUVSOT0, ᶆ3VOUIFTFSWFS4FOEBSFRVFTUNFTTBHF

Slide 48

Slide 48 text

-FU`TUSZBOBOPUIFSNFTTBHFUIBUNJHIUNJHIUSBJTFBFSSPS $ toycol client “get(‘/posts’)” [Toycol] Sent request message: get(‘/posts’) --- [Toycol] Received response message: HTTP/1.1 600 SyntaxError Content-Type: text/html Content-Length: 64 Unexpected request message *TJUQBSTFBCMFCZ3VCZMJLFQSPUPDPMʜ 5IFBQQMJDBUJPOSFUVSOT4ZOUBY&SSPS ᶆ3VOUIFTFSWFS4FOEBSFRVFTUNFTTBHF *U`TXPSLJOHDPSSFDUMZ

Slide 49

Slide 49 text

*OUFSOBMJNQMFNFOUBUJPOPG5PZDPM

Slide 50

Slide 50 text

/PXMFU`TFYQMPSFUIFJOTJEFPG5PZDPM GSPNUXPBTQFDUT 5IFOFUXPSLDPNNVOJDBUJPO fl PX )PXUPUSBOTMBUFBSFRVFTUNFTTBHF

Slide 51

Slide 51 text

5IFOFUXPSLDPNNVOJDBUJPO fl PX

Slide 52

Slide 52 text

5IFOFUXPSLDPNNVOJDBUJPO fl PX -FUTUBLFBMPPLBUIPX5PZDPMXPSLTJOUFSOBMMZXJUIUIF OFUXPSLDPNNVOJDBUJPO fl PX)FSFJTBPWFSBMMWJFX $MJFOU 1SPYZ4FSWFS #BDLHSPVOE4FSWFS "QQMJDBUJPO 3BDL)BOEMFS 1SPUPDPM%F fi OJUJPO

Slide 53

Slide 53 text

4UBSUTFSWFSTCZ3BDLIBOEMFS 5PZDPMSVOT3BDLDPNQBUJCMFBQQMJDBUJPOT 4PZPVTUBSUTFSWFSTGPS5PZDPMCZ3BDLIBOEMFS $MJFOU 1SPYZ4FSWFS #BDLHSPVOE4FSWFS "QQMJDBUJPO 3BDL)BOEMFS 1SPUPDPM%F fi OJUJPO

Slide 54

Slide 54 text

4UBSUTFSWFSTXJUIUPZDPMTFSWFS UPZDPMTFSWFSDPNNBOEDBMMT3BDL4FSWFSTUBSUJOTJEF 3BDL 5IFO3BDL4FSWFSTUBSUDBMMT3BDL)BOEMFS5PZDPMSVO 3BDL)BOEMFS5PZDPMSVO 5PZDPM 3BDL UPZDPMTFSWFS 3BDL4FSWFSTUBSU

Slide 55

Slide 55 text

3BDL)BOEMFS5PZDPMSVO4UBSUTFSWFST module Rack module Handler class Toycol def self.run(app, _ = {}) @app = app @host ||= ::Toycol::DEFAULT_HOST @port ||= "9292" if (child_pid = fork) ::Toycol::Proxy.new(@host, @port).start Process.waitpid(child_pid) else run_background_server end end end end end MJCSBDLIBOEMFSUPZDPMSC 3BDL)BOEMFS5PZDPMSVO

Slide 56

Slide 56 text

module Rack module Handler class Toycol def self.run(app, _ = {}) @app = app @host ||= ::Toycol::DEFAULT_HOST @port ||= "9292" if (child_pid = fork) ::Toycol::Proxy.new(@host, @port).start Process.waitpid(child_pid) else run_background_server end end end end end 4UBSUBQSPYZTFSWFS 4UBSUBCBDLHSPVOETFSWFS MJCSBDLIBOEMFSUPZDPMSC 'PSLUPTUBSUUXPLJOEPGTFSWFST BQSPYZTFSWFSBCBDLHSPVOETFSWFS JOUIJTNFUIPE 3BDL)BOEMFS5PZDPMSVO4UBSUTFSWFST

Slide 57

Slide 57 text

5IFSPMFTPGUIFUXPTFSWFST 5IFQSPYZTFSWFSJTGPSSFDFJWJOHSFRVFTUTUSBOTMBUJOH QSPUPDPM $MJFOU 1SPYZ4FSWFS #BDLHSPVOE4FSWFS "QQMJDBUJPO 3BDL)BOEMFS 1SPUPDPM%F fi OJUJPO

Slide 58

Slide 58 text

5IFSPMFTPGUIFUXPTFSWFST 5IFCBDLHSPVOETFSWFSJTGPSSVOOJOHUIFBQQMJDBUJPO $MJFOU 1SPYZ4FSWFS #BDLHSPVOE4FSWFS "QQMJDBUJPO 3BDL)BOEMFS 1SPUPDPM%F fi OJUJPO

Slide 59

Slide 59 text

3BDL)BOEMFS5PZDPMTFMFDU@CBDLHSPVOE@TFSWFS def self.select_background_server case @prefferd_background_server when “puma” return “puma” if try_require_puma_handler raise LordError, “Puma is not installed in your environment.” when nil try_require_puma_handler ? “puma” : “builtin” else “builtin” rescue LordError Process.kill(:INT, Process.ppid) abort end MJCSBDLIBOEMFSUPZDPMSC "TBCBDLHSPVOETFSWFS VTF1VNBJGJUJTJOTUBMMFE JOZPVSFOWJSPONFOU0SVTFBTFSWFSUIBUJTCVJMUJOUP 5PZDPMJUTFMGJGJUJTOPU

Slide 60

Slide 60 text

28IZTIPVMEXFVTFCPUI BQSPYZTFSWFSBOEBCBDLHSPVOETFSWFS

Slide 61

Slide 61 text

"5PQFSGPSNNFTTBHFUSBOTMBUJPO BOEBQQMJDBUJPOFYFDVUJPOTFQBSBUFMZ 4PNFBQQMJDBUJPOTCVJMUCZGSBNFXPSLTTVDIBT 4JOBUSBPS3BJMTVTF1VNBCZEFGBVMU BOE*XPVMEO`UMJLFUPNPEJGZ1VNBPSUIFGSBNFXPSL UPNBLFUIFNXPSL

Slide 62

Slide 62 text

3FDFJWFBSFRVFTUNFTTBHFGSPNUIFDMJFOU 4PGBS XFWFHPUUIFTFSWFSTVQBOESVOOJOH/FYU UIF QSPYZTFSWFSSFDFJWFTBSFRVFTUNFTTBHFGSPNUIFDMJFOU $MJFOU 1SPYZ4FSWFS #BDLHSPVOE4FSWFS "QQMJDBUJPO 3BDL)BOEMFS 1SPUPDPM%F fi OJUJPO

Slide 63

Slide 63 text

5SBOTMBUFUIFSFRVFTUNFTTBHF "OEUIFOUIFQSPYZTFSWFSUSBOTMBUFTJUJOUPB)551 GPSNBUUFESFRVFTUNFTTBHFVTJOHUIFQSPUPDPMEF fi OJUJPO $MJFOU 1SPYZ4FSWFS #BDLHSPVOE4FSWFS "QQMJDBUJPO 3BDL)BOEMFS 1SPUPDPM%F fi OJUJPO

Slide 64

Slide 64 text

def start … loop do trap(:INT) { shutdown } @client = @proxy.accept while [email protected]? && [email protected]? begin request = @client.readpartial(CHUNK_SIZE) logger “Received message: #{request.inspect.chomp}” safe_execution! { @protocol.run!(request) } … end end @client.close end end MJCUPZDPMQSPYZSC 5PZDPM1SPYZTUBSU 5PZDPM1SPYZTUBSU3FDFJWF5SBOTMBUF

Slide 65

Slide 65 text

def start … loop do trap(:INT) { shutdown } @client = @proxy.accept while [email protected]? && [email protected]? begin request = @client.readpartial(CHUNK_SIZE) logger “Received message: #{request.inspect.chomp}” safe_execution! { @protocol.run!(request) } … end end @client.close end end !QSPYZ5$14FSWFSOFX !IPTU !QPSU MJCUPZDPMQSPYZSC 3FDFJWFBSFRVFTUNFTTBHFGSPNUIFDMJFOU 5PZDPM1SPYZTUBSU3FDFJWF5SBOTMBUF

Slide 66

Slide 66 text

def start … loop do trap(:INT) { shutdown } @client = @proxy.accept while [email protected]? && [email protected]? begin request = @client.readpartial(CHUNK_SIZE) logger “Received message: #{request.inspect.chomp}” safe_execution! { @protocol.run!(request) } … end end @client.close end end !QSPUPDPM5PZDPM1SPUPDPM MJCUPZDPMQSPYZSC &YFDVUF5PZDPM1SPUPDPMSVOUPUSBOTMBUF UIFSFRVFTUNFTTBHFJOUP)551GPSNBU 5PZDPM1SPYZTUBSU3FDFJWF5SBOTMBUF

Slide 67

Slide 67 text

4FOEBSFRVFTUNFTTBHFUPCBDLHSPVOETFSWFS 5IFQSPYZTFSWFSTFOETB)551GPSNBUUFESFRVFTU NFTTBHFUPUIFCBDLHSPVOETFSWFS $MJFOU 1SPYZ4FSWFS #BDLHSPVOE4FSWFS "QQMJDBUJPO 3BDL)BOEMFS 1SPUPDPM%F fi OJUJPO

Slide 68

Slide 68 text

3FDFJWFBSFTQPOTFNFTTBHFGSPNUIFCBDLHSPVOETFSWFS ʜBOESFDFJWFTUIFSFTVMUTPGUIFBQQMJDBUJPOFYFDVUFE GSPNUIFCBDLHSPVOETFSWFS $MJFOU 1SPYZ4FSWFS #BDLHSPVOE4FSWFS "QQMJDBUJPO 3BDL)BOEMFS 1SPUPDPM%F fi OJUJPO

Slide 69

Slide 69 text

5PZDPM1SPYZTUBSU$BMMUSBOTGFS@UP@TFSWFS def start … loop do trap(:INT) { shutdown } @client = @proxy.accept while [email protected]? && [email protected]? begin … http_request_message = build_http_request_message … transfer_to_server(http_request_message) end end @client.close end end MJCUPZDPMQSPYZSC $BMM5PZDPM1SPYZUSBOTGFS@UP@TFSWFS UIBUTFOETUIFSFRVFTUNFTTBHFUP UIFCBDLHSPVOETFSWFS

Slide 70

Slide 70 text

5PZDPM1SPYZUSBOTGFS@UP@TFSWFS3FRVFTU3FTQPOTF def transfer_to_server UNIXSocket.open(UNIIX_SOCKET_PATH) do |server| server.write request_message server.close_write … response_message = [] response_message << server.readpartial(CHUNK_SIZE) until server.eof? response_message = response_message.join … end end MJCUPZDPMQSPYZSC 5PZDPM1SPYZUSBOTGFS@UP@TFSWFS

Slide 71

Slide 71 text

5PZDPM1SPYZUSBOTGFS@UP@TFSWFS3FRVFTU3FTQPOTF def transfer_to_server UNIXSocket.open(UNIIX_SOCKET_PATH) do |server| server.write request_message server.close_write … response_message = [] response_message << server.readpartial(CHUNK_SIZE) until server.eof? response_message = response_message.join … end end MJCUPZDPMQSPYZSC $POOFDUUPUIFCBDLHSPVOETFSWFSXJUI B6/*9EPNBJOTPDLFU

Slide 72

Slide 72 text

5PZDPM1SPYZUSBOTGFS@UP@TFSWFS3FRVFTU3FTQPOTF def transfer_to_server UNIXSocket.open(UNIIX_SOCKET_PATH) do |server| server.write request_message server.close_write … response_message = [] response_message << server.readpartial(CHUNK_SIZE) until server.eof? response_message = response_message.join … end end MJCUPZDPMQSPYZSC 4FOEUIFSFRVFTUNFTTBHFUP UIFCBDLHSPVOETFSWFS 5IFOUIFCBDLHSPVOETFSWFSSVOTUIFBQQMJDBUJPOʜ

Slide 73

Slide 73 text

5PZDPM1SPYZUSBOTGFS@UP@TFSWFS3FRVFTU3FTQPOTF def transfer_to_server UNIXSocket.open(UNIIX_SOCKET_PATH) do |server| server.write request_message server.close_write … response_message = [] response_message << server.readpartial(CHUNK_SIZE) until server.eof? response_message = response_message.join … end end MJCUPZDPMQSPYZSC ʜPOUIFCBDLHSPVOE 3FDFJWFUIFSFTQPOTFNFTTBHFGSPN UIFCBDLHSPVOETFSWFS

Slide 74

Slide 74 text

3FUVSOUIFSFTQPOTFNFTTBHFUPUIFDMJFOU 5IFOUIFQSPYZTFSWFSSFUVSOTUIFSFTQPOTFNFTTBHF SFDFJWFEGSPNUIFCBDLHSPVOETFSWFSUPUIFDMJFOU $MJFOU 1SPYZ4FSWFS #BDLHSPVOE4FSWFS "QQMJDBUJPO 3BDL)BOEMFS 1SPUPDPM%F fi OJUJPO

Slide 75

Slide 75 text

5PZDPM1SPYZUSBOTGFS@UP@TFSWFS3FUVSOUIFSFTQPOTF def transfer_to_server UNIXSocket.open(UNIIX_SOCKET_PATH) do |server| … response_message = [] response_message << server.readpartial(CHUNK_SIZE) until server.eof? response_message = response_message.join … @client.write response_message @client.close_write logger "Finished to response to client" server.close end end MJCUPZDPMQSPYZSC 3FUVSOTUIFSFTQPOTFNFTTBHFSFDFJWFE GSPNUIFCBDLHSPVOETFSWFSUPUIFDMJFOU

Slide 76

Slide 76 text

)PXUPUSBOTMBUFBSFRVFTUNFTTBHF

Slide 77

Slide 77 text

5IJTJTIPX5PZDPMXPSLTJOUFSOBMMZGSPNUIFEF fi OJOHPG UIFQSPUPDPMVOUJMUSBOTMBUJOHBSFRVFTUNFTTBHFXJUIJU DMBTT1SPUPDPM $MJFOU 1SPUPDPM%F fi OJUJPO 1SPYZ4FSWFS UPZDPMTFSWFS "QQMJDBUJPO )PXUPUSBOTMBUFBSFRVFTUNFTTBHF

Slide 78

Slide 78 text

"HBJO UIFTUBSUJOHQPJOUGPSUIFQSPHSBNFYFDVUJPOJT UPZDPMTFSWFSDPNNBOE DMBTT1SPUPDPM $MJFOU 1SPYZ4FSWFS "QQMJDBUJPO UPZDPMTFSWFS 1SPUPDPM%F fi OJUJPO 4UBSUUIFQSPHSBNXJUIUPZDPMTFSWFS

Slide 79

Slide 79 text

4UBSUUIFQSPHSBNXJUIUPZDPMTFSWFS "DUVBMMZ 3BDL4FSWFSTUBSUDBMMT3BDL#VJMEFSMPBE@ fi MF BOE3BDL#VJMEFSOFX@GSPN@TUSJOHUPMPBEUIFBQQMJDBUJPO fi MFCFGPSFDBMMJOH3BDL)BOEMFS5PZDPMSVO 3BDL)BOEMFS5PZDPMSVO 5PZDPM 3BDL UPZDPMTFSWFS 3BDL4FSWFSTUBSU 3BDL#VJMEFSMPBE@ fi MF 3BDL#VJMEFSOFX@GSPN@TUSJOH

Slide 80

Slide 80 text

4P UIFQSPHSBNXJMMMPBEUIFBQQMJDBUJPO fi MFCFGPSF TUBSUJOHUIFTFSWFS $MJFOU 1SPYZ4FSWFS "QQMJDBUJPO UPZDPMTFSWFS -PBEUIFBQQMJDBUJPO fi MF DMBTT1SPUPDPM 1SPUPDPM%F fi OJUJPO

Slide 81

Slide 81 text

5IFBQQMJDBUJPO3FRVJSFlUPZDPMz require "rack" require "toycol" Toycol::Protocol.use(:rubylike) class App def call(env) case env["REQUEST_METHOD"] when “GET” [200, { "Content-Type" => "text/html" }, [“I love Ruby!”\n”, ”I love RubyKaigi!\n”]] when “OTHER” [600, { "Content-Type" => "text/html" }, [“Sorry, but I'd like you to speak more like a Ruby programmer…”]] end end end run App.new 6TFS DPO fi H@SVCZJMLFSV *OUIFBQQMJDBUJPO fi MF UPZDPMJTSFRVJSFEUPSVO5PZDPM

Slide 82

Slide 82 text

NPEVMF5PZDPM-PBE1SPUPDPM fi MFT require " fi leutiils" require “optparse" require “rack" require “scoket” require “stringio” … module Toycol … end Dir["#{FileUtils.pwd}/Protocol fi le*"].sort.each { |f| load f } MJCUPZDPMSC 8IFO5PZDPMJTSFRVJSFE UIJT fi MFOBNFEUPZDPMSCJOUIF5PZDPMHFN XJMMCFMPBEFE

Slide 83

Slide 83 text

require " fi leutiils" require “optparse" require “rack" require “scoket” require “stringio” … module Toycol … end Dir["#{FileUtils.pwd}/Protocol fi le*"].sort.each { |f| load f } 5PZDPMMPBET1SPUPDPM fi MFTUIBUBSFQMBDFE JOUIFTBNFEJSFDUPSZBTUIFBQQMJDBUJPO fi MF NPEVMF5PZDPM-PBE1SPUPDPM fi MFT 1SPUPDPM fi MF"DPO fi HVSBUJPO fi MFDPOUBJOJOHQSPUPDPMEF fi OJUJPOT MJCUPZDPMSC

Slide 84

Slide 84 text

4P UIF fi STUDPEFTUPCFMPBEFEJTUIFQSPUPDPMEF fi OJUJPO XIFOUIFQSPHSBNJTTUBSUFE $MJFOU 1SPYZ4FSWFS "QQMJDBUJPO UPZDPMTFSWFS -PBE1SPUPDPM fi MFT DMBTT1SPUPDPM 1SPUPDPM%F fi OJUJPO

Slide 85

Slide 85 text

1SPUPDPM fi MF4UPSFUIFFOUJSFEF fi OJUJPO Toycol::Protocol.de fi ne(:rubylike) do request.path do |message| /['"](?.+)['"]/.match(message)[:path] end request.http_method do |message| case /\.(?[A-z]+)/.match(message)&.captures&. fi rst when "get" then "GET" else "OTHER" end end additional_request_methods "OTHER" custom_status_codes( 600 => "Hmm...", ) end 6TFS 1SPUPDPM fi MFSVCZMJLF 'PSFYBNQMF1SPUPDPM fi MFPG3VCZMJLFQSPUPDPM

Slide 86

Slide 86 text

1SPUPDPM fi MF4UPSFUIFFOUJSFEF fi OJUJPO Toycol::Protocol.de fi ne(:rubylike) do request.path do |message| /['"](?.+)['"]/.match(message)[:path] end request.http_method do |message| case /\.(?[A-z]+)/.match(message)&.captures&. fi rst when "get" then "GET" else "OTHER" end end additional_request_methods "OTHER" custom_status_codes( 600 => "Hmm...", ) end 6TFS 1SPUPDPM fi MFSVCZMJLF 5IFDPEFTJOUIFCMPDLPG 5PZDPM1SPUPDPMEF fi OFBSFTUPSFE JO5PZDPM1SPUPDPMDMBTT

Slide 87

Slide 87 text

5PZDPM1SPUPDPMEF fi OF4UPSFUIFEF fi OJUJPO NPEVMF5PZDPM DMBTT1SPUPDPM !EF fi OFNFOUT\^ ʜ EFGTFMGEF fi OF QSPUPDPM@OBNFEFGBVMU CMPDL ʜ !EF fi OFNFOUTCMPDL FOE ʜ FOE FOE MJCUPZDPMQSPUPDPMSC 5PZDPM1SPUPDPMEF fi OF

Slide 88

Slide 88 text

5PZDPM1SPUPDPMEF fi OF4UPSFUIFEF fi OJUJPO NPEVMF5PZDPM DMBTT1SPUPDPM !EF fi OFNFOUT\^ ʜ EFGTFMGEF fi OF QSPUPDPM@OBNFEFGBVMU CMPDL ʜ !EF fi OFNFOUTCMPDL FOE ʜ FOE FOE MJCUPZDPMQSPUPDPMSC "TTJHOBIBTIPCKFDUUPBJOTUBODFWBSJBCMF!EF fi OFNFOUT 4UPSFUIFQSPUPDPMOBNFBTUIFLFZBOEUIFCMPDLEF fi OJOH UIFQSPUPDPMBTUIFWBMVFJOUIJTIBTIPCKFDU

Slide 89

Slide 89 text

1SPUPDPM fi MF4UPSFBEFUBJMFEEF fi OJUJPOGPSFBDI Toycol::Protocol.de fi ne(:rubylike) do request.path do |message| /['"](?.+)['"]/.match(message)[:path] end request.http_method do |message| case /\.(?[A-z]+)/.match(message)&.captures&. fi rst when "get" then "GET" else "OTHER" end end additional_request_methods "OTHER" custom_status_codes( 600 => "Hmm...", ) end 6TFS 1SPUPDPM fi MFSVCZMJLF &BDIMPHJDTEF fi OFEJOUIFTFCMPDLTJT TUPSFEJOFBDIWBSJBCMFTPG 5PZDPM1SPUPDPMDMBTT

Slide 90

Slide 90 text

NPEVMF5PZDPM DMBTT1SPUPDPM ʜ EFGTFMGSFRVFTU !SFRVFTUcc$MBTTOFXEP EFGTFMGQBUI CMPDL !QBUICMPDL FOE EFGTFMGIUUQ@NFUIPE CMPDL !IUUQ@NFUIPECMPDL FOE ʜ FOE FOE ʜ FOE FOE FH5PZDPM1SPUPDPMSFRVFTU4UPSFUIFEF fi OJUJPO MJCUPZDPMQSPUPDPMSC 'PSFYBNQMF5PZDPM1SPUPDPMSFRVFTU

Slide 91

Slide 91 text

NPEVMF5PZDPM DMBTT1SPUPDPM ʜ EFGTFMGSFRVFTU !SFRVFTUcc$MBTTOFXEP EFGTFMGQBUI CMPDL !QBUICMPDL FOE EFGTFMGIUUQ@NFUIPE CMPDL !IUUQ@NFUIPECMPDL FOE ʜ FOE FOE ʜ FOE FOE FH5PZDPM1SPUPDPMSFRVFTU4UPSFUIFEF fi OJUJPO MJCUPZDPMQSPUPDPMSC 5IJTJTGPSBTTJHOJOHBOBOPOZNPVTDMBTTUP !SFRVFTUPG5PZDPM1SPUPDPM 5IJTBOPOZNPVTDMBTTJTVTFEUPTUPSFFBDIMPHJDGPS QBSTJOHUIFSFRVFTUNFTTBHFJOJUTPXOJOTUBODFWBSJBCMF

Slide 92

Slide 92 text

FH5PZDPM1SPUPDPMSFRVFTU4UPSFUIFEF fi OJUJPO NPEVMF5PZDPM DMBTT1SPUPDPM ʜ EFGTFMGSFRVFTU !SFRVFTUcc$MBTTOFXEP EFGTFMGQBUI CMPDL !QBUICMPDL FOE EFGTFMGIUUQ@NFUIPE CMPDL !IUUQ@NFUIPECMPDL FOE ʜ FOE FOE ʜ FOE FOE MJCUPZDPMQSPUPDPMSC &BDIJOTUBODFWBSJBCMFPGUIJTBOPOZNPVT DMBTTTUPSFTBCMPDLPGMPHJDUPHFU UIFSFRVFTUQBUI )551NFUIPE FUD SFRVFTUQBUIEPcNFTTBHFc /['"](?.+)['"]/.match(message)[:path] end request.http_method do |message| case /\.(?[A-z]+)/.match(message)&.captures&. fi rst when "get" then "GET" else "OTHER" end end 6TFS 1SPUPDPM fi MFSVCZMJLF

Slide 93

Slide 93 text

FH5PZDPM1SPUPDPMSFRVFTU4UPSFUIFEF fi OJUJPO NPEVMF5PZDPM DMBTT1SPUPDPM ʜ EFGTFMGSFRVFTU !SFRVFTUcc$MBTTOFXEP EFGTFMGQBUI CMPDL !QBUICMPDL FOE EFGTFMGIUUQ@NFUIPE CMPDL !IUUQ@NFUIPECMPDL FOE ʜ FOE FOE ʜ FOE FOE MJCUPZDPMQSPUPDPMSC :PVDBOSFUSJFWFUIFTUPSFEMPHJDTCZFYFDVUJOHDBMMNFUIPE POFBDICMPDLTUPSFEJOUIFTFWBSJBCMFT 5PZDPM1SPUPDPMDMBTTIBTTPNFJOUFSGBDFTUIBU BMMPXTUIFTFUPCFDBMMFEBUBOZUJNF

Slide 94

Slide 94 text

FH5PZDPM1SPUPDPMSFRVFTU@QBUI3FUSJFWFUIFEF fi OJUJPO NPEVMF5PZDPM DMBTT1SPUPDPM ʜ EFGTFMGSFRVFTU@QBUI SFRVFTU@QBUISFRVFTUJOTUBODF@WBSJBCMF@HFU l!QBUIz DBMM SFRVFTU@NFTTBHF ʜ SFRVFTU@QBUI FOE FOE FOE MJCUPZDPMQSPUPDPMSC 'PSFYBNQMF5PZDPM1SPUPDPMSFRVFTU@QBUI

Slide 95

Slide 95 text

FH5PZDPM1SPUPDPMSFRVFTU@QBUI3FUSJFWFUIFEF fi OJUJPO NPEVMF5PZDPM DMBTT1SPUPDPM ʜ EFGTFMGSFRVFTU@QBUI SFRVFTU@QBUISFRVFTUJOTUBODF@WBSJBCMF@HFU l!QBUIz DBMM SFRVFTU@NFTTBHF ʜ SFRVFTU@QBUI FOE FOE FOE MJCUPZDPMQSPUPDPMSC 5IJTJTUIFNFUIPEUPHFUUIFSFRVFTUQBUI GSPNBSFRVFTUNFTTBHFBOE BMPHJDUPQBSTFUIFSFRVFTUNFTTBHF

Slide 96

Slide 96 text

FH5PZDPM1SPUPDPMSFRVFTU@QBUI3FUSJFWFUIFEF fi OJUJPO NPEVMF5PZDPM DMBTT1SPUPDPM ʜ EFGTFMGSFRVFTU@QBUI SFRVFTU@QBUISFRVFTUJOTUBODF@WBSJBCMF@HFU l!QBUIz DBMM SFRVFTU@NFTTBHF ʜ SFRVFTU@QBUI FOE FOE FOE MJCUPZDPMQSPUPDPMSC EFGBTTJHO@QBSTFE@BUUSJCVUFT ʜ !QBUI!QSPUPDPMSFRVFTU@QBUI ʜ FOE MJCUPZDPMQSPYZSC 5IFQSPYZTFSWFSVTFTUIJTNFUIPEUPSFUSJFWF UIFSFRVFTUQBUI XIFOUIFQSPYZTFSWFSCVJMET B)551GPSNBUUFESFRVFTUNFTTBHF

Slide 97

Slide 97 text

"GUFSUIF1SPUPDPM fi MFIBTCFFOMPBEFE UIFBQQMJDBUJPO TFMFDUTXIJDIQSPUPDPMUPVTF $MJFOU 1SPYZ4FSWFS "QQMJDBUJPO UPZDPMTFSWFS 4FMFDUXIJDIQSPUPDPMUPVTF DMBTT1SPUPDPM 1SPUPDPM%F fi OJUJPO

Slide 98

Slide 98 text

"QQMJDBUJPO4FMFDUXIJDIQSPUPDPMUPVTF require "rack" require "toycol" Toycol::Protocol.use(:rubylike) class App def call(env) case env["REQUEST_METHOD"] when “GET” [200, { "Content-Type" => "text/html" }, [“I love Ruby!”\n”, ”I love RubyKaigi!\n”]] when “OTHER” [600, { "Content-Type" => "text/html" }, [“Sorry, but I'd like you to speak more like a Ruby programmer…”]] end end end run App.new DPO fi H@SVCZJMLFSV 1BTTUIFQSPUPDPMOBNFZPVXBOUUPVTFUP 5PZDPM1SPUPDPMVTF

Slide 99

Slide 99 text

NPEVMF5PZDPM DMBTT1SPUPDPM ʜ EFGTFMGVTF QSPUPDPM@OBNFEFGBVMU !QSPUPDPM@OBNFQSPUPDPM@OBNF FOE ʜ FOE FOE 5PZDPM1SPUPDPMVTF4UPSFUIFQSPUPDPMOBNF MJCUPZDPMQSPUPDPMSC 5PZDPM1SPUPDPMVTF

Slide 100

Slide 100 text

5SBOTMBUFBNFTTBHFXJUIQSPUPDPMUPVTF 'JOBMMZ USBOTMBUFUIFSFRVFTUNFTTBHFVTJOHUIFQSPUPDPM ZPVEF fi OFE $MJFOU 1SPYZ4FSWFS "QQMJDBUJPO UPZDPMTFSWFS DMBTT1SPUPDPM 1SPUPDPM%F fi OJUJPO

Slide 101

Slide 101 text

def start … loop do trap(:INT) { shutdown } @client = @proxy.accept while [email protected]? && [email protected]? begin … safe_execution! { @protocol.run!(request) } assign_parsed_attributes! http_request_message = build_http_request_message … end end @client.close end end MJCUPZDPMQSPYZSC 5PZDPM1SPYZTUBSU"QQMZUIFQSPUPDPM 5PZDPM1SPYZTUBSUFYFDVUFT UIFQSPUPDPMUSBOTMBUJPO

Slide 102

Slide 102 text

def start … loop do trap(:INT) { shutdown } @client = @proxy.accept while [email protected]? && [email protected]? begin … safe_execution! { @protocol.run!(request) } assign_parsed_attributes! http_request_message = build_http_request_message … end end @client.close end end !QSPUPDPM5PZDPM1SPUPDPM MJCUPZDPMQSPYZSC 5PZDPM1SPYZTUBSU"QQMZUIFQSPUPDPM &YFDVUF5PZDPM1SPUPDPMSVO UIFOUIFQSPUPDPMXJMMCFBQQMJFE UPUIFSFRVFTUNFTTBHF

Slide 103

Slide 103 text

NPEVMF5PZDPM DMBTT1SPUPDPM ʜ EFGTFMGSVO NFTTBHF !SFRVFTU@NFTTBHFNFTTBHFDIPNQ SFUVSOVOMFTT CMPDL!EF fi OFNFOUT JOTUBODF@FYFD !SFRVFTU@NFTTBHF CMPDL FOE ʜ FOE FOE 5PZDPM1SPUPDPMSVO"QQMZUIFQSPUPDPM MJCUPZDPMQSPUPDPMSC 5PZDPM1SPUPDPMSVO

Slide 104

Slide 104 text

NPEVMF5PZDPM DMBTT1SPUPDPM ʜ EFGTFMGSVO NFTTBHF !SFRVFTU@NFTTBHFNFTTBHFDIPNQ SFUVSOVOMFTT CMPDL!EF fi OFNFOUT JOTUBODF@FYFD !SFRVFTU@NFTTBHF CMPDL FOE ʜ FOE FOE 5PZDPM1SPYZTUBSU"QQMZUIFQSPUPDPM MJCUPZDPMQSPUPDPMSC 'JOEUIFQSPUPDPMEF fi OJUJPO DPSSFTQPOEJOHUP!QSPUPDPM@OBNF JO!EF fi OFNFOUTIBTI

Slide 105

Slide 105 text

NPEVMF5PZDPM DMBTT1SPUPDPM ʜ EFGTFMGSVO NFTTBHF !SFRVFTU@NFTTBHFNFTTBHFDIPNQ SFUVSOVOMFTT CMPDL!EF fi OFNFOUT JOTUBODF@FYFD !SFRVFTU@NFTTBHF CMPDL FOE ʜ FOE FOE 5PZDPM1SPYZTUBSU"QQMZUIFQSPUPDPM MJCUPZDPMQSPUPDPMSC &YFDVUFUIJTCMPDLJOJOTUBODF@FYFD 5IFSFRVFTUNFTTBHFQBTTFEBT UIFBSHVNFOUXJMMCFUSBOTMBUFE

Slide 106

Slide 106 text

def start … loop do trap(:INT) { shutdown } @client = @proxy.accept while [email protected]? && [email protected]? begin … safe_execution! { @protocol.run!(request) } assign_parsed_attributes! http_request_message = build_http_request_message … end end @client.close end end MJCUPZDPMQSPYZSC 5PZDPM1SPYZTUBSU#VJMEBSFRVFTUNFTTBHF 5IFOFYFDVUF5PZDPM1SPYZBTTJHO@QBSTFE@BUUSJCVUFT BOE5PZDPM1SPYZCVJME@IUUQ@SFRVFTU@NFTTBHFUP CVJMEB)551GPSNBUUFESFRVFTUNFTTBHF

Slide 107

Slide 107 text

NPEVMF5PZDPM DMBTT1SPUPDPM … def assign_parsed_attibutes @request_method = @protocol.request_method @path = @protocol.request_path @query = @protocol.query @input = @protocol.input end … end end MJCUPZDPMQSPYZSC 5PZDPM1SPYZBTTJHO@QBSTFE@BUUSJCVUFT#VJMEBSFRVFTUNFTTBHF 5PZDPM1SPYZBTTJHO@QBSTFE@BUUSJCVUFTFYUSBDUT WBMVFTTUPSFEJO5PZDPM1SPUPDPMDMBTT "OEBTTJHOTUIFNUPFBDIJOTUBODFWBSJBCMFT

Slide 108

Slide 108 text

NPEVMF5PZDPM DMBTT1SPUPDPM … def build_http_request_message request_message = "#{request_line}#{request_header}\r\n" request_message += @input if @input request_message end … end end MJCUPZDPMQSPYZSC 5PZDPM1SPYZCVJME@IUUQ@SFRVFTU@NFTTBHF#VJMEBSFRVFTUNFTTBHF 5PZDPM1SPYZCVJME@IUUQ@SFRVFTU@NFTTBHFCVJMET B)551GPSNBUUFESFRVFTUNFTTBHF VTJOHUIPTFJOTUBODFWBSJBCMFT

Slide 109

Slide 109 text

NPEVMF5PZDPM DMBTT1SPUPDPM … def build_http_request_message request_message = "#{request_line}#{request_header}\r\n" request_message += @input if @input request_message end … end end MJCUPZDPMQSPYZSC 5PZDPM1SPYZCVJME@IUUQ@SFRVFTU@NFTTBHF#VJMEBSFRVFTUNFTTBHF FH 5PZDPM1SPYZCVJME@IUUQ@SFRVFTU@NFTTBHFSFUVSOT BWBMVFMJLF (&5QPTUT)551aSaO$POUFOU-FOHUIaSaOaSaO "#{@request_method} #{request_path} HTTP/1.1\r\n" “#{@path}#{"?#{@query}" if @query && [email protected]?}" "Content-Length: #{@input&.bytesize || 0}\r\n"

Slide 110

Slide 110 text

"EWBODFEQSPUPDPMEF fi OJUJPOT

Slide 111

Slide 111 text

-FUTDPOTJEFSTPNFNPSF BEWBODFEEF fi OJUJPOTPGQSPUPDPM

Slide 112

Slide 112 text

-FU`TDPOTJEFSBHBJO3VCZMJLFQSPUPDPM XFKVTUEF fi OFE 5IJTQSPUPDPMUBLFTB3VCZMJLFTZOUBY SFRVFTUNFTTBHFBTBTUSJOH QBSTFTJU BOEUSBOTMBUFTJUJOUP B)551GPSNBUUFESFRVFTUNFTTBHF

Slide 113

Slide 113 text

'PSFYBNQMF JGZPVSFDFJWFBTUSJOH lbQPTUT`HFUz BTBSFRVFTUNFTTBHF XJUIUIF3VCZMJLFQSPUPDPMʜ

Slide 114

Slide 114 text

3VCZMJLFQSPUPDPM1BSTJOHUIFTUSJOHlbQPTUT`HFUz Toycol::Protocol.de fi ne(:rubylike) do request.path do |message| /['"](?.+)['"]/.match(message)[:path] end request.http_method do |message| case /\.(?[A-z]+)/.match(message)&.captures&. fi rst when "get" then "GET" else "OTHER" end end … end 6TFS 1SPUPDPM fi MFSVCZMJLF 1BSTFUIFTUSJOHlbQPTUTHFUzUPHFUBSFRVFTUQBUI BOESFRVFTUNFUIPE TUPSFUIFNJO5PZDPM1SPUPDPM DMBTT BOEUSBOTMBUFUIFNUP)551GPSNBU lQPTUTzBTBSFRVFTUQBUI l(&5zBTBSFRVFTUNFUIPE

Slide 115

Slide 115 text

8IBUBCPVUBQSPUPDPMUIBUDBOSFDFJWF BOEFYFDVUFUIFSFRVFTUNFTTBHF BTBOBDUVBM3VCZTDSJQU SBUIFSUIBOBTBTUSJOH

Slide 116

Slide 116 text

'PSFYBNQMF JGZPVSFDFJWFB3VCZTDSJQU bQPTUT`HFU UIBUDBMMTBNFUIPEHFU POB4USJOHPCKFDUbQPTUT` BTBSFRVFTUNFTTBHFʜ

Slide 117

Slide 117 text

Toycol::Protocol.de fi ne(:ruby) do |message| using Module.new { re fi ne String do def get Toycol::Protocol.request.path { self } Toycol::Protocol.request.http_method { "GET" } end end } instance_eval message end 3VCZQSPUPDPM 6TFS 1SPUPDPM fi MFSVCZ 5IJTJTBEF fi OJUJPOPG3VCZQSPUPDPM UIBUJTCFBCMFUPFYFDVUF BSFRVFTUNFTTBHFBTB3VCZTDSJQU 3VCZQSPUPDPM

Slide 118

Slide 118 text

3VCZQSPUPDPM Toycol::Protocol.de fi ne(:ruby) do |message| using Module.new { re fi ne String do def get Toycol::Protocol.request.path { self } Toycol::Protocol.request.http_method { "GET" } end end } instance_eval message end 6TFS 1SPUPDPM fi MFSVCZ "EEHFUNFUIPEUP4USJOHDMBTTUPCFBCMF UPDBMMJUGPSlQPTUTzBTB4USJOHPCKFDU

Slide 119

Slide 119 text

Toycol::Protocol.de fi ne(:ruby) do |message| using Module.new { re fi ne String do def get Toycol::Protocol.request.path { self } Toycol::Protocol.request.http_method { "GET" } end end } instance_eval message end 3VCZQSPUPDPM 6TFS 1SPUPDPM fi MFSVCZ 5IFOVTFJOTUBODF@FWBMUPFYFDVUF UIFSFDFJWFESFRVFTUNFTTBHF lQPTUTzHFU BTB3VCZTDSJQU lQPTUTzHFU

Slide 120

Slide 120 text

)PXFWFS BTZPVDBOTFF UIJTMPHJD DPOUBJOTBOJOKFDUJPOWVMOFSBCJMJUZ 5IFSFJTOPXBZUPQSFWFOU UIFFYFDVUJPOPGBEBOHFSPVTTDSJQU XIFOJUJTSFDFJWFE TVDIBTTZTUFN lSNSGz

Slide 121

Slide 121 text

6OGPSUVOBUFMZ XFEPOULOPX XIBULJOEPGNFTTBHFT UIFDMJFOUXJMMTFOEUPUIFTFSWFS 5IFSFGPSF 5PZDPMEPFTOPUBMMPXUP XSJUFDPEFTDPOUBJOJOHTVDI WVMOFSBCJMJUJFTJO1SPUPDPM fi MF

Slide 122

Slide 122 text

def start … while [email protected]? && [email protected]? begin request = @client.readpartial(CHUNK_SIZE) logger “Received message: #{request.inspect.chomp}” safe_execution! { @protocol.run!(request) } … end end … end MJCUPZDPMQSPYZSC 4BGFFYFDVUJPOPGUIFQSPUPDPM 5PZDPM1SPUPDPMSVOJTFYFDVUFEJOTJEF BCMPDLPGTBGF@FYFDVUJPOUPFOTVSFUIBU OPWVMOFSBCMFEF fi OJUJPOTBSFJO1SPUPDPM fi MFT

Slide 123

Slide 123 text

def safe_execution!(&block) safe_executionable_tp.enable(&block) end def safe_executionable_tp @safe_executionable_tp ||= TracePoint.new(:script_compiled) do |tp| if tp.binding.receiver == Protocol \ && tp.method_id.to_s.match? /(.*eval|.*exec|`.+|%x\(|system|open|require|load)/ raise UnauthorizeError, … end end end 5PZDPM)FMQFSTBGF@FYFDVUJPO MJCUPZDPMIFMQFSSC 5PZDPM)FMQFSTBGF@FYFDVUJPO "OE5PZDPM)FMQFSTBGF@FYFDVUJPOBCMF@UQ UIBUTBGF@FYFDVUJPOVTFTJOUFSOBMMZ

Slide 124

Slide 124 text

def safe_execution!(&block) safe_executionable_tp.enable(&block) end def safe_executionable_tp @safe_executionable_tp ||= TracePoint.new(:script_compiled) do |tp| if tp.binding.receiver == Protocol \ && tp.method_id.to_s.match? /(.*eval|.*exec|`.+|%x\(|system|open|require|load)/ raise UnauthorizeError, … end end end 5PZDPM)FMQFSTBGF@FYFDVUJPO MJCUPZDPMIFMQFSSC 6TF5SBDF1PJOUUPEFUFDUJGBOZEBOHFSPVT NFUIPETBSFCFJOHFYFDVUFEUIBUDPVME DBVTFJOKFDUJPOWVMOFSBCJMJUJFTɹ

Slide 125

Slide 125 text

def safe_execution!(&block) safe_executionable_tp.enable(&block) end def safe_executionable_tp @safe_executionable_tp ||= TracePoint.new(:script_compiled) do |tp| if tp.binding.receiver == Protocol \ && tp.method_id.to_s.match? /(.*eval|.*exec|`.+|%x\(|system|open|require|load)/ raise UnauthorizeError, … end end end 5PZDPM)FMQFSTBGF@FYFDVUJPO MJCUPZDPMIFMQFSSC 5BSHFUNFUIPETBSFJODMVEJOHFWBMPSFYFD JOUIBUOBNF FYFDVUJOHFYUFSOBMDPNNBOET BOEMPBEJOH fi MFTGSPNPVUTJEF

Slide 126

Slide 126 text

4P XFOFFEUPDPOTJEFSPG BNPSFTFDVSFXBZUPEF fi OFBQSPUPDPM UPSVOUIFBQQMJDBUJPO XJUI3VCZTDSJQUTBTSFRVFTUNFTTBHFT

Slide 127

Slide 127 text

)PXBCPVUUIJT

Slide 128

Slide 128 text

'PSFYBNQMF BTCFGPSF JGZPVSFDFJWFB3VCZTDSJQU bQPTUT`HFU UIBUDBMMTBNFUIPEHFU POB4USJOHPCKFDUbQPTUT` BTBSFRVFTUNFTTBHFʜ

Slide 129

Slide 129 text

4BGF3VCZQSPUPDPM module SafeRuby PARSER_REGEX = /["'](?\/.*)["']\.(?[A-z]+)/ end Toycol::Protocol.de fi ne(:safe_ruby) do |message| using Module.new { re fi ne String do def get Toycol::Protocol.request.http_method { “GET" } end end } path, method = SafeRuby::PARSER_REGEX.match(message) { |m| [m[:path], m[:method]] } request.path { path } request_path.public_send(method) end 6TFS 1SPUPDPM fi MFTBGF@SVCZ 4BGF3VCZQSPUPDPM

Slide 130

Slide 130 text

module SafeRuby PARSER_REGEX = /["'](?\/.*)["']\.(?[A-z]+)/ end Toycol::Protocol.de fi ne(:safe_ruby) do |message| using Module.new { re fi ne String do def get Toycol::Protocol.request.http_method { “GET" } end end } path, method = SafeRuby::PARSER_REGEX.match(message) { |m| [m[:path], m[:method]] } request.path { path } request_path.public_send(method) end 4BGF3VCZQSPUPDPM"EEBQBSTFS3FHFY 6TFS 1SPUPDPM fi MFTBGF@SVCZ 1SFQBSFBSFHVMBSFYQSFTTJPOUPQBSTF UIFSFRVFTUNFTTBHF

Slide 131

Slide 131 text

module SafeRuby PARSER_REGEX = /["'](?\/.*)["']\.(?[A-z]+)/ end Toycol::Protocol.de fi ne(:safe_ruby) do |message| using Module.new { re fi ne String do def get Toycol::Protocol.request.http_method { “GET" } end end } path, method = SafeRuby::PARSER_REGEX.match(message) { |m| [m[:path], m[:method]] } request.path { path } request_path.public_send(method) end 6TJOHUIJTSFHVMBSFYQSFTTJPO HFUUXPTUSJOHT ᶃQBUIlQPTUTz "SFRVFTUQBUI ᶄNFUIPElHFUz "NFUIPEOBNFUPCFDBMMFEGPSUIFSFRVFTUQBUI 4BGF3VCZQSPUPDPM(FUBSFRVFTUQBUINFUIPE 6TFS 1SPUPDPM fi MFTBGF@SVCZ ᶃ ᶄ

Slide 132

Slide 132 text

module SafeRuby PARSER_REGEX = /["'](?\/.*)["']\.(?[A-z]+)/ end Toycol::Protocol.de fi ne(:safe_ruby) do |message| using Module.new { re fi ne String do def get Toycol::Protocol.request.http_method { “GET" } end end } path, method = SafeRuby::PARSER_REGEX.match(message) { |m| [m[:path], m[:method]] } request.path { path } request_path.public_send(method) end 1SPUPDPM fi MFTBGF@SVCZ 4BGF3VCZQSPUPDPM4UPSFUIFSFRVFTUQBUI 4UPSFlQPTUTzBTBSFRVFTUQBUI JO5PZDPM1SPUPDPMSFRVFTUQBUI

Slide 133

Slide 133 text

module SafeRuby PARSER_REGEX = /["'](?\/.*)["']\.(?[A-z]+)/ end Toycol::Protocol.de fi ne(:safe_ruby) do |message| using Module.new { re fi ne String do def get Toycol::Protocol.request.http_method { “GET" } end end } path, method = SafeRuby::PARSER_REGEX.match(message) { |m| [m[:path], m[:method]] } request.path { path } request_path.public_send(method) end 1SPUPDPM fi MFTBGF@SVCZ 4BGF3VCZQSPUPDPM3FUSJFWFUIFSFRVFTUQBUI 5IFO 5PZDPM1SPUPDPMSFRVFTU@QBUI SFUVSOTB4USJOHPCKFDUlQPTUTz KVTUTUPSFEBTBSFRVFTUQBUI

Slide 134

Slide 134 text

module SafeRuby PARSER_REGEX = /["'](?\/.*)["']\.(?[A-z]+)/ end Toycol::Protocol.de fi ne(:safe_ruby) do |message| using Module.new { re fi ne String do def get Toycol::Protocol.request.http_method { “GET" } end end } path, method = SafeRuby::PARSER_REGEX.match(message) { |m| [m[:path], m[:method]] } request.path { path } request_path.public_send(method) end 1SPUPDPM fi MFTBGF@SVCZ 4BGF3VCZQSPUPDPM"EEHFUUP4USJOHDMBTT "EEHFUNFUIPEUPUIF4USJOHDMBTT 5IJTJTUPTUPSFBTUSJOH(&5JO 5PZDPM1SPUPDPMSFRVFTUIUUQ@NFUIPE

Slide 135

Slide 135 text

module SafeRuby PARSER_REGEX = /["'](?\/.*)["']\.(?[A-z]+)/ end Toycol::Protocol.de fi ne(:safe_ruby) do |message| using Module.new { re fi ne String do def get Toycol::Protocol.request.http_method { “GET" } end end } path, method = SafeRuby::PARSER_REGEX.match(message) { |m| [m[:path], m[:method]] } request.path { path } request_path.public_send(method) end 1SPUPDPM fi MFTBGF@SVCZ 4BGF3VCZQSPUPDPM$BMMHFUGPSlQPTUTz $BMMUIFHFUNFUIPEPOUIF4USJOHPCKFDUlQPTUTz &YFDVUJOHUIJTMJOFXJMMHJWFZPVUIFTBNFSFTVMU BTFYFDVUJOHUIFSFRVFTUNFTTBHFlQPTUTzHFU

Slide 136

Slide 136 text

-FUTUSZUIJTPVU

Slide 137

Slide 137 text

require "rack" require "toycol" Toycol::Protocol.use(:safe_ruby) class App def call(env) case env["REQUEST_METHOD"] when “GET” [200, { "Content-Type" => "text/html" }, [“User<1> I love Ruby!\n”, “User<2> I love RubyKaigi!\n”]] end end end run App.new )FSFJTBOBQQMJDBUJPO fi MFGPSUIJTQSPKFDU 6TFS DPO fi H@TBGF@SVCZSV 3VO4BGF3VCZQSPUPDPM

Slide 138

Slide 138 text

4FOEBSFRVFTUNFTTBHFCZ4BGF3VCZQSPUPDPM 4UBSUVQUIFTFSWFST 3VO4BGF3VCZQSPUPDPM

Slide 139

Slide 139 text

*UXPSLFE 3VO4BGF3VCZQSPUPDPM

Slide 140

Slide 140 text

/PX MFUTUSZ4BGF3VCZQSPUPDPMJO TPNFBQQMJDBUJPOTCVJMUXJUIPUIFSXBZT

Slide 141

Slide 141 text

8IBUBCPVUBOBQQMJDBUJPOCVJMUXJUI 4JOBUSB

Slide 142

Slide 142 text

require “sinatra/base" require "toycol" Toycol::Protocol.use(:safe_ruby) class App < Sinatra::Base get “/posts” do [“User<1> I love Ruby!\n”, “User<2> I love RubyKaigi!\n”] end run! if app_ fi le == $PROGRAM_NAME end 6TFS BQQSC 3VO4BGF3VCZQSPUPDPMXJUIB4JOBUSBBQQ 4JOBUSBBQQGPS4BGF3VCZQSPUPDPM

Slide 143

Slide 143 text

3VO4BGF3VCZQSPUPDPMXJUIB4JOBUSBBQQ 4FOEBSFRVFTUNFTTBHFCZ4BGF3VCZQSPUPDPM 4UBSUVQUIFTFSWFST

Slide 144

Slide 144 text

"HBJO JUXPSLFE 3VO4BGF3VCZQSPUPDPMXJUIB4JOBUSBBQQ

Slide 145

Slide 145 text

'JOBMMZ MFUTHFUB3BJMTBQQMJDBUJPO SVOOJOHXJUIPVS4BGF3VCZQSPUPDPM

Slide 146

Slide 146 text

require_relative “con fi g/environment" require "toycol" Toycol::Protocol.use(:safe_ruby) run! Rails.application Rails.application.load_server 6TFS DPO fi HSV 4BGF3VCZQSPUPDPMXJUIB3BJMTBQQ "3BJMTBQQGPS4BGF3VCZQSPUPDPM SBJMTHFOFSBUFTDB ff PMEQPTUT DPNNBOEIBTCFFOFYFDVUFE

Slide 147

Slide 147 text

4BGF3VCZQSPUPDPMXJUIB3BJMTBQQ 4FOEBSFRVFTUNFTTBHFCZ4BGF3VCZQSPUPDPM 4UBSUVQUIFTFSWFST

Slide 148

Slide 148 text

"OEBHBJO JUXPSLFE XJUIMPUTPGIFBEFST 4BGF3VCZQSPUPDPMXJUIB3BJMTBQQ ʜ

Slide 149

Slide 149 text

:PVDBOBMTPTFFUIFCPEZ 4BGF3VCZQSPUPDPMXJUIB3BJMTBQQ

Slide 150

Slide 150 text

"TZPVDBOTFF XFXFSFBCMFUPSVO BWBSJFUZPGBQQMJDBUJPOT XJUI4BGF3VCZQSPUPDPM

Slide 151

Slide 151 text

*OBEEJUJPO ZPVDBO fi OEFYBNQMFTPG HFUUJOHRVFSZQBSBNFUFST BOEIBOEMJOH1045NFUIPET JOUIF5PZDPMSFQPTJUPSZ 1MFBTFFOKPZUIFNJGZPVMJLF IUUQTHJUIVCDPNTIJPJNNUPZDPMCMPCNBJOFYBNQMFT

Slide 152

Slide 152 text

"OETQFDJBMUIBOLTUP !PLVSBNBTBGVNJ !VE[VSB'VLVPLBSC 5IBOLZPVGPSZPVSBUUFOUJPO