Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Rackミドルウェア入門のためのRackミドルウェア
Search
Misaki Shioi(塩井美咲/しおい)
December 21, 2019
Programming
6.6k
6
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Rackミドルウェア入門のためのRackミドルウェア
Misaki Shioi(塩井美咲/しおい)
December 21, 2019
More Decks by Misaki Shioi(塩井美咲/しおい)
See All by Misaki Shioi(塩井美咲/しおい)
The Less-Told Story of Socket Timeouts
coe401_
3
2.5k
Making TCPSocket.new "Happy"!
coe401_
1
9.3k
たのしいSocketのしくみ / Socket Under a Microscope
coe401_
10
3.2k
XPE2-bookclub Explained
coe401_
0
220
Some more adventure of Happy Eyeballs
coe401_
2
490
Introduction of Happy Eyeballs Version 2 (RFC8305) to the Socket library
coe401_
1
560
An adventure of Happy Eyeballs
coe401_
3
13k
Implementing "++" operator, stepping into parse.y
coe401_
4
14k
たのしいRubyの構文解析ツアー
coe401_
7
4.8k
Other Decks in Programming
See All in Programming
Webフレームワークの ベンチマークについて
yusukebe
0
160
Javaの型とAI時代に型が大事な理由 / java types and type in AI era
kishida
2
130
[2026年度第1回ORセミナー] 計画最適化ベンチャーと競技プログラミング人材
terryu16
0
260
ECSアプリログをFireLensでコスト削減しようとしたけど諦めた話 in Fargate×Node.js
akihisaikeda
2
4k
「なぜそう決めたのか」を残し続ける仕組み ― Notion AI カスタムエージェント × Slack連携による設計判断の自動記録 - NIKKEI Tech Talk #47
niftycorp
PRO
0
140
不変条件と整合性境界—ビジネスが決める設計判断と実現パターン / Invariants and Consistency Boundaries
nrslib
13
3.7k
Java × distroless で 軽量なコンテナイメージを / Java on Distroless
contour_gara
0
540
決定論的オーケストレーションの設計と実装 / Design and Implementation of Deterministic Orchestration
nrslib
3
1.3k
作って学ぶ、 JSX (TSX) ランタイムの基本
syumai
7
1.6k
Datadog × OpenTelemetry 入門と実践のあいだ
kn_to_maxpno
1
150
AIで効率化できた業務・日常
ochtum
0
130
Claspは野良GASの夢をみるか
takter00
0
190
Featured
See All Featured
Code Reviewing Like a Champion
maltzj
528
40k
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
610
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
190
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
11k
Building Adaptive Systems
keathley
44
3k
Balancing Empowerment & Direction
lara
6
1.2k
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
250
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
4k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
200
How to make the Groovebox
asonas
2
2.2k
KATA
mclloyd
PRO
35
15k
A Tale of Four Properties
chriscoyier
163
24k
Transcript
3BDLϛυϧΣΞೖͷͨΊͷ 3BDLϛυϧΣΞ ԘҪඒ࡙!DPF@ %FD 5PLZP(JSMTSC.FFUVQWPM
ٕज़తʹ͍༰ؚ·Ε͍ͯΔ͔ͱࢥ͍·͢ɻ օ༷͔Βͷ͝ࢦఠɾ13Λ ͓͓ͪͯ͠Γ·͢
ࣗݾհ ԘҪඒ࡙!DPF@ 8FCϓϩάϥϚGSPNגࣜձࣾΩϟλϧ 5BNBSCɺ"TBLVTBSCɺ'VLVPLBSCʢཧʣʹ͍·͢ ࠷ۙؾʹͳΔϥΠϒϥϦ3BDL
ࣗݾհ ԘҪඒ࡙!DPF@ 8FCϓϩάϥϚGSPNגࣜձࣾΩϟλϧ 5BNBSCɺ"TBLVTBSCɺ'VLVPLBSCʢཧʣʹ͍·͢ ࠷ۙؾʹͳΔϥΠϒϥϦ3BDL ‐ࠓͷ͓
3BDLͬͯԿͰ͚ͨͬ͠ʜʁ ʢهԱࣦʣ
8FCαʔόʔͱ8FCΞϓϦέʔγϣϯΛܨ͙ϓϩτίϧ 8FCαʔόʔͱ8FCΞϓϦέʔγϣϯΛܨ͙ϥΠϒϥϦ 3BDLϓϩτίϧΛຬͨͨ͠8FCαʔόʔͱ 3BDLϓϩτίϧΛຬͨͨ͠8FCΞϓϦέʔγϣϯؒΛ 3BDLϥΠϒϥϦ͕औΓ࣋ͭ 3BDLͱ ը૾ग़యɿIUUQTSVCZPOSBJMTPSH͓ΑͼIUUQTSBDLHJUIVCJP
8FCαʔόʔͱ8FCΞϓϦέʔγϣϯΛܨ͙ϓϩτίϧ 8FCαʔόʔͱ8FCΞϓϦέʔγϣϯΛܨ͙ϥΠϒϥϦ 3BDLϓϩτίϧΛຬͨͨ͠8FCαʔόʔͱ 3BDLϓϩτίϧΛຬͨͨ͠8FCΞϓϦέʔγϣϯؒΛ 3BDLϥΠϒϥϦ͕औΓ࣋ͭ 3BDLͱ ը૾ग़యɿIUUQTSVCZPOSBJMTPSH͓ΑͼIUUQTSBDLHJUIVCJP 3BDLΞϓϦέʔγϣϯ
3BDLΞϓϦέʔγϣϯͷ͓ ը૾ग़యɿIUUQTSVCZPOSBJMTPSH͓ΑͼIUUQTSBDLHJUIVCJP ɹྫ͑ɺ3BJMTΞϓϦέʔγϣϯ͔Β ɹ3BJMTಛ༗ͷॾʑΛશ෦ണ͕͍ͯ͘͠ͱʜ ɹ
3BDLΞϓϦέʔγϣϯͷ͓ ɹྫ͑ɺ3BJMTΞϓϦέʔγϣϯ͔Β ɹ3BJMTಛ༗ͷॾʑΛશ෦ണ͕͍ͯ͘͠ͱʜ ɹ ࠷ޙʹΔͷ͕ૉͷ3BDLΞϓϦέʔγϣϯ ˞3BJMTҎ֎ͷ3VCZͰॻ͔Εͨ8FCΞϓϦέʔγϣϯϑϨʔϜϫʔΫಉ༷ ը૾ग़యɿIUUQTSVCZPOSBJMTPSH͓ΑͼIUUQTSBDLHJUIVCJP
Ұ൪γϯϓϧͳྫ ɹ3BDLΞϓϦέʔγϣϯɺ ɹ8FCΞϓϦέʔγϣϯΛߏ͢ΔͨΊʹඞཁͳ ɹͭͷཁૉΛ࣋ͬͨྻ͔ΒΔ [ 200, { "Content-Type" => "text/plain"
}, ["Hello World!\n"] ] εςʔλείʔυ ϔομ ϘσΟ 3BDLΞϓϦέʔγϣϯͷߏ
Ұ൪γϯϓϧͳྫ ɹ ͱ͍͑ ɹ࣮ࡍͷ8FCΞϓϦέʔγϣϯ ɹͬͱ৭ʑෳࡶͳػೳΛ͍࣋ͬͯΔͷͳͷͰʜʁ [ 200, { "Content-Type" =>
"text/plain" }, ["Hello World!\n"] ]
Ұ൪γϯϓϧͳྫ ɹ ͱ͍͑ ͦΜͳ࣌3BDLϛυϧΣΞͷग़൪ ɹ࣮ࡍͷ8FCΞϓϦέʔγϣϯ ɹͬͱ৭ʑෳࡶͳػೳΛ͍࣋ͬͯΔͷͳͷͰʜʁ [ 200, { "Content-Type"
=> "text/plain" }, ["Hello World!\n"] ]
3BDLϛυϧΣΞͱ 8FCΞϓϦέʔγϣϯ͕ඞཁͱ͢Δ൚༻తͳػೳΛ 3BDLΞϓϦέʔγϣϯʹՃ͢ΔͨΊͷ ϥΠϒϥϦ ͨͪ ɹɹ˞3BDLϛυϧΣΞ3BDLͷػߏΛར༻͍ͯ͠Δ ը૾ग़యɿIUUQTSBDLHJUIVCJP
ػೳ ػೳ ػೳ
3BDLϛυϧΣΞ" "ػೳΛՃ 3BDLϛυϧΣΞ# #ػೳΛՃ 3BDLϛυϧΣΞ$ $ػೳΛՃ Α͘ݟΔΠϝʔδਤ 3BDLΞϓϦέʔγϣϯΛத৺ʹɺ ֤3BDLϛυϧΣΞ͕ͦΕͧΕͷػೳΛՃ ը૾ग़యɿIUUQTSBDLHJUIVCJP
Α͘ݟΔΠϝʔδਤ 3BDLΞϓϦέʔγϣϯ 3BDLΞϓϦ 3BDLϛυϧΣΞҰͭͷ8FCΞϓϦ ೖΕࢠঢ়ʹͳ͍ͬͯΔ " # $
3BJMTͷ߹ ʜ Ҿ༻3BJMTΨΠυ3BJMTͱ3BDL"DUJPO%JTQBUDIFSͷϛυϧΣΞελοΫ 3BJMTΞϓϦέʔγϣϯͰ ଟ͘ͷ3BDLϛυϧΣΞ͕ΘΕ͍ͯΔ
ྫ͑ ActionDispatch::Cookies cookieػೳΛఏڙ͠·͢ Ҿ༻3BJMTΨΠυ3BJMTͱ3BDL"DUJPO%JTQBUDIFSͷϛυϧΣΞελοΫ
ྫ͑ ͳΔ΄Ͳʂ ʢΘ͔Βͳ͍ʣ Ҿ༻3BJMTΨΠυ3BJMTͱ3BDL"DUJPO%JTQBUDIFSͷϛυϧΣΞελοΫ
ྫɿ"DUJPO%JTQBUDI$PPLJFTͷ߹ɹ ࣝͱ͕͍ͯࣗͬͯ͠Δ͜ͱ ɹαʔόʔΫϥΠΞϯτʹରͯ͠ ɹɹϨεϙϯεϔομΛฦ͢ ɹϨεϙϯεϔομʹ ɹɹ$PPLJFͷ໊લͱؚ͕·Ε͍ͯΔ Կ͕Θ͔Βͳ͍ͷ͔
ྫɿ"DUJPO%JTQBUDI$PPLJFTͷ߹ɹ ࣝͱ͕͍ͯࣗͬͯ͠Δ͜ͱ ɹαʔόʔΫϥΠΞϯτʹରͯ͠ ɹɹϨεϙϯεϔομΛฦ͢ ɹϨεϙϯεϔομʹ ɹɹ$PPLJFͷ໊લͱؚ͕·Ε͍ͯΔ Կ͕Θ͔Βͳ͍ͷ͔ $PPLJFͷ໊લͱͱ۩ମతʹԿʁ
Γ͍ͨ ح৺
ͱ͍͏͜ͱͰɺ ͔͜͜Β͕ຊฤͰ͢
͘͡ ɹ3BDLϛυϧΣΞೖͷͨΊͷ ɹ3BDLϛυϧΣΞ ᶃతͱՌ ᶄ࣮ํͱํ๏ ᶅ༗ޮੑͷݕূ
ɹ3BDLϛυϧΣΞೖͷͨΊͷ3BDLϛυϧΣΞ ᶃతͱՌ
త ྫ͑ ֤3BDLϛυϧΣΞΛ௨͢લͱ௨ͨ͠ޙͰɺ ϨεϙϯεϔομʹͲΜͳมߋ͕͋ͬͨͷ͔Γ͍ͨ ը૾ग़యɿIUUQTSBDLHJUIVCJP 3BDLϛυϧΣΞ#Ͱ ൃੜͨ͠มߋΛΓ͍ͨ 3BDLΞϓϦέʔγϣϯ "
# $
ରͷ3BDLϛυϧΣΞΛ௨ͨ͠ޙͷ ϨεϙϯεϔομͷมԽΛλʔϛφϧʹදࣔ͢Δ 3BDLϛυϧΣΞ Λ࡞Γ·ͨ͠ Ռ
ͦͷ໊ 5SBDF)FBEFS IUUQTHJUIVCDPNTIJPJNNUSBDF@IFBEFS
ௐ͍ͨϛυϧΣΞʹରͯ͠ 5SBDF)FBEFSϛυϧΣΞΛJOTFSU@CFGPSF͢Δ class Application < Rails::Application config.middleware.insert_before ActionDispatch::Cookies, TraceHeader end
͍ํ 3BJMTͷ߹ DPOpHBQQMJDBUJPOSC
class Application < Rails::Application config.middleware.insert_before ActionDispatch::Cookies, TraceHeader end ɹ[Target Middleware]
ɹ ActionDispatch::Cookies ɹ[New Headers] ɹ - ʁʁʁʁ ௐ͍ͨϛυϧΣΞʹରͯ͠ 5SBDF)FBEFSϛυϧΣΞΛJOTFSU@CFGPSF͢Δ ͍ํ 3BJMTͷ߹ λʔϛφϧʹ͕ࠩදࣔ͞ΕΔ DPOpHBQQMJDBUJPOSC
ɹ3BDLϛυϧΣΞೖͷͨΊͷ3BDLϛυϧΣΞ ᶄ࣮ํͱํ๏
લఏ 3BDLΞϓϦέʔγϣϯͱ3BDLϛυϧΣΞɺ ڞ௨ͷن֨ʹԊ࣮ͬͯ͞Ε͍ͯΔ ࣮ߦڥ FOW ΛҾʹऔΔΠϯελϯεϝιουDBMMΛ࣮͢Δ 3BDLΞϓϦέʔγϣϯͷ߹ DBMMϝιου
<εςʔλείʔυ \ϔομ^ <ϘσΟ>> ͷྻΛฦ͢ 3BDLϛυϧΣΞͷ߹ ᶃΠϯελϯεม!BQQʹ ࣗͷଆͷΫϥεͷΠϯελϯεΛ࣋ͭ ᶄDBMMϝιουͷதͰ !BQQʹରͯ͠DBMMϝιουΛݺͿ ࣍ϖʔδͰ ͏গ͠ৄ͘͠ )551Ϩεϙϯε " # $
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ʹࣗͷଆͷΫϥεͷΠϯελϯεΛ࣋ͭ " # $
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
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
3BDLϛυϧΣΞͷ෦ߏ͔ΒΘ͔Δ͜ͱ ը૾ग़యɿIUUQTSBDLHJUIVCJP $ΠϯελϯεDBMM FOW <εςʔλείʔυ \ϔομ^ <ϘσΟ>> #ΠϯελϯεDBMM FOW
<εςʔλείʔυ \ϔομ^ <ϘσΟ>> "ΠϯελϯεDBMM FOW <εςʔλείʔυ \ϔομ^ <ϘσΟ>> 3BDLΞϓϦέʔγϣϯ 3BDLϛυϧΣΞڞ௨ͷن֨ʹԊ࣮ͬͯ͞Ε͍ͯΔ ͲͷϛυϧΣΞʹରͯ͠DBMMΛݺΜͰ ࠷Լͷ3BDLΞϓϦέʔγϣϯ·ͰDBMM͞ΕΔ ࠷ऴతʹಉ͡ߏͷྻ͕ฦΔ " # $
͔͜͜ΒཱͯͨԾઆ ը૾ग़యɿIUUQTSBDLHJUIVCJP ରͷϛυϧΣΞͱͦͷલʹݺΕͨϛυϧΣΞͷ DBMMϝιουΛݺͼɺฦΓಉ࢜Λൺֱ͢Εྑ͍ͷͰʁ $ΠϯελϯεDBMM FOW $࣌ͷฦΓ #ΠϯελϯεDBMM FOW
#࣌ͷฦΓ ᶃ#࣌ͱ$࣌ͷϛυϧΣΞ ɹͦΕͧΕͷΠϯελϯεʹͦΕͧΕDBMMΛݺͿ ᶄͦΕͧΕͷฦΓΛऔಘ͢Δ ᶅฦΓಉ࢜ͷࠩΛλʔϛφϧʹग़ྗ͢Δ 3BDLΞϓϦέʔγϣϯ ࣮ํλʔήοτ͕#ͷ߹ʜ#͕ݺΕΔલʹ$͕ݺΕΔ " $ #
͔͠͠
՝ ը૾ग़యɿIUUQTSBDLHJUIVCJP ྫ͑λʔήοτ͕#ͷ߹ 3BDLΞϓϦέʔγϣϯͷߏ্ɺ ؒʹ͋ΔϛυϧΣΞʹରͯ͠ॲཧΛڬΉ͜ͱ͕Ͱ͖ͳ͍ ᶃ"ͷΠϯελϯεʹରͯ͠DBMM͕ݺΕΔ ᶄ࠷Լͷ3BDLΞϓϦέʔγϣϯ·Ͱ ɹશͯͷϛυϧΣΞͷDBMM͕ݺΕΔ ᶅ8FCΞϓϦέʔγϣϯͱ͕ͯ͠ฦΔ ࠓճDBMMΛݺͼ͍ͨ
#࣌ͱ$࣌Ͱ ॲཧΛڬΉ͜ͱ͕Ͱ͖ͳ͍ ͭ·Γʜ ᶃ ᶄ ᶅ " # $
՝ " # $ ը૾ग़యɿIUUQTSBDLHJUIVCJP ྫ͑λʔήοτ͕#ͷ߹ 3BDLΞϓϦέʔγϣϯͷߏ্ɺ ؒʹ͋ΔϛυϧΣΞʹରͯ͠ॲཧΛڬΉ͜ͱ͕Ͱ͖ͳ͍ "ͷΠϯελϯεʹରͯ͠DBMM͕ݺΕΔͱ ࠷Լͷ3BDLΞϓϦέʔγϣϯ·Ͱ
શͯͷϛυϧΣΞͷDBMM͕ݺΕΔ ࠓճDBMMΛݺͼ͍ͨ #࣌ͱ$࣌Ͱ ॲཧΛڬΉ͜ͱ͕Ͱ͖ͳ͍ ͭ·Γʜ
՝ " # $ ը૾ग़యɿIUUQTSBDLHJUIVCJP ྫ͑λʔήοτ͕#ͷ߹ 3BDLΞϓϦέʔγϣϯͷߏ্ɺ ؒʹ͋ΔϛυϧΣΞʹରͯ͠ॲཧΛڬΉ͜ͱ͕Ͱ͖ͳ͍ "ͷΠϯελϯεʹରͯ͠DBMM͕ݺΕΔͱ ࠷Լͷ3BDLΞϓϦέʔγϣϯ·Ͱ
શͯͷϛυϧΣΞͷDBMM͕ݺΕΔ ࠓճDBMMΛݺͼ͍ͨ #࣌ͱ$࣌Ͱ ॲཧΛڬΉ͜ͱ͕Ͱ͖ͳ͍ ͭ·Γʜ 5SBDF1PJOUͷग़൪Ͱʁ
5SBDF1PJOUͱ ɹϓϩάϥϜ࣮ߦதͷΠϕϯτʹϑοΫͯ͠ ɹԿͰͰ͖Δ3VCZͷΈࠐΈϥΠϒϥϦ ɹৄࡉׂѪ ɹࢀߟهࣄ ɹDMBTT5SBDF1PJOU ɹɹIUUQTEPDTSVCZMBOHPSHKBDMBTT5SBDF1PJOUIUNM 3VCZͷվળΛࣗຫ͍ͨ͠ ɹɹIUUQTUFDIMJGFDPPLQBEDPNFOUSZ ɹ3VCZͷ5SBDF1PJOUʹ͍ͭͯௐͯΈͨ
ɹɹIUUQTRJJUBDPNTJNBOJUFNT⒎DGF ˞Πϕϯτʜϝιουݺͼग़͠Ϧλʔϯɺ ɹɹɹɹɹɹΫϥεఆٛɺྫ֎ͷൃੜFUD
Ҏ্Λ౿·͑ͯ 5SBDF)FBEFSͷ࣮
DMBTT5SBDF)FBEFS 5SBDF1PJOUΛ༻ ɾࣗΑΓલʹ࣮ߦ͞Ε͍ͯΔશͯͷϛυϧΣΞͷใΛऩू ɾࣗͷޙʹ࣮ߦ͞ΕΔϛυϧΣΞ λʔήοτͷϛυϧΣΞͷฦΓΛ͢ ޙଓͷॲཧͷͨΊ ɹ DMBTT3FTVMU ɾλʔήοτͱɺͦͷલʹ࣮ߦ͞ΕͨϛυϧΣΞͷ
ΠϯελϯεΛநग़ͯ͠DBMMΛ࣮ߦ ͦΕͧΕͷฦΓΛൺֱ͠ɺࠩΛฦ͢ϝιουΛ࣮ NPEVMF%FTDSJCBCMF ɾλʔϛφϧʹදࣔ͢ΔจࣈྻΛ͑ΔPVUQVUϝιουΛ࣮ ৄࡉׂѪ ˞5SBDF)FBEFSࣗΞϓϦέʔγϣϯʹมߋΛՃ͑ͳ͍ 5SBDF)FBEFSͷߏ
5SBDF)FBEFSΠϯελϯεͷ!BQQDBMM FOW Λ࣮ߦ 5SBDF1PJOUΛ࣮ߦ ɹࣗΑΓલͷશͯͷϛυϧΣΞͷใΛऩू NPEVMF%FTDSJCBCMF DMBTT3FTVMU DMBTT5SBDF)FBEFS DMBTT5SBDF)FBEFS 5SBDF)FBEFSͷॲཧͷྲྀΕ
!BQQDBMM FOW ͷฦΓΛޙଓͷϛυϧΣΞʹ͢ 5SBDF)FBEFSΠϯελϯεDBMM FOW ͕ݺΕΔͱ ௐ͍ͨϛυϧΣΞͷΠϯελϯεDBMM FOW ɹͦΕͧΕͷฦΓΛൺֱ͠ɺࠩΛऔಘ PVUQVUϝιουͰࠩΛλʔϛφϧʹදࣔ
࣮ 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 # ...লུ...
࣮ 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λʔήοτͷϛυϧΣΞͷΠϯελϯε !EBUBT5SBDF1PJOUͷ࣮ߦ݁ՌΛ֨ೲ͢Δྻ !pYFE@BQQ!BQQDBMM FOW ͷฦΓΛ֨ೲ͢Δม
࣮ 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Λ ᶆޙଓͷϛυϧΣΞʹ͢ ˞USBDFS5SBDF1PJOUͷΠϯελϯεΛฦ͢ϝιου
࣮ 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ΛΠϯελϯεԽ ϝιουݺͼग़͠ͱϦλʔϯ࣌ʹ ϒϩοΫͷॲཧΛ࣮ߦ͢Δ
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Ϧλʔϯ Ͱ͋Δ߹
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ϝιουͷݺͼग़͠ Ͱ͋Δ߹
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ʹอଘ
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 ˞ॏཁ
࣮ 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ϛυϧΣΞ λʔήοτͷϛυϧΣΞ λʔήοτͷલͷϛυϧΣΞ Ͱಉ͡ΦϒδΣΫτΛࢦ͢
࣮ 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ϝιουʹΑͬͯ ͕มߋ͞ΕΔՄೳੑ͕͋Δ
࣮ 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ϝιουΛݺͿͱʜ ਖ਼͍͠ฦΓΛฦ͞ͳ͍ ޙଓͷॲཧʹӨڹ͕ग़ΔͳͲ͕ى͜Γ͏Δ յΕΔ
࣮ 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ϛυϧΣΞͰ ༻͞Ε͍ͯΔΦϒδΣΫτͱ ແؔͷΦϒδΣΫτͱͯ͠Λऔಘ
࣮ 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ʹೖ
࣮ 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λʔήοτͷϛυϧΣΞͷΠϯελϯε !EBUBT5SBDF1PJOUͷ࣮ߦ݁ՌΛ֨ೲͨ͠ྻ
࣮ 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
࣮ 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λʔήοτͷϛυϧΣΞͷΠϯελϯε ҾEBUBT5SBDF1PJOUͷ࣮ߦ݁ՌΛ֨ೲͨ͠ྻ ʲҎԼEBUBT͔Βநग़ʳ !UBSHFU@IBTIλʔήοτͷϛυϧΣΞͷใ !JOOFS@IBTIλʔήοτͷલʹݺΕͨ ϛυϧΣΞͷใ
࣮ 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ϛυϧΣΞ࣮ߦ࣌ͷڥ^
࣮ 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 ᶄલʹݺΕͨϛυϧΣΞͷใ # ...লུ...
࣮ 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 # ...লུ... ฦΓͦΕͧΕ <εςʔλείʔυ \ϔομ^ <ϘσΟ>> ϔομΛऔಘ͢ΔͨΊʹ ΠϯσοΫε<>Λࢦఆ
࣮ 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 ϛυϧΣΞΛ௨ͨ͠લޙͰڞ௨ͷϔομ໊Λநग़ ৽͘͠Ճ͞Εͨϔομ໊Λநग़ ͕ॻ͖Θͬͨϔομ໊Λநग़ ϔομ໊͔ΒϔομͷΛऔಘ # ...লུ...
࣮ 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ϝιουͰλʔϛφϧʹදࣔ
5SBDF)FBEFSΠϯελϯεͷ!BQQDBMM FOW Λ࣮ߦ PVUQVUϝιουͰࠩΛλʔϛφϧʹදࣔ 5SBDF1PJOUΛ࣮ߦ ɹࣗΑΓલͷશͯͷϛυϧΣΞͷใΛऩू NPEVMF%FTDSJCBCMF DMBTT3FTVMU DMBTT5SBDF)FBEFS DMBTT5SBDF)FBEFS
5SBDF)FBEFSͷॲཧͷྲྀΕͷ͓͞Β͍ !BQQDBMM FOW ͷฦΓΛޙଓͷϛυϧΣΞʹ͢ 5SBDF)FBEFSΠϯελϯεDBMM FOW ͕ݺΕΔͱ ௐ͍ͨϛυϧΣΞͷΠϯελϯεDBMM FOW ɹͦΕͧΕͷฦΓΛൺֱ͠ɺࠩΛऔಘ
͓ർΕ༷Ͱͨ͠✨
ɹ3BDLϛυϧΣΞೖͷͨΊͷ3BDLϛυϧΣΞ ᶅ༗ޮੑͷݕূ
"DUJPO%JTQBUDI$PPLJFTΛ௨ͨ͠ޙɺ ৽͘͠Ճ͞ΕͨϔομΛλʔϛφϧʹදࣔ͢Δ class Application < Rails::Application config.middleware.insert_before ActionDispatch::Cookies, TraceHeader end
ݕূ DPOpHBQQMJDBUJPOSC ݕূڥ3VCZ 3BJMT ɹ4DB⒎PME͚ͨͩ͠ͷ؆୯ͳΞϓϦέʔγϣϯ ݕূํ๏αʔόʔΛ্ཱͪ͛ͯదͳϖʔδʹΞΫηε
ͦͷ݁Ռ
݁Ռ ࣮ࡍͷը໘ Ͱ͖·ͨ͠ "DUJPO%JTQBUDI$PPLJFTΛ௨ͨ͠ޙɺ ৽͘͠Ճ͞ΕͨϔομΛλʔϛφϧʹදࣔ͢Δ
---------------------------------------------------- TraceHeader printing... [Target Middleware] ActionDispatch::Cookies [New Headers] - Set-Cookie:
_sampleapp_session=P8jTL8...; path=/; HttpOnly [Changed Headers] - ETag: W/"f25d17d6ad73a7091771928fef7cc6f8" ---------------------------------------------------- ϛυϧΣΞ໊ ৽͍͠ϔομͷ໊લͱ ͕ॻ͖Θͬͨϔομͷ໊લͱ ݁Ռ ֦େ "DUJPO%JTQBUDI$PPLJFTΛ௨ͨ͠ޙɺ ৽͘͠Ճ͞ΕͨϔομΛλʔϛφϧʹදࣔ͢Δ
৽͘͠Ճ͞Εͨϔομ4FU$PPLJF ᶃ@TBNQMFBQQ@TFTTJPO1K5-IUCIPHFIPHFGVHBHVGB ᶄQBUI ᶅ)UUQ0OMZ ͕มߋ͞Εͨϔομ&5BH ᶆ8GEEBEBGFGDDG "DUJPO%JTQBUDI$PPLJFT͕ϔομʹ༩࣮͑ͨࡍͷ͔Β ৭ʑͳൃݟ͕͋Γ·ͨ͠ ݁Ռ͔ΒಘΒΕͨͷ ᶃʮ@ΞϓϦ໊@TFTTJPOϥϯμϜͳӳࣈʯ
ᶄσϑΥϧτͰQBUIଐੑ͕ϧʔτʹઃఆ͞ΕΔ ᶅσϑΥϧτͰ)UUQ0OMZʹͳΔ ᶆ&5BHͲͷϛυϧΣΞΛ௨ͯ͠ॻ͖ΘΔ
'VLVPLBSC͔Βͷ͓ͨΑΓհ CZ!VE[VSB͞Μ ൃදࢿྉͷϨϏϡʔΛ͓ئ͍ͨ͠'VLVPLBSC͔Β ײΛ͖·ͨ͠ɻ
5SBDF)FBEFSͷ༗ޮੑ
5SBDF)FBEFSͷ༗ޮੑ ͋Γͦ͏ 13͍ͭͰ͓͓ͪͯ͠Γ·͢ IUUQTHJUIVCDPNTIJPJNNUSBDF@IFBEFS
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ ɹ4QFDJBM5IBOLT✨ !UEUET͞Μ !LBLVUBOJ͞Μ !KPLFS͞Μɹ !ZPVDIBO͞Μ !PLVSBNBTBGVNJ͞Μ
!VE[VSB͞Μ !KJNMPDL͞Μ"TBLVTBSC⚡'VLVPLBSC ը૾ग़యIUUQTUXJUUFSDPN