Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
実録 Let's build a simple Rack compatible server
Misaki Shioi(塩井美咲/しおい)
February 11, 2020
Programming
6
1.7k
実録 Let's build a simple Rack compatible server
Misaki Shioi(塩井美咲/しおい)
February 11, 2020
Tweet
Share
More Decks by Misaki Shioi(塩井美咲/しおい)
See All by Misaki Shioi(塩井美咲/しおい)
実録mruby組み込み体験
coe401_
0
120
Toycol: Define your own application protocol
coe401_
2
1.1k
らくらくRactor
coe401_
3
290
[English ver]実録 Let's build a simple Rack compatible server
coe401_
1
88
Rackミドルウェア入門のためのRackミドルウェア
coe401_
5
4.4k
たのしいOSSコードリーディング:Let's read "cookies"🍪
coe401_
15
7.6k
ApplaudHerJp.pdf
coe401_
2
500
Other Decks in Programming
See All in Programming
クリエイティブ系のウェブサイト制作で役立つCSS技法 / CSS for develop creative website
clockmaker
2
1.7k
Learning DDD輪読会#4 / Learning DDD Book Club #4
suzushin54
1
160
【Qiita Night】新卒エンジニアによるSwift6与太予想
eiji127
0
190
近況PHP / PHP in now a days
uzulla
4
1.9k
heyにおけるSREの大切さ~マルチプロダクト運用の「楽しさ」と「難しさ」および今後の展望~
fufuhu
3
2.3k
Viteはいいぞ/Vite is Good
dojineko
1
110
GraphQL+KMM開発でわかったこと / What we learned from GraphQL+KMM development
kubode
0
140
Let's build components, not layers
thombergs
1
240
あなたの会社の古いシステム、なんとかしませんか?~システム刷新から考えるDX化への道筋とバリエーション~/webinar20220420-systems
grapecity_dev
0
130
Swift Concurrencyによる安全で快適な非同期処理
tattn
2
340
Hapticをカスタマイズしてみよう / ZOZO Tech Talk #6 Customize Haptic
endoumari
0
370
Loom is Blooming
josepaumard
3
570
Featured
See All Featured
Atom: Resistance is Futile
akmur
255
20k
GitHub's CSS Performance
jonrohan
1020
410k
The World Runs on Bad Software
bkeepers
PRO
56
5.2k
Creatively Recalculating Your Daily Design Routine
revolveconf
207
10k
How to Ace a Technical Interview
jacobian
265
21k
Debugging Ruby Performance
tmm1
65
10k
Six Lessons from altMBA
skipperchong
14
1.3k
JazzCon 2018 Closing Keynote - Leadership for the Reluctant Leader
reverentgeek
172
8.3k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
236
1M
Practical Orchestrator
shlominoach
178
8.6k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
4
660
The MySQL Ecosystem @ GitHub 2015
samlambert
238
11k
Transcript
࣮ -FU`TCVJMEBTJNQMF 3BDLDPNQBUJCMFTFSWFS⚡⚡⚡ ԘҪඒ࡙!DPF@ 'FC େߐށ3VCZձٞ
ࣗݾհ ԘҪඒ࡙ ͓͍͠ !DPF@ 8FCϓϩάϥϚ "TBLVTBSCɺ5BNBSCɺ'VLVPLBSCʢཧʣʹ͍·͢ "TBLVTBSCʹ௨͍࢝ΊͯૣҰ ࠷ۙ8FCαʔόʔΛ࡞Γ·ͨ͠
ࣗݾհ ԘҪඒ࡙ ͓͍͠ !DPF@ 8FCϓϩάϥϚ "TBLVTBSCɺ5BNBSCɺ'VLVPLBSCʢཧʣʹ͍·͢ "TBLVTBSCʹ௨͍࢝ΊͯૣҰ ࠷ۙ8FCαʔόʔΛ࡞Γ·ͨ͠ ‐ࠓͷ͓
3VCZ$POG/BTIWJMMF /PWFNCFS
ग़యɿIUUQTOPUJTUFTUIFSD(V(+MFUTCVJMEBTJNQMFIUUQTFSWFSXJUISVCZ ʮ-FU`TCVJMEBTJNQMF)551TFSWFSʯ &45)&30-"56/%&͞Μ!FTUIFS
JHBJHB͞Μ!JHBJHB ग़యɿIUUQTUXJUUFSDPNJHBJHBTUBUVT T
͏ͮΒ͞Μ!VE[VSB 'VLVPLBSC Θͨ͠ !DPF@ ग़యɿIUUQTUXJUUFSDPNVE[VSBTUBUVT T !DPF@
ͱ͍͏͜ͱͰɺ ൃදࢿྉΛࢀߟʹ γϯϓϧͳ)551αʔόʔΛ ࡞ͬͯΈ·ͨ͠
ग़དྷ্͕ͬͨͷ͕ͪ͜Β 1 require ‘socket’ 2 3 server = TCPServer.new(‘localhost’, 5000)
4 5 loop do 6 client = server.accept 7 request = client.readpartial(2048) 8 9 puts request 10 11 client.puts response <<~MESSAGE 12 HTTP/1.1 200 OK\r\n 13 Content-Type: text/plain\r\n 14 \r\n 15 Hello!\r\n 16 MESSAGE 17 end TPDLFUϥΠϒϥϦΛSFRVJSF
1 require ‘socket’ 2 3 server = TCPServer.new(‘localhost’, 5000) 4
5 loop do 6 client = server.accept 7 request = client.readpartial(2048) 8 9 puts request 10 11 client.puts response <<~MESSAGE 12 HTTP/1.1 200 OK\r\n 13 Content-Type: text/plain\r\n 14 \r\n 15 Hello!\r\n 16 MESSAGE 17 end αʔόʔଓΛPQFO ΫϥΠΞϯτ͔ΒͷଓཁٻΛड͚͚Δ ϦΫΤετϝοηʔδΛಡΈࠐΉ ϦΫΤετϝοηʔδΛαʔόʔଆʹग़ྗ దͳϨεϙϯεϝοηʔδ ϨεϙϯεϝοηʔδΛΫϥΠΞϯτଆʹग़ྗ ग़དྷ্͕ͬͨͷ͕ͪ͜Β
DVSMMPDBMIPTU ࡞ͬͨαʔόʔͷϗετͱϙʔτ൪߸
ಈ͖·ͨ͠ αʔόʔଆ ΫϥΠΞϯτଆ ϦΫΤετϝοηʔδ͕ ग़ྗ͞Ε͍ͯΔ ϨεϙϯεϘσΟ͕ ग़ྗ͞Ε͍ͯΔ
͔͠͠
ಈతͳΞϓϦέʔγϣϯʹରԠ͍ͯ͠ͳ͍⚠ 1 require ‘socket’ 2 3 server = TCPServer.new(‘localhost’, 5000)
4 5 loop do 6 client = server.accept 7 request = client.readpartial(2048) 8 9 puts request 10 11 client.puts response <<~MESSAGE 12 HTTP/1.1 200 OK\r\n 13 Content-Type: text/plain\r\n 14 \r\n 15 Hello!\r\n 16 MESSAGE 17 end ͦͦ ΞϓϦέʔγϣϯ͕ ଘࡏ͠ͳ͍ ΞΫηε͢Δͨͼɺຖճ ಉ͡Ϩεϙϯεϝοηʔδ͕ ग़ྗ͞ΕΔ
͔ͤͬ͘ͳͷͰ 3BDLDPNQBUJCMFʹ͍ͨ͠
γϯϓϧͰ3BDLDPNQBUJCMFͳ 4JNQMF3BDL$PNQBUJCMF4FSWFS ͱ͍͏໊લͷαʔόʔΛ ࡞ͬͯΈ͍ͨͱࢥ͍·͢
1 require ‘rack’ 2 require_relative ‘../server/simple_rack_compatible_server’ 3 4 class App
5 def call(env) 6 [ 7 200, 8 { ‘Content-Type’ => ‘text/html’ }, 9 [“<div><h1>Hello.</h1><p>This app is running on .…</p></div>”] 10 ] 11 end 12 end 13 14 run App.new ݕূ༻ͷ3BDLΞϓϦέʔγϣϯ͕ͪ͜Β app/sample.ru
1 require ‘rack’ 2 require_relative ‘../server/simple_rack_compatible_server’ 3 4 class App
5 def call(env) 6 [ 7 200, 8 { ‘Content-Type’ => ‘text/html’ }, 9 [“<div><h1>Hello.</h1><p>This app is running on .…</p></div>”] 10 ] 11 end 12 end 13 14 run App.new εςʔλε)5510, ϔομ$POUFOU5ZQFUFYUIUNM ϘσΟEJW I)FMMPI Q5IJTBQQJTʜQ EJW ݕূ༻ͷ3BDLΞϓϦέʔγϣϯ͕ͪ͜Β app/sample.ru ࣮ߦ͢Δͱʜ
3BDLΞϓϦέʔγϣϯ͕ىಈ͢ΔྲྀΕ SBDLVQίϚϯυΛ࣮ߦ ϋϯυϥʔΛىಈ ϋϯυϥʔʹαʔόʔΛొ αʔόʔຊମ͕ॲཧΛ։࢝ αʔόʔΛىಈ 3BDLຊମͱ αʔόʔຊମΛଓ αʔόʔ͕ ΞϓϦέʔγϣϯΛ࣮ߦ
ىಈ։࢝ 3BDLΞϓϦέʔγϣϯΛ࣮ߦ
3BDLΞϓϦέʔγϣϯ͕ىಈ͢ΔྲྀΕ SBDLVQίϚϯυΛ࣮ߦ ϋϯυϥʔΛىಈ ϋϯυϥʔʹαʔόʔΛొ αʔόʔຊମ͕ॲཧΛ։࢝ αʔόʔΛىಈ 3BDLΞϓϦέʔγϣϯΛ࣮ߦ 3BDLຊମͷ )BOEMFSϞδϡʔϧΛͬͨ αʔόʔຊମͷॲཧ
αʔόʔຊମͷॲཧ 3BDLຊମͷॲཧ
3BDLDPNQBUJCMFͳαʔόʔͷػೳཁ݅ 3BDLΞϓϦέʔγϣϯ͕ىಈ͢ΔྲྀΕΛ౿·͑ͯɺ αʔόʔʹඞཁͳػೳΛߟ͑Δ ᶃϋϯυϥʔ 3BDL)BOEMFS4JNQMF3BDL$PNQBUJCMF4FSWFS ⚡3BDLຊମͷ)BOEMFSϞδϡʔϧʹαʔόʔΛొ͢Δ ⚡αʔόʔΛىಈ͢Δ ᶄαʔόʔຊମ
4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFS ⚡ϦΫΤετΛड͚Δ ⚡ΞϓϦέʔγϣϯΛ࣮ߦ͢Δ ⚡ϨεϙϯεΛฦ͢
1 require ‘rack/handler’ 2 3 module Rack 4 module Handler
5 class SimpleRackCompatibleServer 6 def self.run(app, options = {}) 7 environment = ENV[‘RACK_ENV’] || ‘development’ 8 default_host = environment == ‘development’ ? ‘localhost’ : ‘0.0.0.0’ 9 10 host = options.delete(:Host) || default_host 11 port = options.delete(:Port) || 9292 12 args = [host, port, app] 13 ::SimpleRackCompatibleServer::Server.new(*args).start 14 end 15 end 16 17 register :simple_rack_compatible_server, SimpleRackCompatibleServer 18 end 19 end ࢀߟɿIUUQTHJUIVCDPNNBDPVSOPZFSUIJO rack/handler/simple_rack_compatible_server.rb ϋϯυϥʔΛ࣮ ࢀߟ5IJO 3BDL)BOEMFSϞδϡʔϧΛSFRVJSF
1 require ‘rack/handler’ 2 3 module Rack 4 module Handler
5 class SimpleRackCompatibleServer 6 def self.run(app, options = {}) 7 environment = ENV[‘RACK_ENV’] || ‘development’ 8 default_host = environment == ‘development’ ? ‘localhost’ : ‘0.0.0.0’ 9 10 host = options.delete(:Host) || default_host 11 port = options.delete(:Port) || 9292 12 args = [host, port, app] 13 ::SimpleRackCompatibleServer::Server.new(*args).start 14 end 15 end 16 17 register :simple_rack_compatible_server, SimpleRackCompatibleServer 18 end 19 end rack/handler/simple_rack_compatible_server.rb 3BDL)BOEMFSϞδϡʔϧʹαʔόʔΛొ͢Δ ࢀߟɿIUUQTHJUIVCDPNNBDPVSOPZFSUIJO ϋϯυϥʔΛ࣮ ࢀߟ5IJO
1 require ‘rack/handler’ 2 3 module Rack 4 module Handler
5 class SimpleRackCompatibleServer 6 def self.run(app, options = {}) 7 environment = ENV[‘RACK_ENV’] || ‘development’ 8 default_host = environment == ‘development’ ? ‘localhost’ : ‘0.0.0.0’ 9 10 host = options.delete(:Host) || default_host 11 port = options.delete(:Port) || 9292 12 args = [host, port, app] 13 ::SimpleRackCompatibleServer::Server.new(*args).start 14 end 15 end 16 17 register :simple_rack_compatible_server, SimpleRackCompatibleServer 18 end 19 end rack/handler/simple_rack_compatible_server.rb ࢀߟɿIUUQTHJUIVCDPNNBDPVSOPZFSUIJO αʔόʔΛىಈ͢Δϝιου ϋϯυϥʔΛ࣮ ࢀߟ5IJO
1 require ‘rack/handler’ 2 3 module Rack 4 module Handler
5 class SimpleRackCompatibleServer 6 def self.run(app, options = {}) 7 environment = ENV[‘RACK_ENV’] || ‘development’ 8 default_host = environment == ‘development’ ? ‘localhost’ : ‘0.0.0.0’ 9 10 host = options.delete(:Host) || default_host 11 port = options.delete(:Port) || 9292 12 13 14 end 15 end 16 17 18 end 19 end rack/handler/simple_rack_compatible_server.rb ࣮ߦڥ͔Βϗετͱϙʔτ൪߸Λઃఆ͢Δ ˞σϑΥϧτͰMPDBMIPTUʹଓ ࢀߟɿIUUQTHJUIVCDPNNBDPVSOPZFSUIJO ϋϯυϥʔΛ࣮ ࢀߟ5IJO
1 require ‘rack/handler’ 2 3 module Rack 4 module Handler
5 class SimpleRackCompatibleServer 6 def self.run(app, options = {}) 7 environment = ENV[‘RACK_ENV’] || ‘development’ 8 default_host = environment == ‘development’ ? ‘localhost’ : ‘0.0.0.0’ 9 10 host = options.delete(:Host) || default_host 11 port = options.delete(:Port) || 9292 12 args = [host, port, app] 13 14 end 15 end 16 17 18 end 19 end rack/handler/simple_rack_compatible_server.rb αʔόʔʹ͢ҾΛ༻ҙ͢Δ ⚡ϗετ ⚡ϙʔτ൪߸ ⚡3BDLΞϓϦέʔγϣϯຊମ ࢀߟɿIUUQTHJUIVCDPNNBDPVSOPZFSUIJO ϋϯυϥʔΛ࣮ ࢀߟ5IJO
1 require ‘rack/handler’ 2 3 module Rack 4 module Handler
5 class SimpleRackCompatibleServer 6 def self.run(app, options = {}) 7 environment = ENV[‘RACK_ENV’] || ‘development’ 8 default_host = environment == ‘development’ ? ‘localhost’ : ‘0.0.0.0’ 9 10 host = options.delete(:Host) || default_host 11 port = options.delete(:Port) || 9292 12 args = [host, port, app] 13 ::SimpleRackCompatibleServer::Server.new(*args).start 14 end 15 end 16 17 18 end 19 end rack/handler/simple_rack_compatible_server.rb αʔόʔ 4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFS Λ ΠϯελϯεԽ͠ OFX ɺىಈ͢Δ TUBSU ࢀߟɿIUUQTHJUIVCDPNNBDPVSOPZFSUIJO ϋϯυϥʔΛ࣮ ࢀߟ5IJO
1 require ‘socket’ 2 3 module SimpleRackCompatibleServer 4 class Server
5 def initialize(*args) 6 @host, @port, @app = args 7 end 8 9 def start 26 end 27 end 28 end simple_rack_compatible_server.rb αʔόʔΛ࣮શମ૾ ʜ ϋϯυϥʔ͔ΒҾ͖ܧ͍ͩ ⚡ϗετ ⚡ϙʔτ൪߸ ⚡3BDLΞϓϦέʔγϣϯຊମ ͰΠϯελϯεΛॳظԽ͢Δ ݩʑͷ)551αʔόʔͷॲཧʹ ͭͷมߋΛՃ ৄ࣍͘͠ͷεϥΠυ
9 def start 10 server = TCPServer.new(@host, @port) 11 12
loop do 13 client = server.accept 14 request = client.readpartial(2048) 15 16 @status, @header, @body = @app.call 17 18 puts request 19 20 client.puts <<~MESSAGE 21 #{‘HTTP/1.1 200 OK’ if @status.eql? 200}\r\n 22 #{@header.map { |k, v| [k, v].join(’: ’) }.join(“\r\n”)}\r\n 23 \r\n 24 #{@body} 25 MESSAGE 26 end simple_rack_compatible_server.rb มߋᶄ 3BDLΞϓϦέʔγϣϯ࣮ߦ ฦΓΛऔಘ͢Δ มߋᶅ ฦΓ͔ΒϨεϙϯεϝοηʔδΛੜ αʔόʔΛ࣮TUBSUϝιου มߋᶃ ϋϯυϥʔ͔Βͨ͠ ϗετͱϙʔτ൪߸Λઃఆ
͔͠͠
9 def start 10 server = TCPServer.new(@host, @port) 11 12
loop do 13 client = server.accept 14 request = client.readpartial(2048) 15 16 @status, @header, @body = @app.call(???) 17 18 puts request 19 20 client.puts <<~MESSAGE 21 #{‘HTTP/1.1 200 OK’ if @status.eql? 200}\r\n 22 #{@header.map { |k, v| [k, v].join(’: ’) }.join(“\r\n”)}\r\n 23 \r\n 24 #{@body} 25 MESSAGE 26 end simple_rack_compatible_server.rb Ͳ͏͠Α͏ʜ DBMMϝιουʹ͢Ҿ͕Θ͔Βͳ͍⚠ ڥมΛϋογϡͷܗͰ ೖΕΔඞཁ͕͋Δ
9 def start 10 server = TCPServer.new(@host, @port) 11 12
loop do 13 client = server.accept 14 request = client.readpartial(2048) 15 16 @status, @header, @body = @app.call({ }) 17 18 puts request 19 20 client.puts <<~MESSAGE 21 #{‘HTTP/1.1 200 OK’ if @status.eql? 200}\r\n 22 #{@header.map { |k, v| [k, v].join(’: ’) }.join(“\r\n”)}\r\n 23 \r\n 24 #{@body} 25 MESSAGE 26 end simple_rack_compatible_server.rb Θ͔Βͳ͍ͷͰ ۭϋογϡΛ ೖΕͯΈ·ͨ͠
SBDLVQTTJNQMF@SBDL@DPNQBUJCMF@TFSWFS ͱΓ͋͑ͣ
ͩΊͰͨ͠ ר͖ى͜ΔΤϥʔ☠☠☠
ೖྗඞਢͷڥม͕͋ΔΒ͍͠ FOWNJTTJOHSFRVJSFELFZ3&26&45@.&5)0% 3BDL-JOU-JOU&SSPS
rack/lib/rack/lint.rb 3BDL-JOUΫϥεΛ֬ೝ
rack/lib/rack/lint.rb 3BDL-JOUΫϥεΛ֬ೝ ඞཁͳڥมʹ͍ͭͯղઆͯ͘͠Ε͍ͯΔʂ ʜ
⚡1"5)@*/'0ϦΫΤετ63-ͷύε ⚡26&3:@453*/(ΫΤϦจࣈྻ ⚡.&5)0%)551ϝιου ⚡4&37&3@/".&4$3*15@/".&ͱ1"5)@*/'0ͱͷ Έ߹ΘͤͰ63-Λߏங͢Δ ⚡4&37&3@10354$3*15@/".&ͱ1"5)@*/'0ͱͷ Έ߹ΘͤͰ63-Λߏங͢Δ 1&1Ͱఆٛ͞Εͨڥม 1&11ZUIPO8FC4FSWFS(BUFXBZ*OUFSGBDFW IUUQTXXXQZUIPOPSHEFWQFQTQFQ
⚡SBDLWFSTJPO3BDLͷόʔδϣϯ ྻ ⚡SBDLJOQVUೖྗετϦʔϜ *0ϥΠΫͳΦϒδΣΫτ ⚡SBDLFSSPSTΤϥʔετϦʔϜ QVUTXSJUFqVTIΛݺΔΦϒδΣΫτ
⚡SBDLNVMUJQSPDFTTΞϓϦέʔγϣϯ͕ෳͷϓϩηεʹΑͬͯ ಉ࣌ʹݺͼग़͞ΕΔ͔Ͳ͏͔ ⚡SBDLNVMUJUISFBEΞϓϦέʔγϣϯ͕ ಉ͡ϓϩηεͷෳͷεϨουʹΑͬͯ ಉ࣌ʹݺͼग़͞ΕΔ͔Ͳ͏͔ ⚡SBDLSVO@PODFΞϓϦέʔγϣϯ͕ͦͷϓϩηεͷ࣮ߦதʹ Ұ͚ͩݺͼग़͞ΕΔ͔Ͳ͏͔ $(*ϕʔεͷαʔόʔͰͷΈUSVFʹͳΔ ⚡SBDLVSM@TDIFNF63*εΩʔϜ IUUQPSIUUQT 3BDLڥݻ༗ͷڥม
18 def env 19 { 20 ‘PATH_INFO’ => @path ||
‘/’, 21 ‘QUERY_STRING’ => @query || ‘’, 22 ‘METHOD’ => @method || ‘GET’, 23 ‘SERVER_NAME’ => ‘simple_rack_compatible_server’, 24 ‘SERVER_PORT’ => @port.to_s, 25 ‘rack.version’ => Rack::VERSION, 26 ‘rack.input’ => StringIO.new(@input || ‘’).set_encoding(‘ASCII_8BIT’), 27 ‘rack.errors’ => $stderr, 28 ‘rack.multiprocess’ => false, 29 ‘rack.multithread’ => false, 30 ‘rack.run_once’ => false, 31 ‘rack.url_scheme’ => @scheme&.downcase&.slice(/http[a-z]*/) || ‘http’ 32 } 33 end simple_rack_compatible_server.rb 3BDL-JOUΛࢀߟʹڥมΛઃఆ ϦΫΤετ͔Βಈతʹੜͨ͠ڥม PSσϑΥϧτ
35 def start 36 server = TCPServer.new(@host, @port) 37 38
loop do 39 client = server.accept 40 41 request = client.readpartial(2048).split(“\r\n”) 42 @method, path, @scheme = request.first.split 43 @path, @query = path.split(‘?’) 44 @input = request.index(‘’) ? request[request.index(‘’) + 1] : ‘’ 45 46 puts “Received request message: #{@method} #{@path} #{@scheme}” 47 48 @status, @header, @body = @app.call(env) 49 50 client.puts <<~MESSAGE 51 # … simple_rack_compatible_server.rb ϦΫΤετϝοηʔδ͔ΒڥมΛੜ ڥมΛੜ͢ΔίʔυΛՃ
35 def start 36 server = TCPServer.new(@host, @port) 37 38
loop do 39 client = server.accept 40 41 request = client.readpartial(2048).split(“\r\n”) 42 @method, path, @scheme = request.first.split 43 44 45 46 47 48 49 50 51 simple_rack_compatible_server.rb !NFUIPE)551ϝιου ˏTDIFNB63*εΩʔϜ ϦΫΤετϝοηʔδ͔ΒڥมΛੜ
35 def start 36 server = TCPServer.new(@host, @port) 37 38
loop do 39 client = server.accept 40 41 request = client.readpartial(2048).split(“\r\n”) 42 @method, path, @scheme = request.first.split 43 @path, @query = path.split(‘?’) 44 45 46 47 48 49 50 51 simple_rack_compatible_server.rb !QBUIϦΫΤετ63-ͷύε !RVFSZΫΤϦจࣈྻ ϦΫΤετϝοηʔδ͔ΒڥมΛੜ
35 def start 36 server = TCPServer.new(@host, @port) 37 38
loop do 39 client = server.accept 40 41 request = client.readpartial(2048).split(“\r\n”) 42 @method, path, @scheme = request.first.split 43 @path, @query = path.split(‘?’) 44 @input = request.index(‘’) ? request[request.index(‘’) + 1] : ‘’ 45 46 47 48 49 50 51 simple_rack_compatible_server.rb !JOQVUೖྗετϦʔϜ ϦΫΤετϘσΟ ϦΫΤετϝοηʔδ͔ΒڥมΛੜ
35 def start 36 server = TCPServer.new(@host, @port) 37 38
loop do 39 client = server.accept 40 41 request = client.readpartial(2048).split(“\r\n”) 42 @method, path, @scheme = request.first.split 43 @path, @query = path.split(‘?’) 44 @input = request.index(‘’) ? request[request.index(‘’) + 1] : ‘’ 45 46 puts “Received request message: #{@method} #{@path} #{@scheme}” 47 48 49 50 51 simple_rack_compatible_server.rb ͔ͤͬ͘ͳͷͰϩά ग़ྗ ϦΫΤετϝοηʔδ͔ΒڥมΛੜ
SBDLVQTTJNQMF@SBDL@DPNQBUJCMF@TFSWFS ͋ΒͨΊͯ
ಈ͖·ͨ͠ 3FDFJWFESFRVFTUNFTTBHF(&5)551 3BDL-JOU-JOU&SSPSΤϥʔ͕ফ͑ͯ ϩά͕ग़ྗ͞Ε͍ͯΔʂ λʔϛφϧʹͯ
ϒϥβͷݕূπʔϧʹͯ 3BDLΞϓϦέʔγϣϯ͔Βऔಘͨ͠ εςʔλείʔυͱϔομΛ ΫϥΠΞϯτଆʹ͢͜ͱ͕Ͱ͖͍ͯΔʂ ϔομ $POUFOU5ZQFUFYUIUNM εςʔλείʔυ
ϨεϙϯεϘσΟʜ
ϨεϙϯεϘσΟʜ
Կ͔͕͓͔͍͠ ཧ ݱ࣮ SBDLCPEZQSPYZ ϨεϙϯεϘσΟΛಡΈࠐΜͰ %0.͕ੜ͞ΕΔ
35 def start 36 server = TCPServer.new(@host, @port) 37 38
loop do … 47 48 @status, @header, @body = @app.call(env) 49 50 client.puts <<~MESSAGE 51 #{‘HTTP/1.1 200 OK’ if @status.eql? 200}\r\n 52 #{@header.map { |k, v| [k, v].join(’: ’) }.join(“\r\n”)}\r\n 53 \r\n 54 #{@body} 55 MESSAGE 56 end 57 end simple_rack_compatible_server.rb ϨεϙϯεϝοηʔδͲ͏ͳ͍ͬͯΔʁ ཧͷϨεϙϯεϘσΟ [“<div><h1>Hello.</h1><p>This app is …</p></div>”] 3BDLΞϓϦέʔγϣϯΛ࣮ߦͯ͠ฦΓΛऔಘ <εςʔλείʔυ \ϔομ^ <ϘσΟ>>
!CPEZͷதͲ͏ͳ͍ͬͯΔʁ JSC 4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFSYʜ QQ!CPEZ 3BDL#PEZ1SPYZYʜ !CMPDL 1SPDYʜ!ʜSBDLMJCSBDLDPNNPO@MPHHFSSC !CPEZ 3BDL-JOUYʜ
!BQQ 3BDL5FNQpMF3FBQFSYʜ!BQQ"QQYʜ !CPEZ 3BDL#PEZ1SPYZYʜ !CMPDL 1SPDYʜ!ʜSBDLMJCSBDLUFNQpMF@SFBQFSSC !CPEZ <lEJWI)FMMPIQ5IJTBQQJTSVOOJOHPOʜQEJWz> !DMPTFEGBMTF
!CPEZͷதͲ͏ͳ͍ͬͯΔʁ JSC 4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFSYʜ QQ!CPEZ 3BDL#PEZ1SPYZYʜ !CMPDL 1SPDYʜ!ʜSBDLMJCSBDLDPNNPO@MPHHFSSC !CPEZ 3BDL-JOUYʜ
!BQQ 3BDL5FNQpMF3FBQFSYʜ!BQQ"QQYʜ !CPEZ 3BDL#PEZ1SPYZYʜ !CMPDL 1SPDYʜ!ʜSBDLMJCSBDLUFNQpMF@SFBQFSSC !CPEZ <lEJWI)FMMPIQ5IJTBQQJTSVOOJOHʜQEJWz> !DMPTFEGBMTF 3BDL#PEZ1SPYZͷΠϯελϯεʂ
JSC 4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFSYʜ QQ!CPEZ 3BDL#PEZ1SPYZYʜ !CMPDL 1SPDYʜ!ʜSBDLMJCSBDLDPNNPO@MPHHFSSC !CPEZ 3BDL-JOUYʜ !BQQ
3BDL5FNQpMF3FBQFSYʜ!BQQ"QQYʜ !CPEZ 3BDL#PEZ1SPYZYʜ !CMPDL 1SPDYʜ!ʜSBDLMJCSBDLUFNQpMF@SFBQFSSC !CPEZ <lEJWI)FMMPIQ5IJTBQQJTʜQEJWz> !DMPTFEGBMTF ͋Δ औΓग़͠ํ͕Θ͔Βͳ͍ʜ !CPEZͷதͲ͏ͳ͍ͬͯΔʁ
!CPEZΛDBMMͯ͠Έ·ͨ͠ JSC 4JNQMF3BDL$PNQBUJCMF4FSWFSTFSWʜ QQ!CPEZDBMM FOW < \$POUFOU5ZQFUFYUIUNM^
3BDL-JOUYʜ !BQQ 3BDL5FNQpMF3FBQFSYʜ!BQQ"QQYʜ !CPEZ 3BDL#PEZ1SPYZYʜ !CMPDL 1SPDYʜ!ʜSBDLMJCSBDLUFNQpMF@SFBQFSSC !CPEZ <EJWI)FMMPIQ5IJTBQQJTʜQEJW> !DMPTFEGBMTF !DPOUFOU@MFOHUIOJM !IFBE@SFRVFTUGBMTF>
!CPEZΛDBMMͯ͠Έ·ͨ͠ JSC 4JNQMF3BDL$PNQBUJCMF4FSWFSTFSWFʜ QQ!CPEZDBMM FOW < \$POUFOU5ZQFUFYUIUNM^
3BDL-JOUYʜ !BQQ 3BDL5FNQpMF3FBQFSYʜ!BQQ"QQYʜ !CPEZ 3BDL#PEZ1SPYZYʜ !CMPDL 1SPDYʜ!ʜSBDLMJCSBDLUFNQpMF@SFBQFSSC !CPEZ <lEJWI)FMMPIQ5IJTBQQJTʜQEJWz> !DMPTFEGBMTF !DPOUFOU@MFOHUIOJM !IFBE@SFRVFTUGBMTF> ԕ͍ʜ ϨεϙϯεϘσΟͦͷͷ͕ औಘͰ͖ΔΑ͏ʹͳΔ·Ͱ ԆʑDBMM͠ଓ͚Δ͔͠ͳ͍ʜʁʁ ϘσΟ 3BDL-JOUͷΠϯελϯε
ߴڮ͞Μ͔Βͷώϯτ DBMMϝιουͷฦ͢ཁૉྻͷͭCPEZͰɺ CPEZFBDIϝιουͱ͔UP@QBUIϝιουͱ͔Λୟ͚Δ ΦϒδΣΫτͰ͔͠ͳ͘
ʜFBDIϝιουʁ ߴڮ͞Μ͔Βͷώϯτ DBMMϝιουͷฦ͢ཁૉྻͷͭCPEZͰɺ CPEZFBDIϝιουͱ͔UP@QBUIϝιουͱ͔Λୟ͚Δ ΦϒδΣΫτͰ͔͠ͳ͘
3BDL#PCZ1SPYZFBDI 3BDL#PCZ1SPYZFBDIϝιουΛ࣋ͭ ͑ΔͷͰʁ
1 require ‘socket’ 2 3 module SimpleRackCompatibleServer 4 class Server
69 def body 70 res_body = [] 71 @body.each { |body| res_body << body } 72 res_body.join(“\n”) 73 end 74 end 75 end simple_rack_compatible_server.rb FBDIΛͬͯϨεϙϯεϘσΟΛऔΓग़͢ … !CPEZʹFBDIΛݺͼྻͱͯ͠ೖ͢͠ ࠷ޙʹจࣈྻʹ͢
35 def start 48 @status, @header, @body = @app.call(env) 49
50 client.puts <<~MESSAGE 51 #{‘HTTP/1.1 200 OK’ if @status.eql? 200}\r\n 52 #{@header.map { |k, v| [k, v].join(’: ’) }.join(“\r\n”)}\r\n 53 \r\n 54 #{body} 55 MESSAGE 56 end 57 end simple_rack_compatible_server.rb ϨεϙϯεϘσΟΛݺͼग़͢ … CPEZϝιουΛݺͿ
SBDLVQTTJNQMF@SBDL@DPNQBUJCMF@TFSWFS ͋ΒͨΊͯ
ಈ͖·ͨ͠ ϨεϙϯεϘσΟදࣔͰ͖·ͨ͠
εςʔλείʔυɺϔομɺϘσΟͷશͯΛ ΫϥΠΞϯτଆʹग़ྗͰ͖·ͨ͠ʂ ಈ͖·ͨ͠ εςʔλε)5510, ϔομ$POUFOU5ZQFUFYUIUNM ϘσΟEJW I)FMMPI Q5IJTBQQJTʜQ EJW
࠷ऴతʹ͜͏ͳΓ·ͨ͠⚡
1 require ‘socket’ 2 3 module SimpleRackCompatibleServer 4 class Server
5 def initialize(*args) 6 @host, @port, @app = args 7 @method = nil 8 @path = nil 9 @scheme = nil 10 @query = nil 11 @input = nil 12 @status = nil 13 @header = nil 14 @body = nil 15 end simple_rack_compatible_server.rb 4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFSJOJUJBMJ[F ⚡TPDLFUϥΠϒϥϦΛSFRVJSF ⚡ඞཁͳΠϯελϯεมΛॳظԽ
18 def env 19 { 20 ‘PATH_INFO’ => @path ||
‘/’, 21 ‘QUERY_STRING’ => @query || ‘’, 22 ‘METHOD’ => @method || ‘GET’, 23 ‘SERVER_NAME’ => ‘simple_rack_campatible_server’, 24 ‘SERVER_PORT’ => @port.to_s, 25 ‘rack.version’ => Rack::VERSION, 26 ‘rack.input’ => StringIO.new(@input || ‘’).set_encoding(‘ASCII_8BIT’), 27 ‘rack.errors’ => $stderr, 28 ‘rack.multiprocess’ => false, 29 ‘rack.multithread’ => false, 30 ‘rack.run_once’ => false, 31 ‘rack.url_scheme’ => @scheme&.downcase&.slice(/http[a-z]*/) || ‘http’ 32 } 33 end simple_rack_compatible_server.rb 4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFSFOW ⚡3BDLΞϓϦέʔγϣϯͷ࣮ߦʹඞཁͳڥมΛ༻ҙ
35 def start 36 server = TCPServer.new(@host, @port) 37 38
puts <<~MESSAGE 39 #{@app} is running on #{@host}: #{@port} 40 => Use Ctrl-C to stop 41 MESSAGE 42 43 loop do 44 client = server.accept 60 end 61 end simple_rack_compatible_server.rb … 4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFSTUBSU ⚡ϧʔϓॲཧΛ։࢝͢Δ ⚡ΫϥΠΞϯτ͔ΒͷଓཁٻΛड͚͚Δ ⚡αʔόʔଓΛ։࢝͢Δ ⚡։࢝ϝοηʔδΛग़ྗ͢Δ
46 begin 47 request = client.readpartial(2048).split(“\r\n”) 48 @method, path, @scheme
= request.first.split 49 @path, @query = path.split(‘?’) 50 @input = request.index(‘’) ? request[request.index(‘’) + 1] : ‘’ 51 52 puts “Received request message: #{@method} #{@path} #{@schema}” 53 54 55 56 57 58 59 end simple_rack_compatible_server.rb 4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFSTUBSU ⚡ϦΫΤετϝοηʔδΛಡΈࠐΉ ⚡3BDLΞϓϦέʔγϣϯͷ࣮ߦʹඞཁͳڥมΛੜ͢Δ ⚡αʔόʔʹϩάΛग़ྗ͢Δ
46 begin 47 48 49 50 51 52 53 54
@status, @header, @body = @app.call(env) 55 56 client.puts [status, header, ‘’, body].join(“\r\n”) 57 ensure 58 client.close 59 end simple_rack_compatible_server.rb 4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFSTUBSU ⚡3BDLΞϓϦέʔγϣϯΛ࣮ߦ͠ɺฦΓΛऔಘ͢Δ ⚡ฦΓ͔ΒϨεϙϯεϝοηʔδΛੜ͠ɺग़ྗ͢Δ ⚡ιέοτΛด͡Δ
46 begin 47 48 49 50 51 52 53 54
55 56 client.puts [status, header, ‘’, body].join(“\r\n”) 57 ensure 58 client.close 59 end simple_rack_compatible_server.rb 4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFSTUBSU 67 def status 68 case @status 69 when 200 70 “#{@schema} 200 OK” 82 def header 83 @header.map { |k, v| [k, v].join(’: ’) }.join(“\r\n”) 84 end 86 def body 87 res_body = [] 88 @body.each { |body| res_body << body } 89 res_body.join(“\n”) 90 end
͓ർΕ༷Ͱͨ͠✨
ը૾ɿIUUQTUXJUUFSDPNUFOEFSMPWF ग़యɿIUUQTTQFBLFSEFDLDPNUFOEFSMPWFHBPEVOBLPEP "BSPO͞Μɹɹɹɹ
ײ 3BDLΛͬͯ 3BDLDPNQBUJCMFͳ 8FCαʔόʔΛ࡞Δͷ ָ
⚡Ұ෦Ծ࣮ͷ··ͩ͠ɺ ·ͩ·ͩߟ͑Δ͖͜ͱͨ͘͞Μ͋Δ ೖྗʁฒྻԽʁύϑΥʔϚϯεʁFUD ⚡ͬͱ3BDLͷ͜ͱΛΓ͍ͨʂ ⚡օ͞Μ͔Βͷٕज़తࢦఠΛ͓͍ͪͯ͠·͢ IUUQTHJUIVCDPNTIJPJNNTJNQMF@SBDL@DPNQBUJCMF@TFSWFS ͱ͍͑
3BDLָɹ
3BDLָ͍͠ʂ
͓ΘΓʹ⚡⚡⚡
ࣗݾհ࠶ͼ
ҰલʹԿ͕͔͋ͬͨ օ͞Μ͍֮͑ͯ·͔͢ʜʁ
݄ େߐށ3VCZձٞ ը૾ɿIUUQTSFHJPOBMSVCZLBJHJPSHPFEP
લճͷେߐށ3VCZձٞͷલʹॳࢀՃ "TBLVTBSCͷFTBʹΑΔͱ ͦͯͦ͠ͷͰେߐށ3VCZձٞʹ ਃ͠ࠐΈΛͨ͠هԱ͕ʜ ୈճ ը૾ɿIUUQTBTBLVTBSCFTBJPQPTUT
લճͷେߐށ3VCZձٞ ը૾ɿIUUQTSFHJPOBMSVCZLBJHJPSHPFEP
લճͷେߐށ3VCZձٞ ָ͔ͬͨ͘͢͝͠ ը૾ɿIUUQTSFHJPOBMSVCZLBJHJPSHPFEP
લճͷେߐށ3VCZձٞ جௐߨԋ +POBO͞Μʮ)PXUPCFσΧʯ ը૾ɿIUUQTSFHJPOBMSVCZLBJHJPSHPFEP
લճͷେߐށ3VCZձٞ جௐߨԋ +POBO͞Μʮ)PXUPCFσΧʯ Have your heroes ը૾ɿIUUQTSFHJPOBMSVCZLBJHJPSHPFEP
Ұલͷࣗʹͱͬͯ "TBLVTBSCͷਓʑ ʮώʔϩʔʯ
Ұܦͬͨࠓ ʮಉ͡ίϛϡχςΟͷਓʑʯ Ͱ͋Δ
3VCZ ͳͲͳͲ ͷ͓Λͨ͠Γ✨ ίʔυΛॻ͍ͨΓ+ ͓͍͍͠ͷΛ͍ͨΓ Θͨ͠ʹͱͬͯͷ"TBLVTBSCɺ 3VCZJTU͕ू·ͬͯ ͍ͭΘ͍Θ͍͍ͯ͠Δॴ
"TBLVTBSCָ͍͠ʂ
4QFDJBM5IBOLT ܟশུ ✨ JOTQJSFEGSPN !FTUIFS !UFOEFSMPWFUIF3BDLUFBN !JHBJHB!VE[VSB !UBLBIBTIJN!PLVSBNBTBGVNJ !UIFKPOBOTIPX"TBLVTBSC'VLVPLBSC
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠⚡⚡⚡