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
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
[English ver]実録 Let's build a simple Rack compa...
Search
Misaki Shioi(塩井美咲/しおい)
February 11, 2020
Programming
310
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
[English ver]実録 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
3.6k
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
520
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
たのしいRubyの構文解析ツアー
coe401_
7
4.8k
Other Decks in Programming
See All in Programming
【DroidKaigi 2026】「アクセシビリティを利用するとき、 アクセシビリティもまたこちらを利用している」 〜マルウェアによる攻撃と防衛について〜
halunoyo
0
420
Seeing Through Serverless: Observability for AWS Lambda with ADOT and CloudWatch Application Signals
seike460
PRO
1
130
AWS Step Functions 大規模並列の壁を越える / jaws-sonic-2026-niigata-step-functions
kasacchiful
PRO
1
420
変化を抱擁するドキュメントの作り方 - ビジネスルール駆動開発がもたらす、コードとの新しい関係
ioki
2
120
Oxlintはいいぞ(続)
yug1224
1
560
Press start. Python's next generation.
willingc
PRO
3
320
まだ間に合う!今年の夏こそSchemeのマクロ展開器を完全理解!
omasanori
0
640
kubernetes コンポーネント開発入門 / 新卒N年目の勉強会&交流会!〜〇〇への誘い〜 #n_study
mazrean
0
180
ハーネス設計入門 〜プロンプト、コンテキストの次〜
kinopeee
55
36k
モバイル交通系ICへのチャージ実例から考える、クロスプラットフォーム開発におけるiOS実機テスト設計とCI運用
yusuga
1
130
Foundry Localでエージェント開発
seosoft
0
150
Webプラットフォームで議論されているセキュリティ課題 / Security issues being discussed on Web Platforms
petamoriken
0
300
Featured
See All Featured
KATA
mclloyd
PRO
35
15k
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
1
2.8k
Product Roadmaps are Hard
iamctodd
55
13k
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
380
Mind Mapping
helmedeiros
1
350
Fireside Chat
paigeccino
42
4k
Six Lessons from altMBA
skipperchong
29
4.5k
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
540
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
280
How to build a perfect <img>
jonoalderson
1
6k
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
3
1.2k
Color Theory Basics | Prateek | Gurzu
gurzu
0
460
Transcript
.JTBLJ4IJPJ!DPF@ 'FC 0FEP3VCZ,BJHJ ࣮ -FU`TCVJMEBTJNQMF 3BDLDPNQBUJCMFTFSWFS⚡⚡⚡
"CPVUNF .JTBLJ4IJPJ ͓͍͠ !DPF@ ⚡8FCQSPHSBNNFS ⚡#FMPOHTUP"TBLVTBSC 5BNBSC 'VLVPLBSC ⚡*UTCFFOZFBSBOEBIBMG
TJODF*KPJOFE"TBLVTBSCNFFUVQGPSUIFpSTUUJNF ⚡#VJMUBXFCTFSWFSSFDFOUMZ
.JTBLJ4IJPJ ͓͍͠ !DPF@ ⚡8FCQSPHSBNNFS ⚡#FMPOHTUP"TBLVTBSC 5BNBSC 'VLVPLBSC ⚡*UTCFFOZFBSBOEBIBMG TJODF*KPJOFE"TBLVTBSCNFFUVQGPSUIFpSTUUJNF
⚡#VJMUBXFCTFSWFSSFDFOUMZ "CPVUNF ‐5PEBZ`TUIFNF
BU 3VCZ$POG/BTIWJMMF /PWFNCFS
l-FU`TCVJMEBTJNQMF)551TFSWFSz XIJDIJTBWFSZJOUFSFTUJOHUBML CZ&45)&30-"56/%&!FTUIFS ग़యɿIUUQTOPUJTUFTUIFSD(V(+MFUTCVJMEBTJNQMFIUUQTFSWFSXJUISVCZ
ʜJTJOUSPEVDFECZ!JHBJHB`TUXFFU ग़యɿIUUQTUXJUUFSDPNJHBJHBTUBUVT T
ʜJTJOUSPEVDFECZ!VE[VSB GSPN'VLVPLBSC CZUXFFU UPNF ग़యɿIUUQTUXJUUFSDPNVE[VSBTUBUVT T ˞NF
4P XJUIUIFSFGFSFODFUPUIFTMJEF *CVJMUBTJNQMF)551TFSWFS
ʜBOEIFSFJUJT 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
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 $SFBUFBOFXTFSWFSTPDLFU "DDFQUBOJODPNJOHDPOOFDUJPO (FUBSFRVFTUNFTTBHF %JTQMBZSFRVFTUNFTTBHFUPTFSWFSTJEF 1SPWJTJPOBMSFTQPOTFNFTTBHF %JTQMBZSFTQPOTFNFTTBHFUPDMJFOUTJEF ʜBOEIFSFJUJT
DVSMMPDBMIPTU )PTU1PSUXIJDIBSFPQFOFE
*UXPSLT POTFSWFSTJEF PODMJFOUTJEF 3FRVFTUNFTTBHF JTEJTQMBZFE 3FTQPOTFCPEZ JTEJTQMBZFE
#VU
5IJTTFSWFSDBO`USVOBQQMJDBUJPO⚠ 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 5IFSF`TOPBQQ 4BNFNFTTBHFJTEJTQMBZFE FBDIUJNFZPVBDDFTTFE
*EMJLFUPNBLFUIJTTFSWFS 3BDLDPNQBUJCMF
4P *USJFEUPCVJME BTJNQMF3BDLDPNQBUJCMFTFSWFS XIJDIJTOBNFE 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 )FSFJTB3BDLBQQGPSWFSJpDBUJPO 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 4UBUVT)5510, )FBEFS$POUFOU5ZQFUFYUIUNM #PEZEJW I)FMMPI Q5IJTBQQJTʜQ EJW app/sample.ru )FSFJTB3BDLBQQGPSWFSJpDBUJPO 8IFOZPVSVOʜ
)PX3BDLBQQMJDBUJPOTUBSUT 6TFSFYFDVUFTSBDLVQ )BOEMFSJTDBMMFE 4FSWFSJTSFHJTUFSFEUP)BOEMFS 4FSWFSTUBSUTUPSVO )BOEMFSTUBSUT4FSWFS 5IFTFSWFS DPOOFDUFEUP3BDL 4FSWFSSVOT3BDLBQQ 4UBSU
4FSWFSDBMMT3BDLBQQ
JOUIFTFSWFS JO3BDL)BOEMFSNPEVMF JOUIFTFSWFS JO3BDL 6TFSFYFDVUFTSBDLVQ )BOEMFSJTDBMMFE 4FSWFSJTSFHJTUFSFEUP)BOEMFS 4FSWFSTUBSUTUPSVO )BOEMFSTUBSUT4FSWFS 4FSWFSDBMMT3BDLBQQ
)PX3BDLBQQMJDBUJPOTUBSUT
3FRVJSFNFOUPG3BDLDPNQBUJCMFTFSWFS *UIPVHIUBCPVUUIFSFRVJSFNFOUTGPSUIFTFSWFS CBTFEPOIPX3BDLBQQTUBSUT ᶃ)BOEMFS 3BDL)BOEMFS4JNQMF3BDL$PNQBUJCMF4FSWFS ⚡5PSFHJTUFSUIFTFSWFSUP3BDL)BOEMFSNPEVMF ⚡5PTUBSUUIFTFSWFS ᶄ4FSWFS
4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFS ⚡5PSFDFJWFBSFRVFTUNFTTBHF ⚡5PDBMM3BDLBQQMJDBUJPO ⚡5PSFUVSOBSFTQPOTFNFTTBHF
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 *NQMFNFOUBUJPOPG)BOEMFS SFGTUIJO SFRVJSF3BDL)BOEMFS
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 5PSFHJTUFSUIFTFSWFSUP3BDL)BOEMFSNPEVMF ࢀߟɿIUUQTHJUIVCDPNNBDPVSOPZFSUIJO *NQMFNFOUBUJPOPG)BOEMFS SFGTUIJO
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 5IFNFUIPEUPTUBSUUIFTFSWFS *NQMFNFOUBUJPOPG)BOEMFS SFGTUIJO
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 4FUUIFIPTUQPSUCZFOWJSPONFOU ˞DPOOFDUUPMPDBMIPTUCZEFGBVMU ࢀߟɿIUUQTHJUIVCDPNNBDPVSOPZFSUIJO *NQMFNFOUBUJPOPG)BOEMFS SFGTUIJO
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 "SHTUPJOJUJBMJ[FUIFTFSWFS ⚡)PTU ⚡1PSU ⚡3BDLBQQMJDBUJPO ࢀߟɿIUUQTHJUIVCDPNNBDPVSOPZFSUIJO *NQMFNFOUBUJPOPG)BOEMFS SFGTUIJO
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 *OTUBOUJBUF OFX TUBSU TUBSU UIFTFSWFS 4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFS ࢀߟɿIUUQTHJUIVCDPNNBDPVSOPZFSUIJO *NQMFNFOUBUJPOPG)BOEMFS SFGTUIJO
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 *NQMFNFOUBUJPOPGUIFTFSWFS0WFSBMM ʜ .PWFPSJHJOBMJNQMFNFOUBUJPOPGUIFTFSWFS UP4JNQMF3BDL$PNQBUJCMF4FSWFS4FSWFSDMBTT
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 27 end 28 end 29 end simple_rack_compatible_server.rb ʜ *OTUBOUJBUFXJUIBSHTGSPN)BOEMFS ⚡IPTU ⚡QPSU ⚡3BDLBQQMJDBUJPO "EEUIFGPMMPXJOHDIBOHFT UPUIFPSJHJOBM)551TFSWFS 4FFUIFOFYUTMJEFGPSNPSFEFUBJMTʜ *NQMFNFOUBUJPOPGUIFTFSWFS0WFSBMM
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 DIBOHFTᶄ $BMMUIF3BDLBQQMJDBUJPO BOEHFUUIFSFUVSOWBMVFT DIBOHFTᶅ (FOFSBUFBSFTQPOTFNFTTBHF GSPNUIFSFUVSOWBMVFT *NQMFNFOUBUJPOPGUIFTFSWFSTUBSU DIBOHFTᶃ 4FUUIFIPTUQPSU GSPN)BOEMFS
#VU
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 8IBUTIPVME*EPʜ 8IBUBSHTEPFTUIFDBMMNFUIPEOFFE ⚠ 4PNFFOWJSPONFOUWBSJBCMFT IBWFUPCFIFSF
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 1SPWJTJPOBMMZ "OFNQUZ)BTIPCKFDU
SBDLVQTTJNQMF@SBDL@DPNQBUJCMF@TFSWFS "OZXBZʜ
(PUMPUTPGFSSPST ☠☠☠
*UTFFNTUIFSF`SFSFRVJSFEWBSJBCMFT FOWNJTTJOHSFRVJSFELFZ3&26&45@.&5)0% 3BDL-JOU-JOU&SSPS
rack/lib/rack/lint.rb 4FF3BDL-JOUDMBTT
rack/lib/rack/lint.rb &YQMBOBUJPOTBCPVUSFRVJSFEWBSJBCMFT ʜ 4FF3BDL-JOUDMBTT
⚡1"5)@*/'01BUIPGSFRVFTUFE63- ⚡26&3:@453*/(2VFSZTUSJOH ⚡.&5)0%)551NFUIPE ⚡4&37&3@/".&5PCVJMEB63-XJUI 4$3*15@/".&1"5)@*/'0 ⚡4&37&3@10355PCVJMEB63-XJUI 4$3*15@/".&1"5)@*/'0 7BSJBCMFTEFpOFEJO1&1 1&11ZUIPO8FC4FSWFS(BUFXBZ*OUFSGBDFW IUUQTXXXQZUIPOPSHEFWQFQTQFQ
⚡SBDLWFSTJPO3BDLWFSTJPO BO"SSBZPCKFDU ⚡SBDLJOQVU*OQVUTUSFBN BO*0MJLFPCKFDU ⚡SBDLFSSPST&SSPSTUSFBN BOPCKFDUSFTQPOTFUPQVUTXSJUFqVTI
⚡SBDLNVMUJQSPDFTT8IFUIFSUIFBQQMJDBUJPOJTJOWPLFE CZNVMUJQMFQSPDFTTFTTJNVMUBOFPVTMZ ⚡SBDLNVMUJUISFBE8IFUIFSUIFBQQMJDBUJPOJTJOWPLFE CZNVMUJQMFUISFBETJOUIFTBNFQSPDFTT BUUIFTBNFUJNF ⚡SBDLSVO@PODF'PSBTFSWFSCBTFEPO$(* ⚡SBDLVSM@TDIFNF63*TDIFNF IUUQPSIUUQT 3BDLTQFDJpDWBSJBCMFT
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 %FpOFFOWNFUIPESFGTUP3BDL-JOU %ZOBNJDBMMZHFOFSBUFEWBSJBCMFTGSPNUIFSFRVFTU PSEFGBVMUWBMVF
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 (FOFSBUFWBSJBCMFTGSPNUIFSFRVFTUNFTTBHF "EEDPEFTUPHFOFSBUFWBSJBCMFT
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)551NFUIPE ˏTDIFNF63*TDIFNF (FOFSBUFWBSJBCMFTGSPNUIFSFRVFTUNFTTBHF
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 !QBUI1BUIPGSFRVFTUFE63- !RVFSZ2VFSZTUSJOH (FOFSBUFWBSJBCMFTGSPNUIFSFRVFTUNFTTBHF
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*OQVUTUSFBN 3FRVFTUCPEZ (FOFSBUFWBSJBCMFTGSPNUIFSFRVFTUNFTTBHF
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 *BMTPBEEFEMPHTUPEJTQMBZ (FOFSBUFWBSJBCMFTGSPNUIFSFRVFTUNFTTBHF
SBDLVQTTJNQMF@SBDL@DPNQBUJCMF@TFSWFS "HBJOʜ
*UXPSLT 3FDFJWFESFRVFTUNFTTBHF(&5)551 3BDL-JOU-JOU&SSPSFSSPSDMFBSFE BOEMPHTBSFEJTQMBZFE BUNZUFSNJOBM
BU%FW5PPMTPGNZCSPXTFS 4UBUVTDPEFBOE)FBEFSSFUVSOFEGSPN3BDLBQQ BSFTVDDFTTGVMMZPVUQVUUPUIFDMJFOUTJEF )FBEFS $POUFOU5ZQFUFYUIUNM 4UBUVTDPEF
"OEUIFSFTQPOTFCPEZJTʜ
"OEUIFSFTQPOTFCPEZJTʜ
4PNFUIJOH`TXSPOH 0, /( SBDLCPEZQSPYZ %0.TIPVMECFHFOFSBUFE GSPNSFTQPOTFCPEZ
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 )FSFUIFSFTQPOTFNFTTBHFJT 8IBU*XBTFYQFDUJOHJT [“<div><h1>Hello.</h1><p>This app is …</p></div>”] $BMMUIF3BDLBQQHFUUIFSFUVSOWBMVFT <4UBUVT \)FBEFS^ <#PEZ>>
8IBUJTJOTJEF!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
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 *U`TBOJOTUBODFPG3BDL#PEZ1SPYZ 8IBUJTJOTJEF!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)FMMPIQ5IJTBQQJTʜQEJWz> !DMPTFEGBMTF "OEUIJTJTXIBU*XBOU )PXDBO*HFUUIJTʜ 8IBUJTJOTJEF!CPEZ
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> 5SJFEUPDBMM!CPEZ
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> 4PGBSʜ 4IPVME*LFFQDBMMJOHVOUJM UIFSFTQPOTFCPEZJUTFMG JTSFUVSOFE CPEZ BOJOTUBODFPG3BDL-JOU 5SJFEUPDBMM!CPEZ
*HPUBIJOUGSPN5BLBIBTIJTBO 5IFDBMMNFUIPESFUVSOTBO"SSBZPCKFDU XJUIFMFNFOUTBOEUIFUIJSEJTCPEZ "OECPEZJTBOPCKFDUSFTQPOEUP FBDINFUIPE UP@QBUINFUIPEBOETPPOʜ
*HPUBIJOUGSPN5BLBIBTIJTBO 5IFDBMMNFUIPESFUVSOTBO"SSBZPCKFDU XJUIFMFNFOUTBOEUIFUIJSEJTCPEZ "OECPEZJTBOPCKFDUSFTQPOEUP FBDINFUIPE UP@QBUINFUIPEBOETPPOʜ ʜFBDINFUIPE
3BDL#PCZ1SPYZFBDI 3BDL#PCZ1SPYZIBTFBDINFUIPE 5IJTNJHIUCFVTFGVM
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 (FUSFTQPOTFCPEZVTJOHFBDINFUIPE … $BMMFBDINFUIPEUP!CPEZ BOEHFOFSBUFBO"SSBZPCKFDU $POWFSUUPBTUSJOHBUUIFFOE
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 $BMMCPEZNFUIPE … $BMMUIFCPEZNFUIPE
SBDLVQTTJNQMF@SBDL@DPNQBUJCMF@TFSWFS "HBJOBOEBHBJO
BOEʜ
*UXPSLT 3FTQPOTFCPEZJTBMTPEJTQMBZFE
5IFTUBUVTDPEF IFBEFS BOECPEZBSF BMMPVUQVUUPUIFDMJFOUTJEF *UXPSLT 4UBUVT)5510, )FBEFS$POUFOU5ZQFUFYUIUNM #PEZEJW I)FMMPI Q5IJTBQQJTʜQ
EJW
5IJTJTUIFpYFEWFSTJPO⚡
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 ⚡SFRVJSFTPDLFUMJCSBSZ ⚡*OJUJBMJ[FSFRVJSFEJOTUBODFWBSJBCMFT
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 ⚡1SPWJEFUIFWBSJBCMFTSFRVJSFEUPDBMMUIF3BDLBQQ
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 ⚡4UBSUMPPQJOH ⚡"DDFQUBOJODPNJOHDPOOFDUJPO ⚡$SFBUFBOFXTFSWFSTPDLFU ⚡%JTQMBZBTUBSUJOHNFTTBHF
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 ⚡(FUUIFSFRVFTUNFTTBHF ⚡(FOFSBUFWBSJBCMFTGPSDBMMJOH3BDLBQQ ⚡%JTQMBZMPHUPUIFTFSWFSTJEF
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 ⚡$BMMUIF3BDLBQQ(FUUIFSFUVSOFEWBMVFT ⚡(FOFSBUFUIFSFTQPOTFNFTTBHF GSPNUIFSFUVSOFEWBMVF0VUQVUJU ⚡$MPTFUIFTPDLFU
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 "BSPOTBOɹɹɹɹ
.ZJNQSFTTJPOBGUFSJNQMFNFOUBUJPO 3BDLΛͬͯ 3BDLDPNQBUJCMFͳ 8FCαʔόʔΛ࡞Δͷ ָ
"OEBMTPʜ ⚡5IFSFBSFTUJMMBMPUPGUIJOHTUPUIJOLBCPVU BTJUJTTUJMMQSPWJTJPOBMMZJNQMFNFOUFE *OQVU 1BSBMMFMJ[BUJPO 1FSGPSNBODFʜ ⚡*`EMPWFUPLOPXNPSFBOENPSFBCPVU3BDL ⚡*`NXBJUJOHGPSZPVSSFWJFX
IUUQTHJUIVCDPNTIJPJNNTJNQMF@SBDL@DPNQBUJCMF@TFSWFS
3BDLָɹ
3BDLָ͍͠ʂ
͓ΘΓʹ⚡⚡⚡
"CPVUNF BHBJO
%PZPVSFNFNCFSXIBUIBQQFOFE ZFBSBOEBIBMGBHP
4FQ 0FEP3VCZ,BJHJ ը૾ɿIUUQTSFHJPOBMSVCZLBJHJPSHPFEP
.ZpSTUUJNFGPS"TBLVTBSC ʜJTEBZTCFGPSF UIFQSFWJPVT0FEP3VCZ,BJHJ GSPNUIFFTBPG"TBLVTBSC "OE*BQQMJFEGPSJUBUUIBUUJNFSJHIUBXBZ ୈճ ը૾ɿIUUQTBTBLVTBSCFTBJPQPTUT
ը૾ɿIUUQTSFHJPOBMSVCZLBJHJPSHPFEP 5IFQSFWJPVT0FEP3VCZLBJHJ
XBTBHSFBUUJNF ը૾ɿIUUQTSFHJPOBMSVCZLBJHJPSHPFEP 5IFQSFWJPVT0FEP3VCZLBJHJ
,FZOPUF +POBOTBOʮ)PXUPCFσΧʯ ը૾ɿIUUQTSFHJPOBMSVCZLBJHJPSHPFEP 5IFQSFWJPVT0FEP3VCZLBJHJ
,FZOPUF +POBOTBOʮ)PXUPCFσΧʯ Have your heroes ը૾ɿIUUQTSFHJPOBMSVCZLBJHJPSHPFEP 5IFQSFWJPVT0FEP3VCZLBJHJ
'PSNF ZFBSBOEBIBMGBHP 5IFQFPQMFJO"TBLVTBSC XFSFSFBMlIFSPFTz
/PX BOEBIBMGZFBSTMBUFS 5IFZBSFBMTP QFFSTJOUIFTBNFDPNNVOJUZ
5BMLBCPVU3VCZ FUD ✨ 8SJUFDPEFT+ )BWFBEFMJDJPVTEJTIFTFUD 'PSNF "TBLVTBSCJTXIFSF 3VCZJTUTHBUIFS UPNBLFΘ͍Θ͍BOEFOKPZ
"TBLVTBSCָ͍͠ʂ
4QFDJBM5IBOLT✨ JOTQJSFEGSPN !FTUIFS !UFOEFSMPWFUIF3BDLUFBN !JHBJHB!VE[VSB !UBLBIBTIJN!PLVSBNBTBGVNJ !UIFKPOBOTIPX"TBLVTBSC'VLVPLBSC "OEUIBOLZPVGPSMJTUFOJOH⚡⚡⚡