$30 off During Our Annual Pro Sale. View Details »

Rackミドルウェア入門のためのRackミドルウェア

 Rackミドルウェア入門のためのRackミドルウェア

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

Other Decks in Programming

Transcript

  1. 3BDLϛυϧ΢ΣΞೖ໳ͷͨΊͷ
    3BDLϛυϧ΢ΣΞ
    ԘҪඒ࡙!DPF@
    %FD
    5PLZP(JSMTSC.FFUVQWPM

    View Slide

  2. ٕज़తʹ੿͍಺༰΋ؚ·Ε͍ͯΔ͔ͱࢥ͍·͢ɻ
    օ༷͔Βͷ͝ࢦఠɾ13Λ
    ͓଴͓ͪͯ͠Γ·͢

    View Slide

  3. ࣗݾ঺հ
    ԘҪඒ࡙!DPF@

    8FCϓϩάϥϚGSPNגࣜձࣾΩϟλϧ
    5BNBSCɺ"TBLVTBSCɺ'VLVPLBSCʢ࿦ཧʣʹ͍·͢
    ࠷ۙؾʹͳΔϥΠϒϥϦ͸3BDL

    View Slide

  4. ࣗݾ঺հ
    ԘҪඒ࡙!DPF@

    8FCϓϩάϥϚGSPNגࣜձࣾΩϟλϧ
    5BNBSCɺ"TBLVTBSCɺ'VLVPLBSCʢ࿦ཧʣʹ͍·͢
    ࠷ۙؾʹͳΔϥΠϒϥϦ͸3BDL
    ‐ࠓ೔ͷ͓࿩

    View Slide

  5. 3BDLͬͯԿͰ͚ͨͬ͠ʜʁ
    ʢهԱ૕ࣦʣ

    View Slide

  6. 8FCαʔόʔͱ8FCΞϓϦέʔγϣϯΛܨ͙ϓϩτίϧ
    8FCαʔόʔͱ8FCΞϓϦέʔγϣϯΛܨ͙ϥΠϒϥϦ
    ‎3BDLϓϩτίϧΛຬͨͨ͠8FCαʔόʔͱ
    ‎3BDLϓϩτίϧΛຬͨͨ͠8FCΞϓϦέʔγϣϯؒΛ
    ‎3BDLϥΠϒϥϦ͕औΓ࣋ͭ
    3BDLͱ͸
    ը૾ग़యɿIUUQTSVCZPOSBJMTPSH͓ΑͼIUUQTSBDLHJUIVCJP

    View Slide

  7. 8FCαʔόʔͱ8FCΞϓϦέʔγϣϯΛܨ͙ϓϩτίϧ
    8FCαʔόʔͱ8FCΞϓϦέʔγϣϯΛܨ͙ϥΠϒϥϦ
    ‎3BDLϓϩτίϧΛຬͨͨ͠8FCαʔόʔͱ
    ‎3BDLϓϩτίϧΛຬͨͨ͠8FCΞϓϦέʔγϣϯؒΛ
    ‎3BDLϥΠϒϥϦ͕औΓ࣋ͭ
    3BDLͱ͸
    ը૾ग़యɿIUUQTSVCZPOSBJMTPSH͓ΑͼIUUQTSBDLHJUIVCJP
    3BDLΞϓϦέʔγϣϯ

    View Slide

  8. 3BDLΞϓϦέʔγϣϯͷ͓࿩
    ը૾ग़యɿIUUQTSVCZPOSBJMTPSH͓ΑͼIUUQTSBDLHJUIVCJP
    ɹྫ͑͹ɺ3BJMTΞϓϦέʔγϣϯ͔Β
    ɹ3BJMTಛ༗ͷॾʑΛશ෦ണ͕͍ͯ͘͠ͱʜ
    ɹ

    View Slide

  9. 3BDLΞϓϦέʔγϣϯͷ͓࿩
    ɹྫ͑͹ɺ3BJMTΞϓϦέʔγϣϯ͔Β
    ɹ3BJMTಛ༗ͷॾʑΛશ෦ണ͕͍ͯ͘͠ͱʜ
    ɹ
    ࠷ޙʹ࢒Δͷ͕ૉͷ3BDLΞϓϦέʔγϣϯ
    ˞3BJMTҎ֎ͷ3VCZͰॻ͔Εͨ8FCΞϓϦέʔγϣϯϑϨʔϜϫʔΫ΋ಉ༷
    ը૾ग़యɿIUUQTSVCZPOSBJMTPSH͓ΑͼIUUQTSBDLHJUIVCJP

    View Slide

  10. Ұ൪γϯϓϧͳྫ
    ɹ3BDLΞϓϦέʔγϣϯ͸ɺ
    ɹ8FCΞϓϦέʔγϣϯΛߏ੒͢ΔͨΊʹඞཁͳ
    ɹͭͷཁૉΛ࣋ͬͨ഑ྻ͔Β੒Δ
    [ 200, { "Content-Type" => "text/plain" }, ["Hello World!\n"] ]
    εςʔλείʔυ ϔομ ϘσΟ
    3BDLΞϓϦέʔγϣϯͷߏ଄

    View Slide

  11. Ұ൪γϯϓϧͳྫ
    ɹ
    ͱ͸͍͑
    ɹ࣮ࡍͷ8FCΞϓϦέʔγϣϯ͸
    ɹ΋ͬͱ৭ʑෳࡶͳػೳΛ͍࣋ͬͯΔ΋ͷͳͷͰ͸ʜʁ
    [ 200, { "Content-Type" => "text/plain" }, ["Hello World!\n"] ]

    View Slide

  12. Ұ൪γϯϓϧͳྫ
    ɹ
    ͱ͸͍͑
    ‎ͦΜͳ࣌͸3BDLϛυϧ΢ΣΞͷग़൪
    ɹ࣮ࡍͷ8FCΞϓϦέʔγϣϯ͸
    ɹ΋ͬͱ৭ʑෳࡶͳػೳΛ͍࣋ͬͯΔ΋ͷͳͷͰ͸ʜʁ
    [ 200, { "Content-Type" => "text/plain" }, ["Hello World!\n"] ]

    View Slide

  13. 3BDLϛυϧ΢ΣΞͱ͸
    8FCΞϓϦέʔγϣϯ͕ඞཁͱ͢Δ൚༻తͳػೳΛ
    3BDLΞϓϦέʔγϣϯʹ௥Ճ͢ΔͨΊͷ
    ϥΠϒϥϦ ͨͪ

    ɹɹ˞3BDLϛυϧ΢ΣΞ͸3BDLͷػߏΛར༻͍ͯ͠Δ
    ը૾ग़యɿIUUQTSBDLHJUIVCJP
    ػೳ
    ػೳ
    ػೳ

    View Slide

  14. 3BDLϛυϧ΢ΣΞ"
    "ػೳΛ௥Ճ
    3BDLϛυϧ΢ΣΞ#
    #ػೳΛ௥Ճ
    3BDLϛυϧ΢ΣΞ$
    $ػೳΛ௥Ճ
    Α͘ݟΔΠϝʔδਤ
    3BDLΞϓϦέʔγϣϯΛத৺ʹɺ
    ֤3BDLϛυϧ΢ΣΞ͕ͦΕͧΕͷػೳΛ௥Ճ
    ը૾ग़యɿIUUQTSBDLHJUIVCJP
    Α͘ݟΔΠϝʔδਤ
    3BDLΞϓϦέʔγϣϯ
    3BDLΞϓϦ3BDLϛυϧ΢ΣΞ‎Ұͭͷ8FCΞϓϦ
    ೖΕࢠঢ়ʹͳ͍ͬͯΔ
    "
    #
    $

    View Slide

  15. 3BJMTͷ৔߹
    ʜ
    Ҿ༻3BJMTΨΠυ3BJMTͱ3BDL"DUJPO%JTQBUDIFSͷϛυϧ΢ΣΞελοΫ
    3BJMTΞϓϦέʔγϣϯͰ΋
    ଟ͘ͷ3BDLϛυϧ΢ΣΞ͕࢖ΘΕ͍ͯΔ

    View Slide

  16. ྫ͑͹
    ActionDispatch::Cookies
    cookieػೳΛఏڙ͠·͢
    Ҿ༻3BJMTΨΠυ3BJMTͱ3BDL"DUJPO%JTQBUDIFSͷϛυϧ΢ΣΞελοΫ

    View Slide

  17. ྫ͑͹
    ͳΔ΄Ͳʂ
    ʢΘ͔Βͳ͍ʣ
    Ҿ༻3BJMTΨΠυ3BJMTͱ3BDL"DUJPO%JTQBUDIFSͷϛυϧ΢ΣΞελοΫ

    View Slide


  18. ྫɿ"DUJPO%JTQBUDI$PPLJFTͷ৔߹ɹ
    ஌ࣝͱͯࣗ͠෼͕஌͍ͬͯΔ͜ͱ
    ɹαʔόʔ͸ΫϥΠΞϯτʹରͯ͠
    ɹɹϨεϙϯεϔομΛฦ͢
    ɹϨεϙϯεϔομʹ͸
    ɹɹ$PPLJFͷ໊લͱ஋ؚ͕·Ε͍ͯΔ
    Կ͕Θ͔Βͳ͍ͷ͔

    View Slide


  19. ྫɿ"DUJPO%JTQBUDI$PPLJFTͷ৔߹ɹ
    ஌ࣝͱͯࣗ͠෼͕஌͍ͬͯΔ͜ͱ
    ɹαʔόʔ͸ΫϥΠΞϯτʹରͯ͠
    ɹɹϨεϙϯεϔομΛฦ͢
    ɹϨεϙϯεϔομʹ͸
    ɹɹ$PPLJFͷ໊લͱ஋ؚ͕·Ε͍ͯΔ
    Կ͕Θ͔Βͳ͍ͷ͔
    ‎$PPLJFͷ໊લͱ஋ͱ͸۩ମతʹԿʁ

    View Slide

  20. ஌Γ͍ͨ
    ޷ح৺

    View Slide

  21. ͱ͍͏͜ͱͰɺ
    ͔͜͜Β͕ຊฤͰ͢

    View Slide

  22. ΋͘͡
    ɹ3BDLϛυϧ΢ΣΞೖ໳ͷͨΊͷ
    ɹ3BDLϛυϧ΢ΣΞ
    ᶃ໨తͱ੒Ռ෺
    ᶄ࣮૷ํ਑ͱํ๏
    ᶅ༗ޮੑͷݕূ

    View Slide

  23. ɹ3BDLϛυϧ΢ΣΞೖ໳ͷͨΊͷ3BDLϛυϧ΢ΣΞ
    ᶃ໨తͱ੒Ռ෺

    View Slide

  24. ໨త
    ྫ͑͹
    ֤3BDLϛυϧ΢ΣΞΛ௨͢લͱ௨ͨ͠ޙͰɺ
    ϨεϙϯεϔομʹͲΜͳมߋ͕͋ͬͨͷ͔஌Γ͍ͨ
    ը૾ग़యɿIUUQTSBDLHJUIVCJP
    3BDLϛυϧ΢ΣΞ#Ͱ
    ൃੜͨ͠มߋΛ஌Γ͍ͨ
    3BDLΞϓϦέʔγϣϯ
    "
    #
    $

    View Slide

  25. ର৅ͷ3BDLϛυϧ΢ΣΞΛ௨ͨ͠ޙͷ
    ϨεϙϯεϔομͷมԽΛλʔϛφϧʹදࣔ͢Δ
    3BDLϛυϧ΢ΣΞ
    Λ࡞Γ·ͨ͠
    ੒Ռ෺

    View Slide

  26. ͦͷ໊͸
    5SBDF)FBEFS
    IUUQTHJUIVCDPNTIJPJNNUSBDF@IFBEFS

    View Slide

  27. ௐ΂͍ͨϛυϧ΢ΣΞʹରͯ͠
    5SBDF)FBEFSϛυϧ΢ΣΞΛJOTFSU@CFGPSF͢Δ
    class Application < Rails::Application

    config.middleware.insert_before ActionDispatch::Cookies, TraceHeader

    end
    ࢖͍ํ 3BJMTͷ৔߹

    DPOpHBQQMJDBUJPOSC

    View Slide

  28. class Application < Rails::Application

    config.middleware.insert_before ActionDispatch::Cookies, TraceHeader

    end
    ɹ[Target Middleware]

    ɹ ActionDispatch::Cookies

    ɹ[New Headers]

    ɹ -
    ʁʁʁʁ
    ௐ΂͍ͨϛυϧ΢ΣΞʹରͯ͠
    5SBDF)FBEFSϛυϧ΢ΣΞΛJOTFSU@CFGPSF͢Δ
    ࢖͍ํ 3BJMTͷ৔߹

    λʔϛφϧʹࠩ෼͕දࣔ͞ΕΔ
    DPOpHBQQMJDBUJPOSC

    View Slide

  29. ɹ3BDLϛυϧ΢ΣΞೖ໳ͷͨΊͷ3BDLϛυϧ΢ΣΞ
    ᶄ࣮૷ํ਑ͱํ๏

    View Slide

  30. લఏ
    3BDLΞϓϦέʔγϣϯͱ3BDLϛυϧ΢ΣΞ͸ɺ
    ڞ௨ͷن֨ʹԊ࣮ͬͯ૷͞Ε͍ͯΔ
    ࣮ߦ؀ڥ FOW
    ΛҾ਺ʹऔΔΠϯελϯεϝιουDBMMΛ࣮૷͢Δ
    3BDLΞϓϦέʔγϣϯͷ৔߹

    DBMMϝιου͸
    <εςʔλείʔυ \ϔομ^ <ϘσΟ>>
    ͷ഑ྻΛฦ͢
    3BDLϛυϧ΢ΣΞͷ৔߹

    ᶃΠϯελϯεม਺!BQQʹ
    ࣗ෼ͷ಺ଆͷΫϥεͷΠϯελϯεΛ࣋ͭ
    ᶄDBMMϝιουͷதͰ
    !BQQʹରͯ͠DBMMϝιουΛݺͿ
    ࣍ϖʔδͰ
    ΋͏গ͠ৄ͘͠
    )551Ϩεϙϯε

    "
    #
    $

    View Slide

  31. 3BDLϛυϧ΢ΣΞͷ಺෦ߏ଄ ྫ

    ᶄDBMMϝιουͷதͰ
    ɹ!BQQʹରͯ͠DBMMϝιουΛݺͿ
    ‎!BQQ͔ΒฦΓ஋Λड͚औΔ
    ‎ࣗ෼ࣗ਎ͷฦΓ஋Λ֎ଆͷϛυϧ΢ΣΞʹ౉͢
    BQQ"OFX #OFX $OFX 3BDLΞϓϦέʔγϣϯͷΠϯελϯε



    "Πϯελϯεͷ!BQQ#Πϯελϯεͷ!BQQ$Πϯελϯεͷ!BQQ
    BQQ "
    DBMMͷதͰ!BQQ #
    DBMM
    ‎!BQQ #
    DBMMͷதͰ!BQQ $
    DBMM
    ‎!BQQ $
    DBMMͷதͰ!BQQ 3BDLΞϓϦ
    DBMM
    ը૾ग़యɿIUUQTSBDLHJUIVCJP
    ᶃΠϯελϯεม਺!BQQʹࣗ෼ͷ಺ଆͷΫϥεͷΠϯελϯεΛ࣋ͭ
    "
    #
    $

    View Slide

  32. require 'rack'

    require_relative 'sample_middleware'

    class SampleApp

    def call(env)

    [ 200, {"Content-Type" => "text/plain"}, ["Hello World!\n"] ]

    end

    end

    use SampleMiddleware

    run SampleApp.new

    3BDLΞϓϦέʔγϣϯͷ࣮૷ྫ
    ഑ྻΛฦ͢
    ϛυϧ΢ΣΞΛੵΉ
    εςʔλείʔυ ϘσΟ
    ϔομ
    DPOpHSV

    View Slide

  33. 3BDLϛυϧ΢ΣΞͷ࣮૷ྫ
    class SampleMiddleware

    def initialize(app)

    @app = app

    end

    def call(env)

    status, header, body = @app.call(env)



    [ status, header, body ]

    end

    end

    ͦͷଞͷॲཧ
    3BDLΞϓϦέʔγϣϯͷฦΓ஋ͱͯ͠
    ഑ྻΛฦ͢
    Πϯελϯεม਺!BQQ Ҿ਺BQQ
    ͸
    ಺ଆͷϛυϧ΢ΣΞͷΠϯελϯε
    ಺ଆͷϛυϧ΢ΣΞͷฦΓ஋Λ
    ഑ྻͱͯ͠ड͚औΔ
    TBNQMF@NJEEMFXBSFSC

    View Slide

  34. 3BDLϛυϧ΢ΣΞͷ಺෦ߏ଄͔ΒΘ͔Δ͜ͱ
    ը૾ग़యɿIUUQTSBDLHJUIVCJP
    $ΠϯελϯεDBMM FOW

    ‎<εςʔλείʔυ \ϔομ^ <ϘσΟ>>
    #ΠϯελϯεDBMM FOW

    ‎<εςʔλείʔυ \ϔομ^ <ϘσΟ>>
    "ΠϯελϯεDBMM FOW

    ‎<εςʔλείʔυ \ϔομ^ <ϘσΟ>>
    3BDLΞϓϦέʔγϣϯ
    3BDLϛυϧ΢ΣΞ͸ڞ௨ͷن֨ʹԊ࣮ͬͯ૷͞Ε͍ͯΔ
    ‎Ͳͷϛυϧ΢ΣΞʹରͯ͠DBMMΛݺΜͰ΋
    ࠷Լ૚ͷ3BDLΞϓϦέʔγϣϯ·ͰDBMM͞ΕΔ
    ‎࠷ऴతʹಉ͡ߏ଄ͷ഑ྻ͕ฦΔ
    "
    #
    $

    View Slide

  35. ͔͜͜ΒཱͯͨԾઆ
    ը૾ग़యɿIUUQTSBDLHJUIVCJP
    ର৅ͷϛυϧ΢ΣΞͱͦͷ௚લʹݺ͹Εͨϛυϧ΢ΣΞͷ
    DBMMϝιουΛݺͼɺฦΓ஋ಉ࢜Λൺֱ͢Ε͹ྑ͍ͷͰ͸ʁ
    $ΠϯελϯεDBMM FOW
    ‎ $࣌఺ͷฦΓ஋

    #ΠϯελϯεDBMM FOW
    ‎ #࣌఺ͷฦΓ஋

    ᶃ#࣌఺ͱ$࣌఺ͷϛυϧ΢ΣΞ
    ɹͦΕͧΕͷΠϯελϯεʹͦΕͧΕDBMMΛݺͿ
    ᶄͦΕͧΕͷฦΓ஋Λऔಘ͢Δ
    ᶅฦΓ஋ಉ࢜ͷࠩ෼Λλʔϛφϧʹग़ྗ͢Δ
    3BDLΞϓϦέʔγϣϯ
    ࣮૷ํ਑λʔήοτ͕#ͷ৔߹ʜ#͕ݺ͹ΕΔ௚લʹ$͕ݺ͹ΕΔ
    "
    $
    #

    View Slide

  36. ͔͠͠

    View Slide

  37. ՝୊
    ը૾ग़యɿIUUQTSBDLHJUIVCJP
    ྫ͑͹λʔήοτ͕#ͷ৔߹
    3BDLΞϓϦέʔγϣϯͷߏ଄্ɺ
    ؒʹ͋Δϛυϧ΢ΣΞʹରͯ͠ॲཧΛڬΉ͜ͱ͕Ͱ͖ͳ͍
    ᶃ"ͷΠϯελϯεʹରͯ͠DBMM͕ݺ͹ΕΔ
    ᶄ࠷Լ૚ͷ3BDLΞϓϦέʔγϣϯ·Ͱ
    ɹશͯͷϛυϧ΢ΣΞͷDBMM͕ݺ͹ΕΔ
    ᶅ8FCΞϓϦέʔγϣϯͱͯ͠஋͕ฦΔ
    ࠓճDBMMΛݺͼ͍ͨ
    #࣌఺ͱ$࣌఺Ͱ
    ॲཧΛڬΉ͜ͱ͕Ͱ͖ͳ͍
    ͭ·Γʜ



    "
    #
    $

    View Slide

  38. ՝୊
    "
    #
    $
    ը૾ग़యɿIUUQTSBDLHJUIVCJP
    ྫ͑͹λʔήοτ͕#ͷ৔߹
    3BDLΞϓϦέʔγϣϯͷߏ଄্ɺ
    ؒʹ͋Δϛυϧ΢ΣΞʹରͯ͠ॲཧΛڬΉ͜ͱ͕Ͱ͖ͳ͍
    "ͷΠϯελϯεʹରͯ͠DBMM͕ݺ͹ΕΔͱ
    ࠷Լ૚ͷ3BDLΞϓϦέʔγϣϯ·Ͱ
    શͯͷϛυϧ΢ΣΞͷDBMM͕ݺ͹ΕΔ
    ࠓճDBMMΛݺͼ͍ͨ
    #࣌఺ͱ$࣌఺Ͱ
    ॲཧΛڬΉ͜ͱ͕Ͱ͖ͳ͍
    ͭ·Γʜ

    View Slide

  39. ՝୊
    "
    #
    $
    ը૾ग़యɿIUUQTSBDLHJUIVCJP
    ྫ͑͹λʔήοτ͕#ͷ৔߹
    3BDLΞϓϦέʔγϣϯͷߏ଄্ɺ
    ؒʹ͋Δϛυϧ΢ΣΞʹରͯ͠ॲཧΛڬΉ͜ͱ͕Ͱ͖ͳ͍
    "ͷΠϯελϯεʹରͯ͠DBMM͕ݺ͹ΕΔͱ
    ࠷Լ૚ͷ3BDLΞϓϦέʔγϣϯ·Ͱ
    શͯͷϛυϧ΢ΣΞͷDBMM͕ݺ͹ΕΔ
    ࠓճDBMMΛݺͼ͍ͨ
    #࣌఺ͱ$࣌఺Ͱ
    ॲཧΛڬΉ͜ͱ͕Ͱ͖ͳ͍
    ͭ·Γʜ
    5SBDF1PJOUͷग़൪Ͱ͸ʁ

    View Slide

  40. 5SBDF1PJOUͱ͸
    ɹϓϩάϥϜ࣮ߦதͷΠϕϯτʹϑοΫͯ͠
    ɹԿͰ΋Ͱ͖Δ3VCZͷ૊ΈࠐΈϥΠϒϥϦ
    ɹৄࡉ͸ׂѪ
    ɹࢀߟهࣄ
    ɹDMBTT5SBDF1PJOU
    ɹɹIUUQTEPDTSVCZMBOHPSHKBDMBTT5SBDF1PJOUIUNM
    3VCZͷվળΛࣗຫ͍ͨ͠
    ɹɹIUUQTUFDIMJGFDPPLQBEDPNFOUSZ
    ɹ3VCZͷ5SBDF1PJOUʹ͍ͭͯௐ΂ͯΈͨ
    ɹɹIUUQTRJJUBDPNTJNBOJUFNT⒎DGF
    ˞Πϕϯτʜϝιουݺͼग़͠΍Ϧλʔϯɺ
    ɹɹɹɹɹɹΫϥεఆٛɺྫ֎ͷൃੜFUD

    View Slide

  41. Ҏ্Λ౿·͑ͯ
    5SBDF)FBEFSͷ࣮૷

    View Slide

  42. DMBTT5SBDF)FBEFS ‏5SBDF1PJOUΛ࢖༻

    ɾࣗ෼ΑΓલʹ࣮ߦ͞Ε͍ͯΔશͯͷϛυϧ΢ΣΞͷ৘ใΛऩू
    ɾࣗ෼ͷޙʹ࣮ߦ͞ΕΔϛυϧ΢ΣΞ΁
    λʔήοτͷϛυϧ΢ΣΞͷฦΓ஋Λ౉͢ ޙଓͷॲཧͷͨΊ
    ɹ
    DMBTT3FTVMU
    ɾλʔήοτͱɺͦͷ௚લʹ࣮ߦ͞Εͨϛυϧ΢ΣΞͷ
    ΠϯελϯεΛநग़ͯ͠DBMMΛ࣮ߦ
    ͦΕͧΕͷฦΓ஋Λൺֱ͠ɺࠩ෼Λฦ͢ϝιουΛ࣮૷
    NPEVMF%FTDSJCBCMF
    ɾλʔϛφϧʹදࣔ͢ΔจࣈྻΛ੔͑ΔPVUQVUϝιουΛ࣮૷
    ৄࡉ͸ׂѪ
    ˞5SBDF)FBEFSࣗ਎͸ΞϓϦέʔγϣϯʹมߋΛՃ͑ͳ͍
    5SBDF)FBEFSͷߏ଄

    View Slide

  43. 5SBDF)FBEFSΠϯελϯεͷ!BQQDBMM FOW
    Λ࣮ߦ
    5SBDF1PJOUΛ࣮ߦ
    ɹ‎ࣗ෼ΑΓલͷશͯͷϛυϧ΢ΣΞͷ৘ใΛऩू
    NPEVMF%FTDSJCBCMF
    DMBTT3FTVMU
    DMBTT5SBDF)FBEFS
    DMBTT5SBDF)FBEFS
    5SBDF)FBEFSͷॲཧͷྲྀΕ
    !BQQDBMM FOW
    ͷฦΓ஋Λޙଓͷϛυϧ΢ΣΞʹ౉͢
    5SBDF)FBEFSΠϯελϯεDBMM FOW
    ͕ݺ͹ΕΔͱ
    ௐ΂͍ͨϛυϧ΢ΣΞͷΠϯελϯεDBMM FOW

    ɹ‎ͦΕͧΕͷฦΓ஋Λൺֱ͠ɺࠩ෼Λऔಘ
    PVUQVUϝιουͰࠩ෼Λλʔϛφϧʹදࣔ

    View Slide

  44. ࣮૷ DMBTT5SBDF)FBEFS

    1 require 'active_support/core_ext'





    6 class TraceHeader

    7 include Describable

    8

    9 def initialize(app)

    10 @app = app

    11 @datas = []

    12 @fixed_app = nil

    13 end

    14

    15 def call(env)

    16 tracer.enable { @app.call(env) }

    17 output(result)

    18 @fixed_app

    19 end
    ˞จࣈྻΛ੒ܗ͢Δ
    %FTDSJCBCMFPVUQVUϝιουΛ
    ࢖༻͢ΔͨΊʹJODMVEF
    # ...লུ...

    View Slide

  45. ࣮૷ DMBTT5SBDF)FBEFS

    1 require 'active_support/core_ext'





    6 class TraceHeader

    7 include Describable

    8

    9 def initialize(app)

    10 @app = app

    11 @datas = []

    12 @fixed_app = nil

    13 end

    14

    15

    16

    17

    18

    19
    # ...লུ...
    !BQQ‎λʔήοτͷϛυϧ΢ΣΞͷΠϯελϯε
    !EBUBT‎5SBDF1PJOUͷ࣮ߦ݁ՌΛ֨ೲ͢Δ഑ྻ
    !pYFE@BQQ‎!BQQDBMM FOW
    ͷฦΓ஋Λ֨ೲ͢Δม਺

    View Slide

  46. ࣮૷ DMBTT5SBDF)FBEFS

    1 require 'active_support/core_ext'





    6 class TraceHeader

    7

    8

    9

    10

    11

    12

    13

    14

    15 def call(env)

    16 tracer.enable { @app.call(env) }

    17 output(result)

    18 @fixed_app

    19 end
    # ...লུ...



    ᶃ!BQQDBMM FOW
    ΛϑοΫͯ͠5SBDF1PJOUΛ࣮ߦ
    ᶄ%FTDSJCBCMFPVUQVUͰ࣮ߦ݁ՌSFTVMUΛλʔϛφϧʹදࣔ
    ᶅ!BQQDBMM FOW
    ͷฦΓ஋!pYFE@BQQΛ
    ᶆޙଓͷϛυϧ΢ΣΞʹ౉͢
    ˞USBDFS͸5SBDF1PJOUͷΠϯελϯεΛฦ͢ϝιου

    View Slide

  47. ࣮૷ DMBTT5SBDF)FBEFS

    30 def tracer

    31 TracePoint.new(:call, :return) do |tp|

    32 if tp.rack_middleware_called?

    33 if tp.event.eql?(:call) \

    34 && !@datas.find { |op| op[:middleware].eql? tp.defined_class }

    35 @datas << { middleware: tp.defined_class,

    36 app: tp.self.deep_dup,

    37 env: tp.binding.local_variable_get(:env).deep_dup }

    38 end

    39

    40 @fixed_app = tp.return_value if tp.event.eql?(:return)

    41 end

    42 end

    43

    44 def result

    45 Result.new(@app, @datas)

    46 end

    47 end
    5SBDF1PJOUΛΠϯελϯεԽ
    ϝιουݺͼग़͠ͱϦλʔϯ࣌ʹ
    ϒϩοΫ಺ͷॲཧΛ࣮ߦ͢Δ

    View Slide

  48. 30 def tracer

    31 TracePoint.new(:call, :return) do |tp|

    32 if tp.rack_middleware_called?

    33

    34

    35

    36

    37

    38

    39

    40

    41 end

    42 end

    43

    44 def result

    45 Result.new(@app, @datas)

    46 end

    47 end
    ࣮૷ DMBTT5SBDF)FBEFS

    ࣮ߦதͷΠϕϯτ͕
    3BDLϛυϧ΢ΣΞͷΠϯελϯεʹର͢Δ
    DBMMϝιουͷݺͼग़͠PSϦλʔϯ
    Ͱ͋Δ৔߹

    View Slide

  49. 30 def tracer

    31 TracePoint.new(:call, :return) do |tp|

    32 if tp.rack_middleware_called?

    33 if tp.event.eql?(:call) \

    34 && !@datas.find { |op| op[:middleware].eql? tp.defined_class }

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44 def result

    45 Result.new(@app, @datas)

    46 end

    47 end
    ࣮૷ DMBTT5SBDF)FBEFS

    ࣮ߦதͷΠϕϯτ͕
    ·ͩॲཧ͞Ε͍ͯͳ͍3BDLϛυϧ΢ΣΞʹର͢Δ
    DBMMϝιουͷݺͼग़͠
    Ͱ͋Δ৔߹

    View Slide

  50. 30 def tracer

    31 TracePoint.new(:call, :return) do |tp|

    32 if tp.rack_middleware_called?

    33 if tp.event.eql?(:call) \

    34 && !@datas.find { |op| op[:middleware].eql? tp.defined_class }

    35 @datas << { middleware: tp.defined_class,

    36 app: tp.self.deep_dup,

    37 env: tp.binding.local_variable_get(:env).deep_dup }

    38 end

    39

    40

    41 end

    42 end

    43

    44 def result

    45 Result.new(@app, @datas)

    46 end

    47 end


    ࣮૷ DMBTT5SBDF)FBEFS


    ֤ϛυϧ΢ΣΞͷ
    ᶃΫϥεᶄΠϯελϯεᶅ࣮ߦ؀ڥ
    Λ഑ྻ!EBUBTʹอଘ

    View Slide

  51. 30 def tracer

    31 TracePoint.new(:call, :return) do |tp|

    32 if tp.rack_middleware_called?

    33 if tp.event.eql?(:call) \

    34 && !@datas.find { |op| op[:middleware].eql? tp.defined_class }

    35 @datas << { middleware: tp.defined_class,

    36 app: tp.self.deep_dup,

    37 env: tp.binding.local_variable_get(:env).deep_dup }

    38 end

    39

    40

    41 end

    42 end

    43

    44

    45

    46

    47 end


    ᶃUQTFMG
    DBMMϝιου͕ݺ͹ΕͨΦϒδΣΫτ
    ‎ͦͷϛυϧ΢ΣΞͷΠϯελϯε
    ᶄUQCJOEJOHMPDBM@WBSJBCMF@HFU FOW

    DBMMϝιου͕ݺ͹ΕͨίϯςΩετͰ
    ఆٛ͞Ε͍ͯΔϩʔΧϧม਺FOW
    ‎ͦͷϛυϧ΢ΣΞͷDBMM࣮ߦ࣌ͷҾ਺FOW
    ࣮૷ DMBTT5SBDF)FBEFS
    ˞ॏཁ

    View Slide

  52. ࣮૷ DMBTT5SBDF)FBEFS
    ˞ॏཁ
    30 def tracer

    31 TracePoint.new(:call, :return) do |tp|

    32 if tp.rack_middleware_called?

    33 if tp.event.eql?(:call) \

    34 && !@datas.find { |op| op[:middleware].eql? tp.defined_class }

    35 @datas << { middleware: tp.defined_class,

    36 app: tp.self.deep_dup,

    37 env: tp.binding.local_variable_get(:env).deep_dup }

    38 end

    39

    40

    41 end

    42 end

    43

    44

    45

    46

    47 end
    ཹҙ఺ᶃ
    ֤ϛυϧ΢ΣΞͷΠϯελϯεͱҾ਺FOW͸
    5SBDF)FBEFSϛυϧ΢ΣΞ
    λʔήοτͷϛυϧ΢ΣΞ
    λʔήοτͷ௚લͷϛυϧ΢ΣΞ
    Ͱಉ͡ΦϒδΣΫτΛࢦ͢

    View Slide

  53. ࣮૷ DMBTT5SBDF)FBEFS
    ˞ॏཁ
    30 def tracer

    31 TracePoint.new(:call, :return) do |tp|

    32 if tp.rack_middleware_called?

    33 if tp.event.eql?(:call) \

    34 && !@datas.find { |op| op[:middleware].eql? tp.defined_class }

    35 @datas << { middleware: tp.defined_class,

    36 app: tp.self.deep_dup,

    37 env: tp.binding.local_variable_get(:env).deep_dup }

    38 end

    39

    40

    41 end

    42 end

    43

    44

    45

    46

    47 end
    ཹҙ఺ᶄ
    ֤ϛυϧ΢ΣΞͷΠϯελϯεͱҾ਺FOW͸
    DBMMϝιουʹΑͬͯ
    ஋͕มߋ͞ΕΔՄೳੑ͕͋Δ

    View Slide

  54. ࣮૷ DMBTT5SBDF)FBEFS
    ˞ॏཁ
    30 def tracer

    31 TracePoint.new(:call, :return) do |tp|

    32 if tp.rack_middleware_called?

    33 if tp.event.eql?(:call) \

    34 && !@datas.find { |op| op[:middleware].eql? tp.defined_class }

    35 @datas << { middleware: tp.defined_class,

    36 app: tp.self.deep_dup,

    37 env: tp.binding.local_variable_get(:env).deep_dup }

    38 end

    39

    40

    41 end

    42 end

    43

    44

    45

    46

    47 end
    ཹҙ఺ᶅ
    ஋͕มߋ͞ΕͨΦϒδΣΫτʹ
    ࠶౓DBMMϝιουΛݺͿͱʜ
    ਖ਼͍͠ฦΓ஋Λฦ͞ͳ͍
    ޙଓͷॲཧʹӨڹ͕ग़ΔͳͲ͕ى͜Γ͏Δ
    ‎յΕΔ

    View Slide

  55. ࣮૷ DMBTT5SBDF)FBEFS
    ˞ॏཁ
    30 def tracer

    31 TracePoint.new(:call, :return) do |tp|

    32 if tp.rack_middleware_called?

    33 if tp.event.eql?(:call) \

    34 && !@datas.find { |op| op[:middleware].eql? tp.defined_class }

    35 @datas << { middleware: tp.defined_class,

    36 app: tp.self.deep_dup,

    37 env: tp.binding.local_variable_get(:env).deep_dup }

    38 end

    39

    40

    41 end

    42 end

    43

    44

    45

    46

    47 end
    ճආࡦ
    "DUJWF4VQQPSUEFFQ@EVQΛ࢖ͬͯ
    σΟʔϓίϐʔΛߦ͏
    ‎5SBDF)FBEFSϛυϧ΢ΣΞ಺Ͱ
    ࢖༻͞Ε͍ͯΔΦϒδΣΫτͱ͸
    ແؔ܎ͷΦϒδΣΫτͱͯ͠஋Λऔಘ

    View Slide

  56. ࣮૷ DMBTT5SBDF)FBEFS

    30 def tracer

    31 TracePoint.new(:call, :return) do |tp|

    32 if tp.rack_middleware_called?

    33 if tp.event.eql?(:call) \

    34 && !@datas.find { |op| op[:middleware].eql? tp.defined_class }

    35 @datas << { middleware: tp.defined_class,

    36 app: tp.self.deep_dup,

    37 env: tp.binding.local_variable_get(:env).deep_dup }

    38 end

    39

    40 @fixed_app = tp.return_value if tp.event.eql?(:return)

    41 end

    42 end

    43

    44

    45

    46

    47 end
    ࣮ߦதͷΠϕϯτ͕
    DBMMϝιουͷϦλʔϯͰ͋Δ৔߹
    ‎!BQQDBMM FOW
    ͷฦΓ஋Λ!pYFE@BQQʹ୅ೖ

    View Slide

  57. ࣮૷ DMBTT5SBDF)FBEFS

    30 def tracer

    31 TracePoint.new(:call, :return) do |tp|

    32 if tp.rack_middleware_called?

    33 if tp.event.eql?(:call) \

    34 && !@datas.find { |op| op[:middleware].eql? tp.defined_class }

    35 @datas << { middleware: tp.defined_class,

    36 app: tp.self.deep_dup,

    37 env: tp.binding.local_variable_get(:env).deep_dup }

    38 end

    39

    40

    41 end

    42 end

    43

    44 def result

    45 Result.new(@app, @datas)

    46 end

    47 end
    ࠩ෼Λऔಘ͢ΔͨΊ3FTVMUΫϥεΛΠϯελϯεԽ
    !BQQ‎λʔήοτͷϛυϧ΢ΣΞͷΠϯελϯε
    !EBUBT‎5SBDF1PJOUͷ࣮ߦ݁ՌΛ֨ೲͨ͠഑ྻ

    View Slide

  58. ࣮૷ DMBTT3FTVMU

    1 class TraceHeader

    2 class Result

    3 attr_reader :target_app

    4

    5 def initialize(target_app, datas)

    6 @target_app = target_app

    7 @target_hash = datas.find { |dt| dt[:middleware].eql?(target_app.class) }

    8 @inner_hash = datas[datas.index(target_hash) + 1]

    9 end

    10

    11 def new_headers

    12 headers(new_fields)

    13 end

    14

    15 def changed_headers

    16 headers(changed_fields)

    17 end

    18

    View Slide

  59. ࣮૷ DMBTT3FTVMU

    1 class TraceHeader

    2 class Result

    3 attr_reader :target_app

    4

    5 def initialize(target_app, datas)

    6 @target_app = target_app

    7 @target_hash = datas.find { |dt| dt[:middleware].eql?(target_app.class) }

    8 @inner_hash = datas[datas.index(target_hash) + 1]

    9 end

    10

    11 def new_headers

    12 headers(new_fields)

    13 end

    14

    15 def changed_headers

    16 headers(changed_fields)

    17 end

    18
    !UBSHFU@BQQ‎λʔήοτͷϛυϧ΢ΣΞͷΠϯελϯε
    Ҿ਺EBUBT‎5SBDF1PJOUͷ࣮ߦ݁ՌΛ֨ೲͨ͠഑ྻ
    ʲҎԼ͸EBUBT͔Βநग़ʳ
    !UBSHFU@IBTI‎λʔήοτͷϛυϧ΢ΣΞͷ৘ใ
    !JOOFS@IBTI‎λʔήοτͷ௚લʹݺ͹Εͨ
    ϛυϧ΢ΣΞͷ৘ใ

    View Slide

  60. ࣮૷ DMBTT3FTVMU

    1 class TraceHeader

    2 class Result

    3 attr_reader :target_app

    4

    5 def initialize(target_app, datas)

    6 @target_app = target_app

    7 @target_hash = datas.find { |dt| dt[:middleware].eql?(target_app.class) }

    8 @inner_hash = datas[datas.index(target_hash) + 1]

    9 end

    10

    11 def new_headers

    12 headers(new_fields)

    13 end

    14

    15 def changed_headers

    16 headers(changed_fields)

    17 end

    18
    !UBSHFU@IBTIͱ!JOOFS@IBTIʹ͸
    ͦΕͧΕ࣍ͷΑ͏ͳϋογϡ͕֨ೲ͞Ε͍ͯΔ
    \NJEEMFXBSFϛυϧ΢ΣΞͷΫϥε
    BQQϛυϧ΢ΣΞͷΠϯελϯε
    FOWϛυϧ΢ΣΞ࣮ߦ࣌ͷ؀ڥ^

    View Slide

  61. ࣮૷ DMBTT3FTVMU

    1 class TraceHeader

    2 class Result

    3 attr_reader :target_app

    4



    32

    33 def target_header

    34 @target_header ||= rack_app( @target_hash )[1]

    35 end

    36

    37 def prev_header

    38 @prev_header ||= rack_app( @inner_hash )[1]

    39 end

    40

    41 def rack_app(hash)

    42 hash[:app].call(hash[:env])

    43 end

    44
    ᶃλʔήοτͷϛυϧ΢ΣΞͷ৘ใ
    ᶃͱᶄɺ
    ͦΕͧΕͷϛυϧ΢ΣΞͷ
    Πϯελϯεʹରͯ͠DBMM
    ᶄ௚લʹݺ͹Εͨϛυϧ΢ΣΞͷ৘ใ
    # ...লུ...

    View Slide

  62. ࣮૷ DMBTT3FTVMU

    1 class TraceHeader

    2 class Result

    3 attr_reader :target_app

    4



    32

    33 def target_header

    34 @target_header ||= rack_app( @target_hash )[1]

    35 end

    36

    37 def prev_header

    38 @prev_header ||= rack_app( @inner_hash )[1]

    39 end

    40

    41 def rack_app(hash)

    42 hash[:app].call(hash[:env])

    43 end

    44
    # ...লུ...
    ฦΓ஋͸ͦΕͧΕ
    <εςʔλείʔυ \ϔομ^ <ϘσΟ>>
    ‎ϔομΛऔಘ͢ΔͨΊʹ
    ‎ΠϯσοΫε<>Λࢦఆ

    View Slide

  63. ࣮૷ DMBTT3FTVMU

    20

    21 def common_fields

    22 target_header.keys & prev_header.keys

    23 end

    24

    25 def new_fields

    26 target_header.keys - common_fields

    27 end

    28

    29 def changed_fields

    30 common_fields.select { |field| target_header[field] != prev_header[field] }

    31 end

    32



    46 def headers(fields)

    47 fields.map { |field| { field => target_header[field].to_s } }

    48 end

    49 end
    ϛυϧ΢ΣΞΛ௨ͨ͠લޙͰڞ௨ͷϔομ໊Λநग़
    ৽͘͠௥Ճ͞Εͨϔομ໊Λநग़
    ஋͕ॻ͖׵Θͬͨϔομ໊Λநग़
    ϔομ໊͔Βϔομͷ஋Λऔಘ
    # ...লུ...

    View Slide

  64. ࣮૷ DMBTT3FTVMU

    1 class TraceHeader

    2 class Result

    3

    4

    5

    6

    7

    8

    9

    10

    11 def new_headers

    12 headers(new_fields)

    13 end

    14

    15 def changed_headers

    16 headers(changed_fields)

    17 end

    18
    औಘͨ͠஋Λ
    3FTVMUOFX@IFBEFST ৽͘͠௥Ճ͞Εͨϔομ

    3FTVMUDIBOHFE@IFBEFST ஋͕ॻ͖׵Θͬͨϔομ

    ͱ࣮ͯ͠૷
    ‎%FTDSJCBCMFPVUQVUϝιουͰλʔϛφϧʹදࣔ

    View Slide

  65. 5SBDF)FBEFSΠϯελϯεͷ!BQQDBMM FOW
    Λ࣮ߦ
    PVUQVUϝιουͰࠩ෼Λλʔϛφϧʹදࣔ
    5SBDF1PJOUΛ࣮ߦ
    ɹ‎ࣗ෼ΑΓલͷશͯͷϛυϧ΢ΣΞͷ৘ใΛऩू
    NPEVMF%FTDSJCBCMF
    DMBTT3FTVMU
    DMBTT5SBDF)FBEFS
    DMBTT5SBDF)FBEFS
    5SBDF)FBEFSͷॲཧͷྲྀΕͷ͓͞Β͍
    !BQQDBMM FOW
    ͷฦΓ஋Λޙଓͷϛυϧ΢ΣΞʹ౉͢
    5SBDF)FBEFSΠϯελϯεDBMM FOW
    ͕ݺ͹ΕΔͱ
    ௐ΂͍ͨϛυϧ΢ΣΞͷΠϯελϯεDBMM FOW

    ɹ‎ͦΕͧΕͷฦΓ஋Λൺֱ͠ɺࠩ෼Λऔಘ

    View Slide

  66. ͓ർΕ༷Ͱͨ͠✨

    View Slide

  67. ɹ3BDLϛυϧ΢ΣΞೖ໳ͷͨΊͷ3BDLϛυϧ΢ΣΞ
    ᶅ༗ޮੑͷݕূ

    View Slide

  68. "DUJPO%JTQBUDI$PPLJFTΛ௨ͨ͠ޙɺ
    ৽͘͠௥Ճ͞ΕͨϔομΛλʔϛφϧʹදࣔ͢Δ
    class Application < Rails::Application

    config.middleware.insert_before ActionDispatch::Cookies, TraceHeader

    end
    ݕূ
    DPOpHBQQMJDBUJPOSC
    ݕূ؀ڥ3VCZ
    3BJMT
    ɹ4DB⒎PME͚ͨͩ͠ͷ؆୯ͳΞϓϦέʔγϣϯ
    ݕূํ๏αʔόʔΛ্ཱͪ͛ͯద౰ͳϖʔδʹΞΫηε

    View Slide

  69. ͦͷ݁Ռ

    View Slide

  70. ݁Ռ ࣮ࡍͷը໘

    ‎Ͱ͖·ͨ͠
    "DUJPO%JTQBUDI$PPLJFTΛ௨ͨ͠ޙɺ
    ৽͘͠௥Ճ͞ΕͨϔομΛλʔϛφϧʹදࣔ͢Δ

    View Slide

  71. ----------------------------------------------------

    TraceHeader printing...

    [Target Middleware]

    ActionDispatch::Cookies
    [New Headers]

    - Set-Cookie: _sampleapp_session=P8jTL8...; path=/; HttpOnly
    [Changed Headers]

    - ETag: W/"f25d17d6ad73a7091771928fef7cc6f8"
    ----------------------------------------------------
    ϛυϧ΢ΣΞ໊
    ৽͍͠ϔομͷ໊લͱ஋
    ஋͕ॻ͖׵Θͬͨϔομͷ໊લͱ஋
    ݁Ռ ֦େ

    "DUJPO%JTQBUDI$PPLJFTΛ௨ͨ͠ޙɺ
    ৽͘͠௥Ճ͞ΕͨϔομΛλʔϛφϧʹදࣔ͢Δ

    View Slide

  72. ৽͘͠௥Ճ͞Εͨϔομ4FU$PPLJF
    ᶃ@TBNQMFBQQ@TFTTJPO1K5-IUCIPHFIPHFGVHBHVGB
    ᶄQBUI
    ᶅ)UUQ0OMZ
    ஋͕มߋ͞Εͨϔομ&5BH
    ᶆ8GEEBEBGFGDDG
    "DUJPO%JTQBUDI$PPLJFT͕ϔομʹ༩࣮͑ͨࡍͷ஋͔Β
    ৭ʑͳൃݟ͕͋Γ·ͨ͠
    ݁Ռ͔ΒಘΒΕͨ΋ͷ
    ᶃ஋͸ʮ@ΞϓϦ໊@TFTTJPOϥϯμϜͳӳ਺ࣈʯ
    ᶄσϑΥϧτͰQBUIଐੑ͕ϧʔτʹઃఆ͞ΕΔ
    ᶅσϑΥϧτͰ)UUQ0OMZʹͳΔ
    ᶆ&5BH͸Ͳͷϛυϧ΢ΣΞΛ௨ͯ͠΋ॻ͖׵ΘΔ

    View Slide

  73. 'VLVPLBSC͔Βͷ͓ͨΑΓ঺հ
    CZ!VE[VSB͞Μ
    ൃදࢿྉͷϨϏϡʔΛ͓ئ͍ͨ͠'VLVPLBSC͔Β
    ײ૝Λ௖͖·ͨ͠ɻ

    View Slide

  74. 5SBDF)FBEFSͷ༗ޮੑ

    View Slide

  75. 5SBDF)FBEFSͷ༗ޮੑ
    ͋Γͦ͏
    13͍ͭͰ΋͓଴͓ͪͯ͠Γ·͢
    IUUQTHJUIVCDPNTIJPJNNUSBDF@IFBEFS

    View Slide

  76. ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠
    ɹ4QFDJBM5IBOLT✨
    !UEUET͞Μ !LBLVUBOJ͞Μ
    !KPLFS͞Μɹ !ZPVDIBO͞Μ
    !PLVSBNBTBGVNJ͞Μ !VE[VSB͞Μ
    !KJNMPDL͞Μ"TBLVTBSC⚡'VLVPLBSC
    ը૾ग़యIUUQTUXJUUFSDPN

    View Slide