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
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
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.4k
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
「エンジニアインターン、どうやって取った?」準備のリアルを語るLT会 Progate BAR
akiomatic
0
120
oxlintはeslint/typescript-eslintを置き換えられるのか
shomafujita
2
320
AI 時代のソフトウェア設計の学び方
masuda220
PRO
29
12k
DynamoDBには集計系のクエリがないけどなんとかしたい
musan
1
130
決定論的オーケストレーションの設計と実装 / Design and Implementation of Deterministic Orchestration
nrslib
3
1.1k
フロントエンドとバックエンドで「1文字」を揃えよう
youkidearitai
PRO
0
210
Spec Driven Development | AI Summit Lisbon
danielsogl
PRO
0
150
AIとASP.NET Coreで雑Webアプリを作った話
mayuki
0
340
New "Type" system on PicoRuby
pocke
1
470
TypeSpec で繋ぐ複数プロダクトの型安全
maroon8021
1
400
AIとRubyの静的型付け
ukin0k0
0
540
Spring Security 実践 ─ GraphQL APIで実務に役立つ 認証・認可 を学ぶ
wagyu
0
150
Featured
See All Featured
The Spectacular Lies of Maps
axbom
PRO
1
790
Code Reviewing Like a Champion
maltzj
528
40k
The untapped power of vector embeddings
frankvandijk
2
1.7k
Optimising Largest Contentful Paint
csswizardry
37
3.7k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
220
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
320
Chasing Engaging Ingredients in Design
codingconduct
0
210
The Language of Interfaces
destraynor
162
27k
The World Runs on Bad Software
bkeepers
PRO
72
12k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
1.9k
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.2k
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