Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Rackミドルウェア入門のためのRackミドルウェア
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Misaki Shioi(塩井美咲/しおい)
December 21, 2019
Programming
6.7k
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(塩井美咲/しおい)
時うどん〜Socket.getifaddrsで学ぶネットワーク編 / Tokiudon: The Socket.getifaddrs Edition
coe401_
4
310
The Less-Told Story of Socket Timeouts
coe401_
3
4k
Making TCPSocket.new "Happy"!
coe401_
1
11k
たのしいSocketのしくみ / Socket Under a Microscope
coe401_
10
3.3k
XPE2-bookclub Explained
coe401_
0
390
Some more adventure of Happy Eyeballs
coe401_
2
530
Introduction of Happy Eyeballs Version 2 (RFC8305) to the Socket library
coe401_
1
590
An adventure of Happy Eyeballs
coe401_
3
14k
Implementing "++" operator, stepping into parse.y
coe401_
4
15k
Other Decks in Programming
See All in Programming
UnityでSystem.Net.WebSocketsなWebSocketサーバが動かないのでUnity Monoのコードを覗いてみた / about implementing websocket server with unity mono
drumath2237
1
610
When benchmarks go bad - what I learned from measuring performance wrong
hollycummins
0
220
Optunaを作ったときにやりたかったこと、その後 (2026/10/16, Optuna Meetup #3)
iwiwi
1
440
AIで開発が速くなった先で、開発チームは何を目指すか
shihochan
1
1.6k
S3 TablesのIcebergデータに、AIエージェントからアクセスしてみた / 20261016developersio2026joetsu-accessing-iceberg-in-s3tables-via-agent
kasacchiful
PRO
0
160
ジョジョの世界をXRで再現する
mofurune
0
170
ハーネス設計入門 〜 基礎知識の整理から実務へのステップアップ 〜
kinopeee
28
33k
Simple Storage Service(S3) is not simple
iwatsukayura
0
290
golang-bob.pdf
iwatsukayura
0
130
全ての永続トークンを、生まれる前に消し去りたい!
sylph01
2
970
AWSに止められる覚悟してますか?
morizo_1984
2
540
[JA] Domain Modeling with Vanilla Rails: 「操作」から再考するRailsの設計論
yasaichi
3
430
Featured
See All Featured
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
232
55k
Building Applications with DynamoDB
mza
96
7.2k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
31k
The Cost Of JavaScript in 2023
addyosmani
55
10k
Information Architects: The Missing Link in Design Systems
soysaucechin
1
1.2k
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.5k
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.8k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
Building Adaptive Systems
keathley
44
3.3k
Into the Great Unknown - MozCon
thekraken
41
2.8k
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