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

Toycol: Define your own application protocol

Toycol: Define your own application protocol

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

Other Decks in Programming

Transcript

  1. .JTBLJ4IJPJ TIJPJNN!DPF@

    4FQ
    3VCZ,BJHJ5BLFPVU
    5PZDPM
    %F
    fi
    OFZPVSPXOBQQMJDBUJPOQSPUPDPM

    View full-size slide

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

    View full-size slide

  3. "CPVUNF
    IUUQTSVCZLBJHJPSH
    ʜBOEXBTBIFMQFSTUB
    ff

    BU3VCZ,BJHJJO'VLVPLB

    View full-size slide

  4. *`NWFSZIBQQZUPCFBTQFBLFSBU
    3VCZ,BJHJ5BLFPVU

    View full-size slide

  5. 8IBUEPZPVMJLFBCPVU
    5$1*1QSPUPDPMTUBDL
    *ONZPQJOJPOʜ

    View full-size slide

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

    View full-size slide

  7. 8IBU*MJLFBCPVU5$1*1QSPUPDPMTUBDLᶄ
    /FUXPSLOPEF
    Application Layer
    Transport Layer
    Internet Layer
    Link Layer
    /FUXPSLOPEF
    Application Layer
    Transport Layer
    Internet Layer
    Link Layer

    5IFGBDUUIBUMBZFSTPGUIFTBNFMFWFMPGUIFBCTUSBDUJPO
    DPNNVOJDBUFXJUIFBDIPUIFSVTJOHUIFTBNFQSPUPDPM

    View full-size slide

  8. 4P XIBUJTB
    JOUIFDPOUFYUPGDPNQVUFSOFUXPSL
    QSPUPDPM

    View full-size slide

  9. *UJTBTFUPGSVMFTGPSDPNNVOJDBUJPO
    CFUXFFOOFUXPSLOPEFT

    View full-size slide

  10. '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

    View full-size slide

  11. '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
    ˕

    View full-size slide

  12. '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

    View full-size slide

  13. '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

    View full-size slide

  14. '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
    ˕

    View full-size slide

  15. 4P
    *IBWFDSFBUFEBTNBMMGSBNFXPSL
    UIBUBMMPXTZPVUPDSFBUF
    ZPVSPXOQSPUPDPMGPSDPNNVOJDBUJPO
    CFUXFFOBDMJFOUBOEBTFSWFSPO888
    JOTUFBEPG)551

    View full-size slide

  16. *OUIJTGSBNFXPSL
    UIFQSPUPDPMZPVEF
    fi
    OFXPSLTBT
    BXSBQQFSGPSUIF)551
    BOEDBOCFVTFEUPSVOBQQMJDBUJPOT

    View full-size slide

  17. -FUTTFFIPXJUXPSLT

    View full-size slide

  18. FH%VDLQSPUPDPM

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  21. *UHPFTMJLFUIJT

    View full-size slide

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

    View full-size slide

  23. $ 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

    View full-size slide

  24. $ 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

    View full-size slide

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

    View full-size slide

  26. 'PSUIJTSFBTPO
    *OBNFEUIJTGSBNFXPSLBTGPMMPXT

    View full-size slide

  27. 5PZ1SPUPDPM
    5PZDPM

    View full-size slide

  28. 5PZ1SPUPDPM
    5PZDPM
    IUUQTHJUIVCDPNTIJPJNNUPZDPM

    View full-size slide

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

    View full-size slide

  30. 5PEBZ *XPVMEMJLFUPTIBSFJUXJUIZPV

    View full-size slide

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

    View full-size slide

  32. )PXUPVTF5PZDPM
    XJUIBFYBNQMFPGTJNQMFEF
    fi
    OJUJPOT

    View full-size slide

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

    View full-size slide

  34. 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

    View full-size slide

  35. ᶃ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

    View full-size slide

  36. ᶄ%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

    View full-size slide

  37. 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

    View full-size slide

  38. 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

    View full-size slide

  39. 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

    View full-size slide

  40. 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

    View full-size slide

  41. 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

    View full-size slide

  42. ᶅ#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

    View full-size slide

  43. 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

    View full-size slide

  44. 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

    View full-size slide

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

    View full-size slide

  46. -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

    View full-size slide

  47. -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

    View full-size slide

  48. *OUFSOBMJNQMFNFOUBUJPOPG5PZDPM

    View full-size slide

  49. /PXMFU`TFYQMPSFUIFJOTJEFPG5PZDPM
    GSPNUXPBTQFDUT
    5IFOFUXPSLDPNNVOJDBUJPO
    fl
    PX
    )PXUPUSBOTMBUFBSFRVFTUNFTTBHF

    View full-size slide

  50. 5IFOFUXPSLDPNNVOJDBUJPO
    fl
    PX

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  54. 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

    View full-size slide

  55. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  58. 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

    View full-size slide

  59. 28IZTIPVMEXFVTFCPUI
    BQSPYZTFSWFSBOEBCBDLHSPVOETFSWFS

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  63. 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

    View full-size slide

  64. 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

    View full-size slide

  65. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  68. 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

    View full-size slide

  69. 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

    View full-size slide

  70. 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

    View full-size slide

  71. 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ʜ

    View full-size slide

  72. 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

    View full-size slide

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

    View full-size slide

  74. 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

    View full-size slide

  75. )PXUPUSBOTMBUFBSFRVFTUNFTTBHF

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  78. 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

    View full-size slide

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

    View full-size slide

  80. 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

    View full-size slide

  81. 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

    View full-size slide

  82. 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

    View full-size slide

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

    View full-size slide

  84. 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

    View full-size slide

  85. 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

    View full-size slide

  86. 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

    View full-size slide

  87. 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

    View full-size slide

  88. 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

    View full-size slide

  89. NPEVMF5PZDPM
    DMBTT1SPUPDPM
    ʜ
    EFGTFMGSFRVFTU
    !SFRVFTUcc$MBTTOFXEP
    EFGTFMGQBUI CMPDL

    !QBUICMPDL
    FOE
    EFGTFMGIUUQ@NFUIPE CMPDL

    !IUUQ@NFUIPECMPDL
    FOE
    ʜ
    FOE
    FOE
    ʜ
    FOE
    FOE
    FH5PZDPM1SPUPDPMSFRVFTU4UPSFUIFEF
    fi
    OJUJPO
    MJCUPZDPMQSPUPDPMSC
    'PSFYBNQMF5PZDPM1SPUPDPMSFRVFTU

    View full-size slide

  90. 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

    View full-size slide

  91. 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

    View full-size slide

  92. 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

    View full-size slide

  93. 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

    View full-size slide

  94. 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

    View full-size slide

  95. 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

    View full-size slide

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

    View full-size slide

  97. "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

    View full-size slide

  98. NPEVMF5PZDPM
    DMBTT1SPUPDPM
    ʜ
    EFGTFMGVTF QSPUPDPM@OBNFEFGBVMU

    !QSPUPDPM@OBNFQSPUPDPM@OBNF
    FOE
    ʜ
    FOE
    FOE
    5PZDPM1SPUPDPMVTF4UPSFUIFQSPUPDPMOBNF
    MJCUPZDPMQSPUPDPMSC
    5PZDPM1SPUPDPMVTF

    View full-size slide

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

    View full-size slide

  100. 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

    View full-size slide

  101. 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

    View full-size slide

  102. NPEVMF5PZDPM
    DMBTT1SPUPDPM
    ʜ
    EFGTFMGSVO NFTTBHF

    !SFRVFTU@NFTTBHFNFTTBHFDIPNQ
    SFUVSOVOMFTT CMPDL!EF
    fi
    OFNFOUT

    JOTUBODF@FYFD !SFRVFTU@NFTTBHF CMPDL

    FOE
    ʜ
    FOE
    FOE
    5PZDPM1SPUPDPMSVO"QQMZUIFQSPUPDPM
    MJCUPZDPMQSPUPDPMSC
    5PZDPM1SPUPDPMSVO

    View full-size slide

  103. 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

    View full-size slide

  104. 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

    View full-size slide

  105. 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

    View full-size slide

  106. 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

    View full-size slide

  107. 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

    View full-size slide

  108. 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"

    View full-size slide

  109. "EWBODFEQSPUPDPMEF
    fi
    OJUJPOT

    View full-size slide

  110. -FUTDPOTJEFSTPNFNPSF
    BEWBODFEEF
    fi
    OJUJPOTPGQSPUPDPM

    View full-size slide

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

    View full-size slide

  112. 'PSFYBNQMF
    JGZPVSFDFJWFBTUSJOH
    lbQPTUT`HFUz
    BTBSFRVFTUNFTTBHF
    XJUIUIF3VCZMJLFQSPUPDPMʜ

    View full-size slide

  113. 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

    View full-size slide

  114. 8IBUBCPVUBQSPUPDPMUIBUDBOSFDFJWF
    BOEFYFDVUFUIFSFRVFTUNFTTBHF
    BTBOBDUVBM3VCZTDSJQU
    SBUIFSUIBOBTBTUSJOH

    View full-size slide

  115. 'PSFYBNQMF
    JGZPVSFDFJWFB3VCZTDSJQU
    bQPTUT`HFU
    UIBUDBMMTBNFUIPEHFU
    POB4USJOHPCKFDUbQPTUT`
    BTBSFRVFTUNFTTBHFʜ

    View full-size slide

  116. 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

    View full-size slide

  117. 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

    View full-size slide

  118. 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

    View full-size slide

  119. )PXFWFS BTZPVDBOTFF UIJTMPHJD
    DPOUBJOTBOJOKFDUJPOWVMOFSBCJMJUZ
    5IFSFJTOPXBZUPQSFWFOU
    UIFFYFDVUJPOPGBEBOHFSPVTTDSJQU
    XIFOJUJTSFDFJWFE
    TVDIBTTZTUFN lSNSGz

    View full-size slide

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

    View full-size slide

  121. 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

    View full-size slide

  122. 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

    View full-size slide

  123. 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ɹ

    View full-size slide

  124. 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

    View full-size slide

  125. 4P XFOFFEUPDPOTJEFSPG
    BNPSFTFDVSFXBZUPEF
    fi
    OFBQSPUPDPM
    UPSVOUIFBQQMJDBUJPO
    XJUI3VCZTDSJQUTBTSFRVFTUNFTTBHFT

    View full-size slide

  126. )PXBCPVUUIJT

    View full-size slide

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

    View full-size slide

  128. 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

    View full-size slide

  129. 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

    View full-size slide

  130. 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
    ᶃ ᶄ

    View full-size slide

  131. 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

    View full-size slide

  132. 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

    View full-size slide

  133. 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

    View full-size slide

  134. 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

    View full-size slide

  135. -FUTUSZUIJTPVU

    View full-size slide

  136. 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

    View full-size slide

  137. 4FOEBSFRVFTUNFTTBHFCZ4BGF3VCZQSPUPDPM
    4UBSUVQUIFTFSWFST
    3VO4BGF3VCZQSPUPDPM

    View full-size slide

  138. *UXPSLFE
    3VO4BGF3VCZQSPUPDPM

    View full-size slide

  139. /PX MFUTUSZ4BGF3VCZQSPUPDPMJO
    TPNFBQQMJDBUJPOTCVJMUXJUIPUIFSXBZT

    View full-size slide

  140. 8IBUBCPVUBOBQQMJDBUJPOCVJMUXJUI
    4JOBUSB

    View full-size slide

  141. 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

    View full-size slide

  142. 3VO4BGF3VCZQSPUPDPMXJUIB4JOBUSBBQQ
    4FOEBSFRVFTUNFTTBHFCZ4BGF3VCZQSPUPDPM
    4UBSUVQUIFTFSWFST

    View full-size slide

  143. "HBJO JUXPSLFE
    3VO4BGF3VCZQSPUPDPMXJUIB4JOBUSBBQQ

    View full-size slide

  144. 'JOBMMZ MFUTHFUB3BJMTBQQMJDBUJPO
    SVOOJOHXJUIPVS4BGF3VCZQSPUPDPM

    View full-size slide

  145. 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

    View full-size slide

  146. 4BGF3VCZQSPUPDPMXJUIB3BJMTBQQ
    4FOEBSFRVFTUNFTTBHFCZ4BGF3VCZQSPUPDPM
    4UBSUVQUIFTFSWFST

    View full-size slide

  147. "OEBHBJO JUXPSLFE
    XJUIMPUTPGIFBEFST

    4BGF3VCZQSPUPDPMXJUIB3BJMTBQQ
    ʜ

    View full-size slide

  148. :PVDBOBMTPTFFUIFCPEZ
    4BGF3VCZQSPUPDPMXJUIB3BJMTBQQ

    View full-size slide

  149. "TZPVDBOTFF XFXFSFBCMFUPSVO
    BWBSJFUZPGBQQMJDBUJPOT
    XJUI4BGF3VCZQSPUPDPM

    View full-size slide

  150. *OBEEJUJPO
    ZPVDBO
    fi
    OEFYBNQMFTPG
    HFUUJOHRVFSZQBSBNFUFST
    BOEIBOEMJOH1045NFUIPET
    JOUIF5PZDPMSFQPTJUPSZ
    1MFBTFFOKPZUIFNJGZPVMJLF
    IUUQTHJUIVCDPNTIJPJNNUPZDPMCMPCNBJOFYBNQMFT

    View full-size slide

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

    View full-size slide