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

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

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

Transcript

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

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

  3. ࣗݾ঺հ ԘҪඒ࡙!DPF@  8FCϓϩάϥϚGSPNגࣜձࣾΩϟλϧ 5BNBSCɺ"TBLVTBSCɺ'VLVPLBSCʢ࿦ཧʣʹ͍·͢ ࠷ۙؾʹͳΔϥΠϒϥϦ͸3BDL

  4. ࣗݾ঺հ ԘҪඒ࡙!DPF@  8FCϓϩάϥϚGSPNגࣜձࣾΩϟλϧ 5BNBSCɺ"TBLVTBSCɺ'VLVPLBSCʢ࿦ཧʣʹ͍·͢ ࠷ۙؾʹͳΔϥΠϒϥϦ͸3BDL ‐ࠓ೔ͷ͓࿩

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

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

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

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

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

  10. Ұ൪γϯϓϧͳྫ ɹ3BDLΞϓϦέʔγϣϯ͸ɺ ɹ8FCΞϓϦέʔγϣϯΛߏ੒͢ΔͨΊʹඞཁͳ ɹͭͷཁૉΛ࣋ͬͨ഑ྻ͔Β੒Δ [ 200, { "Content-Type" => "text/plain"

    }, ["Hello World!\n"] ] εςʔλείʔυ ϔομ ϘσΟ 3BDLΞϓϦέʔγϣϯͷߏ଄
  11. Ұ൪γϯϓϧͳྫ ɹ ͱ͸͍͑ ɹ࣮ࡍͷ8FCΞϓϦέʔγϣϯ͸ ɹ΋ͬͱ৭ʑෳࡶͳػೳΛ͍࣋ͬͯΔ΋ͷͳͷͰ͸ʜʁ [ 200, { "Content-Type" =>

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

    => "text/plain" }, ["Hello World!\n"] ]
  13. 3BDLϛυϧ΢ΣΞͱ͸ 8FCΞϓϦέʔγϣϯ͕ඞཁͱ͢Δ൚༻తͳػೳΛ  3BDLΞϓϦέʔγϣϯʹ௥Ճ͢ΔͨΊͷ  ϥΠϒϥϦ ͨͪ  ɹɹ˞3BDLϛυϧ΢ΣΞ͸3BDLͷػߏΛར༻͍ͯ͠Δ ը૾ग़యɿIUUQTSBDLHJUIVCJP

    ػೳ ػೳ ػೳ
  14. 3BDLϛυϧ΢ΣΞ" "ػೳΛ௥Ճ 3BDLϛυϧ΢ΣΞ# #ػೳΛ௥Ճ 3BDLϛυϧ΢ΣΞ$ $ػೳΛ௥Ճ Α͘ݟΔΠϝʔδਤ 3BDLΞϓϦέʔγϣϯΛத৺ʹɺ ֤3BDLϛυϧ΢ΣΞ͕ͦΕͧΕͷػೳΛ௥Ճ ը૾ग़యɿIUUQTSBDLHJUIVCJP

    Α͘ݟΔΠϝʔδਤ 3BDLΞϓϦέʔγϣϯ 3BDLΞϓϦ 3BDLϛυϧ΢ΣΞ‎Ұͭͷ8FCΞϓϦ ೖΕࢠঢ়ʹͳ͍ͬͯΔ " # $
  15. 3BJMTͷ৔߹ ʜ Ҿ༻3BJMTΨΠυ3BJMTͱ3BDL"DUJPO%JTQBUDIFSͷϛυϧ΢ΣΞελοΫ 3BJMTΞϓϦέʔγϣϯͰ΋ ଟ͘ͷ3BDLϛυϧ΢ΣΞ͕࢖ΘΕ͍ͯΔ

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

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

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

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

  20. ஌Γ͍ͨ ޷ح৺

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

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

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

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

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

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

  27. ௐ΂͍ͨϛυϧ΢ΣΞʹରͯ͠ 5SBDF)FBEFSϛυϧ΢ΣΞΛJOTFSU@CFGPSF͢Δ class Application < Rails::Application config.middleware.insert_before ActionDispatch::Cookies, TraceHeader end

    ࢖͍ํ 3BJMTͷ৔߹ DPOpHBQQMJDBUJPOSC
  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
  29. ɹ3BDLϛυϧ΢ΣΞೖ໳ͷͨΊͷ3BDLϛυϧ΢ΣΞ ᶄ࣮૷ํ਑ͱํ๏

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

    <εςʔλείʔυ \ϔομ^ <ϘσΟ>> ͷ഑ྻΛฦ͢  3BDLϛυϧ΢ΣΞͷ৔߹  ᶃΠϯελϯεม਺!BQQʹ ࣗ෼ͷ಺ଆͷΫϥεͷΠϯελϯεΛ࣋ͭ ᶄDBMMϝιουͷதͰ !BQQʹରͯ͠DBMMϝιουΛݺͿ ࣍ϖʔδͰ ΋͏গ͠ৄ͘͠ )551Ϩεϙϯε " # $
  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ʹࣗ෼ͷ಺ଆͷΫϥεͷΠϯελϯεΛ࣋ͭ " # $
  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
  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
  34. 3BDLϛυϧ΢ΣΞͷ಺෦ߏ଄͔ΒΘ͔Δ͜ͱ ը૾ग़యɿIUUQTSBDLHJUIVCJP $ΠϯελϯεDBMM FOW  ‎<εςʔλείʔυ \ϔομ^ <ϘσΟ>> #ΠϯελϯεDBMM FOW

     ‎<εςʔλείʔυ \ϔομ^ <ϘσΟ>> "ΠϯελϯεDBMM FOW  ‎<εςʔλείʔυ \ϔομ^ <ϘσΟ>> 3BDLΞϓϦέʔγϣϯ 3BDLϛυϧ΢ΣΞ͸ڞ௨ͷن֨ʹԊ࣮ͬͯ૷͞Ε͍ͯΔ ‎Ͳͷϛυϧ΢ΣΞʹରͯ͠DBMMΛݺΜͰ΋ ࠷Լ૚ͷ3BDLΞϓϦέʔγϣϯ·ͰDBMM͞ΕΔ ‎࠷ऴతʹಉ͡ߏ଄ͷ഑ྻ͕ฦΔ " # $
  35. ͔͜͜ΒཱͯͨԾઆ ը૾ग़యɿIUUQTSBDLHJUIVCJP ର৅ͷϛυϧ΢ΣΞͱͦͷ௚લʹݺ͹Εͨϛυϧ΢ΣΞͷ DBMMϝιουΛݺͼɺฦΓ஋ಉ࢜Λൺֱ͢Ε͹ྑ͍ͷͰ͸ʁ $ΠϯελϯεDBMM FOW ‎ $࣌఺ͷฦΓ஋ #ΠϯελϯεDBMM FOW

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

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

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

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

    શͯͷϛυϧ΢ΣΞͷDBMM͕ݺ͹ΕΔ ࠓճDBMMΛݺͼ͍ͨ #࣌఺ͱ$࣌఺Ͱ ॲཧΛڬΉ͜ͱ͕Ͱ͖ͳ͍ ͭ·Γʜ 5SBDF1PJOUͷग़൪Ͱ͸ʁ
  40. 5SBDF1PJOUͱ͸ ɹϓϩάϥϜ࣮ߦதͷΠϕϯτʹϑοΫͯ͠ ɹԿͰ΋Ͱ͖Δ3VCZͷ૊ΈࠐΈϥΠϒϥϦ ɹৄࡉ͸ׂѪ ɹࢀߟهࣄ ɹDMBTT5SBDF1PJOU ɹɹIUUQTEPDTSVCZMBOHPSHKBDMBTT5SBDF1PJOUIUNM 3VCZͷվળΛࣗຫ͍ͨ͠ ɹɹIUUQTUFDIMJGFDPPLQBEDPNFOUSZ ɹ3VCZͷ5SBDF1PJOUʹ͍ͭͯௐ΂ͯΈͨ

    ɹɹIUUQTRJJUBDPNTJNBOJUFNT⒎DGF ˞Πϕϯτʜϝιουݺͼग़͠΍Ϧλʔϯɺ ɹɹɹɹɹɹΫϥεఆٛɺྫ֎ͷൃੜFUD
  41. Ҏ্Λ౿·͑ͯ 5SBDF)FBEFSͷ࣮૷

  42. DMBTT5SBDF)FBEFS ‏5SBDF1PJOUΛ࢖༻  ɾࣗ෼ΑΓલʹ࣮ߦ͞Ε͍ͯΔશͯͷϛυϧ΢ΣΞͷ৘ใΛऩू ɾࣗ෼ͷޙʹ࣮ߦ͞ΕΔϛυϧ΢ΣΞ΁ λʔήοτͷϛυϧ΢ΣΞͷฦΓ஋Λ౉͢ ޙଓͷॲཧͷͨΊ ɹ DMBTT3FTVMU ɾλʔήοτͱɺͦͷ௚લʹ࣮ߦ͞Εͨϛυϧ΢ΣΞͷ

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

    !BQQDBMM FOW ͷฦΓ஋Λޙଓͷϛυϧ΢ΣΞʹ౉͢ 5SBDF)FBEFSΠϯελϯεDBMM FOW ͕ݺ͹ΕΔͱ ௐ΂͍ͨϛυϧ΢ΣΞͷΠϯελϯεDBMM FOW  ɹ‎ͦΕͧΕͷฦΓ஋Λൺֱ͠ɺࠩ෼Λऔಘ PVUQVUϝιουͰࠩ෼Λλʔϛφϧʹදࣔ
  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 # ...লུ...
  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 ͷฦΓ஋Λ֨ೲ͢Δม਺
  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ͷΠϯελϯεΛฦ͢ϝιου
  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ΛΠϯελϯεԽ ϝιουݺͼग़͠ͱϦλʔϯ࣌ʹ ϒϩοΫ಺ͷॲཧΛ࣮ߦ͢Δ
  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Ϧλʔϯ Ͱ͋Δ৔߹
  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ϝιουͷݺͼग़͠ Ͱ͋Δ৔߹
  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ʹอଘ
  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 ˞ॏཁ
  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ϛυϧ΢ΣΞ λʔήοτͷϛυϧ΢ΣΞ λʔήοτͷ௚લͷϛυϧ΢ΣΞ Ͱಉ͡ΦϒδΣΫτΛࢦ͢
  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ϝιουʹΑͬͯ ஋͕มߋ͞ΕΔՄೳੑ͕͋Δ
  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ϝιουΛݺͿͱʜ ਖ਼͍͠ฦΓ஋Λฦ͞ͳ͍ ޙଓͷॲཧʹӨڹ͕ग़ΔͳͲ͕ى͜Γ͏Δ ‎յΕΔ
  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ϛυϧ΢ΣΞ಺Ͱ ࢖༻͞Ε͍ͯΔΦϒδΣΫτͱ͸ ແؔ܎ͷΦϒδΣΫτͱͯ͠஋Λऔಘ
  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ʹ୅ೖ
  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ͷ࣮ߦ݁ՌΛ֨ೲͨ͠഑ྻ
  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
  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‎λʔήοτͷ௚લʹݺ͹Εͨ ϛυϧ΢ΣΞͷ৘ใ
  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ϛυϧ΢ΣΞ࣮ߦ࣌ͷ؀ڥ^
  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 ᶄ௚લʹݺ͹Εͨϛυϧ΢ΣΞͷ৘ใ # ...লུ...
  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 # ...লུ... ฦΓ஋͸ͦΕͧΕ <εςʔλείʔυ \ϔομ^ <ϘσΟ>> ‎ϔομΛऔಘ͢ΔͨΊʹ ‎ΠϯσοΫε<>Λࢦఆ
  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 ϛυϧ΢ΣΞΛ௨ͨ͠લޙͰڞ௨ͷϔομ໊Λநग़ ৽͘͠௥Ճ͞Εͨϔομ໊Λநग़ ஋͕ॻ͖׵Θͬͨϔομ໊Λநग़ ϔομ໊͔Βϔομͷ஋Λऔಘ # ...লུ...
  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ϝιουͰλʔϛφϧʹදࣔ
  65. 5SBDF)FBEFSΠϯελϯεͷ!BQQDBMM FOW Λ࣮ߦ PVUQVUϝιουͰࠩ෼Λλʔϛφϧʹදࣔ 5SBDF1PJOUΛ࣮ߦ ɹ‎ࣗ෼ΑΓલͷશͯͷϛυϧ΢ΣΞͷ৘ใΛऩू NPEVMF%FTDSJCBCMF DMBTT3FTVMU DMBTT5SBDF)FBEFS DMBTT5SBDF)FBEFS

    5SBDF)FBEFSͷॲཧͷྲྀΕͷ͓͞Β͍ !BQQDBMM FOW ͷฦΓ஋Λޙଓͷϛυϧ΢ΣΞʹ౉͢ 5SBDF)FBEFSΠϯελϯεDBMM FOW ͕ݺ͹ΕΔͱ ௐ΂͍ͨϛυϧ΢ΣΞͷΠϯελϯεDBMM FOW  ɹ‎ͦΕͧΕͷฦΓ஋Λൺֱ͠ɺࠩ෼Λऔಘ
  66. ͓ർΕ༷Ͱͨ͠✨

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

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

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

  70. ݁Ռ ࣮ࡍͷը໘ ‎Ͱ͖·ͨ͠ "DUJPO%JTQBUDI$PPLJFTΛ௨ͨ͠ޙɺ ৽͘͠௥Ճ͞ΕͨϔομΛλʔϛφϧʹදࣔ͢Δ

  71. ---------------------------------------------------- TraceHeader printing... [Target Middleware] ActionDispatch::Cookies [New Headers] - Set-Cookie:

    _sampleapp_session=P8jTL8...; path=/; HttpOnly [Changed Headers] - ETag: W/"f25d17d6ad73a7091771928fef7cc6f8" ---------------------------------------------------- ϛυϧ΢ΣΞ໊ ৽͍͠ϔομͷ໊લͱ஋ ஋͕ॻ͖׵Θͬͨϔομͷ໊લͱ஋ ݁Ռ ֦େ "DUJPO%JTQBUDI$PPLJFTΛ௨ͨ͠ޙɺ ৽͘͠௥Ճ͞ΕͨϔομΛλʔϛφϧʹදࣔ͢Δ
  72. ৽͘͠௥Ճ͞Εͨϔομ4FU$PPLJF ᶃ@TBNQMFBQQ@TFTTJPO1K5-IUCIPHFIPHFGVHBHVGB ᶄQBUI ᶅ)UUQ0OMZ ஋͕มߋ͞Εͨϔομ&5BH ᶆ8GEEBEBGFGDDG "DUJPO%JTQBUDI$PPLJFT͕ϔομʹ༩࣮͑ͨࡍͷ஋͔Β ৭ʑͳൃݟ͕͋Γ·ͨ͠ ݁Ռ͔ΒಘΒΕͨ΋ͷ ᶃ஋͸ʮ@ΞϓϦ໊@TFTTJPOϥϯμϜͳӳ਺ࣈʯ

    ᶄσϑΥϧτͰQBUIଐੑ͕ϧʔτʹઃఆ͞ΕΔ ᶅσϑΥϧτͰ)UUQ0OMZʹͳΔ ᶆ&5BH͸Ͳͷϛυϧ΢ΣΞΛ௨ͯ͠΋ॻ͖׵ΘΔ
  73. 'VLVPLBSC͔Βͷ͓ͨΑΓ঺հ CZ!VE[VSB͞Μ ൃදࢿྉͷϨϏϡʔΛ͓ئ͍ͨ͠'VLVPLBSC͔Β ײ૝Λ௖͖·ͨ͠ɻ

  74. 5SBDF)FBEFSͷ༗ޮੑ

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

  76. ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ ɹ4QFDJBM5IBOLT✨  !UEUET͞Μ !LBLVUBOJ͞Μ  !KPLFS͞Μɹ !ZPVDIBO͞Μ  !PLVSBNBTBGVNJ͞Μ

    !VE[VSB͞Μ  !KJNMPDL͞Μ"TBLVTBSC⚡'VLVPLBSC ը૾ग़యIUUQTUXJUUFSDPN