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
実録 Let's build a simple Rack compatible server
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Misaki Shioi(塩井美咲/しおい)
February 11, 2020
Programming
2.9k
6
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
実録 Let's build a simple Rack compatible server
Misaki Shioi(塩井美咲/しおい)
February 11, 2020
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
作って学ぶ、 JSX (TSX) ランタイムの基本
syumai
7
1.6k
技術記事、 専門家としてのプログラマ、 言語化
mizchi
11
4.4k
Composerを使ったサプライチェーン攻撃の様子を眺めてみる #phpstudy
o0h
PRO
2
240
Oxcを導入して開発体験が向上した話
yug1224
4
310
The ROI of Quarkus for Spring Boot Applications
hollycummins
0
110
Semantic Version 単位で戦略を柔軟に変えて、パッケージアップデートを自動化する
daitasu
0
220
TypeScript+Orvalで実現する型安全かつ堅牢でスケーラブルなマルチチャネル通知基盤 / TSKaigi Night talks ~after conference~
d0riven
0
330
3Dシーンの圧縮
fadis
1
750
Webフレームワークの ベンチマークについて
yusukebe
0
160
Skillsは効率化、Agentsは"自分の拡張"——Builder時代のエージェント編成(CC Night 2026)
wemra
1
120
Spring Security 実践 ─ GraphQL APIで実務に役立つ 認証・認可 を学ぶ
wagyu
0
220
TSKaigi Night Talks 2026_TypeScriptでサプライチェーンの整合性を型に閉じ込める
geekplus_tech
0
340
Featured
See All Featured
Navigating Weather and Climate Data
rabernat
0
220
How GitHub (no longer) Works
holman
316
150k
Rebuilding a faster, lazier Slack
samanthasiow
85
9.5k
Testing 201, or: Great Expectations
jmmastey
46
8.2k
Visualization
eitanlees
152
17k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.2k
Product Roadmaps are Hard
iamctodd
PRO
55
12k
SEO for Brand Visibility & Recognition
aleyda
0
4.6k
A Modern Web Designer's Workflow
chriscoyier
698
190k
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
250
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
720
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
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
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠⚡⚡⚡