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
実録 Let's build a simple Rack compatible server
Search
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(塩井美咲/しおい)
時うどん〜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
最近”作らせてる” ローカルAIアプリの話
akit37
0
480
複雑なUIコンポーネントとの ⻑い付き合い⽅:波及するバグからテスト戦略を経て、安全な再設計へ
mixplace
0
430
[2026-10-14](C)Re:ゼロから始める異世界生活〜始まりの終わりと終わりの始まり〜
tosite
0
110
Optunaを作ったときにやりたかったこと、その後 (2026/10/16, Optuna Meetup #3)
iwiwi
2
580
Workers Cache を知る
syumai
0
370
JIS keyboard support in Omarchy
lef237
0
140
Domain-Driven Transformation
hschwentner
2
2.3k
ジョジョの世界をXRで再現する
mofurune
0
170
AI主導のプログラミング学習アプリを作ってみた
econanringo
0
180
エージェントを使い続けるためのメタワーク / Meta-work for keeping using the agent
rkaga
1
220
コードで差別化できない時代の ソフトウェアエンジニアリング / Software Engineering in an Era Where Code Doesn’t Differentiate
kishida
2
180
月間100万人のサービス刷新で、 技術選定をHonoに振り切った話
yutobara
8
6.7k
Featured
See All Featured
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.8k
Why Our Code Smells
bkeepers
PRO
340
58k
How GitHub (no longer) Works
holman
316
150k
How to Talk to Developers About Accessibility
jct
2
580
How to build a perfect <img>
jonoalderson
1
6.1k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.9k
The Pragmatic Product Professional
lauravandoore
37
7.5k
Optimizing for Happiness
mojombo
378
71k
Large-scale JavaScript Application Architecture
addyosmani
516
110k
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2.2k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
370
Into the Great Unknown - MozCon
thekraken
41
2.8k
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
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠⚡⚡⚡