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
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
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
280
The Less-Told Story of Socket Timeouts
coe401_
3
3.8k
Making TCPSocket.new "Happy"!
coe401_
1
10k
たのしい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
580
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ネイティブ開発を支える、Shift Down〜 / Can build fast. Next, moving to development where we can verify fast.
rkaga
7
5.1k
TiDB Cloudのカスタムコントローラーによるオートスケール対応
takaidohigasi
0
140
Intent as Code
shoppingjaws
6
1.1k
GemmaをJevのように使ってみる / Use Gemma like Jev
kishida
4
140
MVNOの申込からeSIM開通までをiOSアプリでつなぐ- 本人確認・MNP・通信事業者基盤をまたぐ実装
satotakeshi
0
510
Omarchy Tokyo やると聞いて UMPC 買ってセットアップしてきた
mtsmfm
0
190
カツオ、ご期待ください
suneo3476
0
120
thread_parallel_with_free-threaded_Python_and_NumPy.pdf
riku_sakamoto
0
370
[Rails World 2026] Durable orchestration on Rails: from continuation to workflow
palkan
1
370
ハーネス設計入門 〜 基礎知識の整理から実務へのステップアップ 〜
kinopeee
18
19k
スマート反転とウェブアクセシビリティ
camiha
0
220
AgentCore CLI で進化した AWS での AI エージェントの作り方 : 必要な機能を必要な時に
icoxfog417
PRO
4
390
Featured
See All Featured
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.5k
Visualization
eitanlees
153
17k
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
2
510
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.6k
[RailsConf 2023] Rails as a piece of cake
palkan
59
7k
Building AI with AI
inesmontani
PRO
1
1.3k
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
5
750
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
19k
Building Adaptive Systems
keathley
44
3.2k
Abbi's Birthday
coloredviolet
4
10k
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
320
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
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠⚡⚡⚡