What is Rack Hijacking API

What is Rack
Hijacking API
2016-12-03 at rubyconf.tw
1
Who am I?
• Kiyoshi Nomo
• @kysnm
• Web Application Engineer
• Goodpatch, Inc.
http://goodpatch.com/
https://prottapp.com/
2
Agenda
• The Basics
• About the SPEC
• About the implementation
• Take a quick look at ActionCable
• Conclusion
3
The Basics
4
Who made this API?
5
6
Why it was made?
• Rack didn't have an API that allows
for IO-like streaming.
• for WebSocket
• for HTTP2
https://github.com/rack/rack/pull/
481#issue-9702395
7
Similar implementation
• Golang's Hijacker interface.
• Probably, This API would made
based on this interface.
https://github.com/rack/rack/pull/
481#issue-9702395
8
Support Servers
• puma
• passenger
• thin
• webrick (only partial hijack is
supported.)
• etc…
9
About the SPEC
10
Two mode of Hijaking
• Full hijacking
• Partial hijacking
http://www.rubydoc.info/github/
rack/rack/master/file/
SPEC#Hijacking
11
The timing of Full
hijacking
• Request (before status)
12
The conditions of Full
hijacking
env['rack.hijack?'] == true
env['rack.hijack'].respond_to?(:call) == true
env['rack.hijack'].call must returns the io
env['rack.hijack'].call is assigned the io to
env['rack.hijack_io']
REQUIRED_METHOD =
[:read, :write, :read_nonblock, :write_nonblock, :fl
ush, :close, :close_read, :close_write, :closed?]
REQUIRED_METHOD.all? { |m|
env['rack.hijack_io'].respond_to?(m) } == true
13
Your responsibility of
Full hijacking
• Outputting any HTTP headers, if
applicable.
• Closing the IO object when you no
longer need it.
14
class HijackWrapper
include Assertion
extend Forwardable
REQUIRED_METHODS = [
:read, :write, :read_nonblock, :write_nonblock, :flush, :clos
e,
:close_read, :close_write, :closed?
]
def_delegators :@io, *REQUIRED_METHODS
def initialize(io)
@io = io
REQUIRED_METHODS.each do |meth|
assert("rack.hijack_io must respond to #{meth}")
{ io.respond_to? meth }
end
end
end
https://github.com/rack/rack/blob/
fd1fbab1ec8c7fc49ac805aac47b1f12d4cc5a99/lib/rack/lint.rb#L494-
L511
15
def check_hijack(env)
if env[RACK_IS_HIJACK]
original_hijack = env[RACK_HIJACK]
assert("rack.hijack must respond to call")
{ original_hijack.respond_to?(:call) }
env[RACK_HIJACK] = proc do
io = original_hijack.call
HijackWrapper.new(io)
env[RACK_HIJACK_IO] =
HijackWrapper.new(env[RACK_HIJACK_IO])
io
end
else
assert("rack.hijack? is false, but rack.hijack is
present") { env[RACK_HIJACK].nil? }
assert("rack.hijack? is false, but rack.hijack_io is
present") { env[RACK_HIJACK_IO].nil? }
end
end
https://github.com/rack/rack/blob/
fd1fbab1ec8c7fc49ac805aac47b1f12d4cc5a99/lib/rack/
lint.rb#L513-L562
16
The timing of Partial
hijacking
• Response (after headers)
17
The conditions of
Partial hijacking
• an application may set the special
header rack.hijack to an object
that responds to #call accepting
an argument that conforms to the
rack.hijack_io protocol.
18
Your responsibility of
Partial hijacking
• closing the socket when it’s no
longer needed.
19
def check_hijack_response(headers, env)
headers = Rack::Utils::HeaderHash.new(headers)
if env[RACK_IS_HIJACK] && headers[RACK_HIJACK]
assert('rack.hijack header must respond to #call') {
headers[RACK_HIJACK].respond_to? :call
}
original_hijack = headers[RACK_HIJACK]
headers[RACK_HIJACK] = proc do |io|
original_hijack.call HijackWrapper.new(io)
end
else
assert('rack.hijack header must not be present if server
does not support hijacking') {
headers[RACK_HIJACK].nil?
}
end
end
https://github.com/rack/rack/blob/
fd1fbab1ec8c7fc49ac805aac47b1f12d4cc5a99/lib/rack/
lint.rb#L564-L614
20
About the
implementation
21
Introduce two servers
• rack (webrick)
• puma
22
Webrick (rack)
23
Webrick is
• supported only partial hijack.
24
How to configure?
• See the test/spec_webrick.rb
25
it "support Rack partial hijack" do
io_lambda = lambda{ |io|
5.times do
io.write "Davidrn"
end
io.close
}
@server.mount "/partial", Rack::Handler::WEBrick,
Rack::Lint.new(lambda{ |req|
[
200,
[ [ "rack.hijack", io_lambda ] ],
[""]
]
})
Net::HTTP.start(@host, @port){ |http|
res = http.get("/partial")
res.body.must_equal "DavidrnDavidrnDavidrnDavidrnDavidrn"
}
end
https://github.com/rack/rack/blob/
cabe6b33ca4601aa6acb56317ac1c819cf6dc4bb/test/spec_webrick.rb#L162-L183
26
run lambda { |env|
io_lambda = lambda { |io|
i = 1
5.times do
io.write "Davidrn"
end
io.close
}
[
200,
[ [ 'rack.hijack', io_lambda ] ],
['']
]
}
27
Rack::Handler::Webrick::run
def self.run(app, options={})
environment = ENV['RACK_ENV'] || 'development'
default_host = environment == 'development' ? 'localhost' :
nil
options[:BindAddress] = options.delete(:Host) || default_host
options[:Port] ||= 8080
@server = ::WEBrick::HTTPServer.new(options)
@server.mount "/", Rack::Handler::WEBrick, app
yield @server if block_given?
@server.start
end
https://github.com/rack/rack/blob/
cabe6b33ca4601aa6acb56317ac1c819cf6dc4bb/lib/rack/handler/
webrick.rb#L25-L35
app
[1] pry(#<Rack::Handler::WEBrick>)> app
=> #<Rack::ContentLength:0x007fa0fa17f2a8
@app=
#<Rack::Chunked:0x007fa0fa17f2f8
@app=
#<Rack::CommonLogger:0x007fa0fa17f348
@app=
#<Rack::ShowExceptions:0x007fa0fb208458
@app=
#<Rack::Lint:0x007fa0fb2084a8
@app=
#<Rack::TempfileReaper:0x007fa0fb208520
@app=#<Proc:0x007fa0fb368c08@/tmp/rack_hijack_test/
webrick/config.ru:1 (lambda)>>,
@content_length=nil>>,
@logger=#<IO:<STDERR>>>>>
Webrick::HTTPServer#servic
e
si = servlet.get_instance(self,
*options)
@logger.debug(format("%s is
invoked.", si.class.name))
si.service(req, res)
https://github.com/ruby/ruby/blob/
v2_3_3/lib/webrick/
httpserver.rb#L138-L140
Webrick::HTTPServlet::Abstr
actServlet::get_instance
def self.get_instance(server,
*options)
self.new(server, *options)
end
https://github.com/ruby/ruby/blob/
v2_3_3/lib/webrick/httpservlet/
abstract.rb#L85-L87
Rack::Handler::Webrick#initi
alize
def initialize(server, app)
super server
@app = app
end
https://github.com/rack/rack/blob/
cabe6b33ca4601aa6acb56317ac1c819cf6
dc4bb/lib/rack/handler/
webrick.rb#L52-L55
Rack::Handler::Webrick#serv
ice (Take out the io_lambda)
status, headers, body = @app.call(env)
begin
res.status = status.to_i
io_lambda = nil
headers.each { |k, vs|
if k == RACK_HIJACK
io_lambda = vs
elsif k.downcase == "set-cookie"
res.cookies.concat vs.split("n")
else
# Since WEBrick won't accept repeated headers,
# merge the values per RFC 1945 section 4.2.
res[k] = vs.split("n").join(", ")
end
}
https://github.com/rack/rack/blob/cabe6b33ca4601aa6acb56317ac1c819cf6dc4bb/
lib/rack/handler/webrick.rb#L86-L100
Rack::Handler::Webrick#serv
ice (Calls the io_lambda)
if io_lambda
rd, wr = IO.pipe
res.body = rd
res.chunked = true
io_lambda.call wr
elsif body.respond_to?(:to_path)
res.body = ::File.open(body.to_path, 'rb')
else
body.each { |part|
res.body << part
}
end
ensure
body.close if body.respond_to? :close
end
https://github.com/rack/rack/blob/cabe6b33ca4601aa6acb56317ac1c819cf6dc4bb/
lib/rack/handler/webrick.rb#L86-L100
response
<= Recv data, 35 bytes (0x23)
0000: David
0007: David
000e: David
0015: David
001c: David
== Info: transfer closed with outstanding read data
remaining
== Info: Curl_http_done: called premature == 1
== Info: Closing connection 0
https://gist.github.com/kysnm/
ca5237d4ac96764b9cfe6ac1547710cf
puma
36
puma is
• threaded, cluster enabled server.
• supported two mode of hijacking.
37
Full hijacking example
run lambda { |env|
io = env['rack.hijack'].call
io.puts "HTTP/1.1 200rnr
nBLAH"
[-1, {}, []]
}
https://github.com/puma/puma/blob/
3.6.1/test/hijack.ru
38
Before
Puma::Runner#start_server
=> #0 start_server
<Puma::Runner#start_server()>
#1 [method] start_server
<Puma::Runner#start_server()>
#2 [method] run
<Puma::Single#run()>
#3 [method] run
<Puma::Launcher#run()>
#4 [method] run <Puma::CLI#run()>
39
Puma::Runner#start_serv
er
def start_server
min_t = @options[:min_threads]
max_t = @options[:max_threads]
server = Puma::Server.new app, @launcher.events, @options
server.min_threads = min_t
server.max_threads = max_t
server.inherit_binder @launcher.binder
if @options[:mode] == :tcp
server.tcp_mode!
end
unless development?
server.leak_stack_on_error = false
end
server
end
https://github.com/puma/puma/blob/3.6.1/lib/puma/runner.rb#L140-L160
40
app
[1] pry(#<Puma::Server>)> app
=> #<Puma::Configuration::ConfigMiddleware:0x007ffaf2badc50
@app=#<Proc:0x007ffaf2badfc0@puma/hijack.ru:1 (lambda)>,
@config=
#<Puma::Configuration:0x007ffaf2c75110
@options=
#<Puma::LeveledOptions:0x007ffaf2c74f08
@cur={},
@defaults=
{:min_threads=>0,
:max_threads=>16,
:log_requests=>false,
:debug=>false,
:binds=>["tcp://0.0.0.0:9292"],
:workers=>0,
… snip …
41
Puma::Single#run
begin
server.run.join
rescue Interrupt
# Swallow it
end
https://github.com/puma/puma/blob/
3.6.1/lib/puma/single.rb#L103-L107
42
Puma::Server#handle_ser
vers
if io = sock.accept_nonblock
client = Client.new io, @binder.env(sock)
if remote_addr_value
client.peerip = remote_addr_value
elsif remote_addr_header
client.remote_addr_header = remote_addr_header
end
pool << client
pool.wait_until_not_full unless queue_requests
end
https://github.com/puma/puma/blob/3.6.1/lib/puma/
server.rb#L333-L343
43
Before
Puma::ThreadPool#spawn_thre
ad
=> #0 spawn_thread
<Puma::ThreadPool#spawn_thread()>
#1 [method] spawn_thread
<Puma::ThreadPool#spawn_thread()>
#2 [block] block in <<
<Puma::ThreadPool#<<(work)>
#3 [method] << <Puma::ThreadPool#<<(work)>
#4 [block] block in handle_servers
<Puma::Server#handle_servers()>
#5 [method] handle_servers
<Puma::Server#handle_servers()>
#6 [block] block in run
<Puma::Server#run(background=?)>
44
Puma::Server#run
(block)
process_client client, buffer
https://github.com/puma/puma/blob/
3.6.1/lib/puma/server.rb#L275
45
Puma::Server#process_cl
ient
while true
case handle_request(client, buffer)
when false
return
when :async
close_socket = false
return
when true
return unless @queue_requests
buffer.reset
https://github.com/puma/puma/blob/3.6.1/lib/
puma/server.rb#L275
46
Puma::Server#handle_req
uest (arguments)
def handle_request(req, lines)
env = req.env
client = req.io
normalize_env env, req
env[PUMA_SOCKET] = client
https://github.com/puma/puma/blob/
3.6.1/lib/puma/server.rb#L549-L555
47
Puma::Server#handle_req
uest (HIJACK_P, HIJACK)
env[HIJACK_P] = true
env[HIJACK] = req
https://github.com/puma/puma/blob/
3.6.1/lib/puma/server.rb#L561-L562
48
Puma::Client#call
# For the hijack protocol (allows us
to just put the Client object
# into the env)
def call
@hijacked = true
env[HIJACK_IO] ||= @io
end
https://github.com/puma/puma/blob/
3.6.1/lib/puma/client.rb#L69-L74
49
Puma::Const
HIJACK_P = "rack.hijack?".freeze
HIJACK = "rack.hijack".freeze
HIJACK_IO =
"rack.hijack_io".freeze
https://github.com/puma/puma/blob/
3.6.1/lib/puma/const.rb#L249-L251
50
Puma::Server#handle_req
uest (@app.call)
begin
begin
status, headers, res_body =
@app.call(env)
return :async if req.hijacked
https://github.com/puma/puma/blob/
3.6.1/lib/puma/server.rb#L576-L580
51
Partial hijacking
example
run lambda { |env|
body = lambda { |io| io.puts "BLAH
n"; io.close }
[200, { 'rack.hijack' => body },
[]]
}
https://github.com/puma/puma/blob/
3.6.1/test/hijack2.ru
52
Puma::Server#handle_req
uest (@app.call)
begin
begin
status, headers, res_body =
@app.call(env)
return :async if req.hijacked
https://github.com/puma/puma/blob/
3.6.1/lib/puma/server.rb#L576-L580
53
Puma::Server#handle_req
uest (response_hijack)
response_hijack = nil
headers.each do |k, vs|
case k.downcase
when CONTENT_LENGTH2
content_length = vs
next
when TRANSFER_ENCODING
allow_chunked = false
content_length = nil
when HIJACK
response_hijack = vs
next
end
https://github.com/puma/puma/blob/3.6.1/lib/puma/server.rb#L653-
L666
54
Puma::Server#handle_reque
st (response_hijack.call)
if response_hijack
response_hijack.call client
return :async
end
https://github.com/puma/puma/blob/
3.6.1/lib/puma/server.rb#L705-L708
55
Take a quick look at
ActionCable
56
In
ActionCable::Connection::St
ream
57
ActionCable::Connection::
Stream#hijack_rack_socket
def hijack_rack_socket
return unless @socket_object.env['rack.hijack']
@socket_object.env['rack.hijack'].call
@rack_hijack_io =
@socket_object.env['rack.hijack_io']
@event_loop.attach(@rack_hijack_io, self)
end
https://github.com/rails/rails/blob/v5.0.0.1/
actioncable/lib/action_cable/connection/
stream.rb#L40-L47
58
ActionCable::Connection::
Stream#clean_rack_hijack
private
def clean_rack_hijack
return unless @rack_hijack_io
@event_loop.detach(@rack_hijack_io,
self)
@rack_hijack_io = nil
end
https://github.com/rails/rails/blob/
v5.0.0.1/actioncable/lib/action_cable/
connection/stream.rb#L40-L47
59
Faye::RackStream#hijack
_rack_socket 1
def hijack_rack_socket
return unless
@socket_object.env['rack.hijack']
@socket_object.env['rack.hijack'].call
@rack_hijack_io =
@socket_object.env['rack.hijack_io']
queue = Queue.new
https://github.com/faye/faye-websocket-
ruby/blob/0.10.5/lib/faye/
rack_stream.rb#L30-L36
60
Faye::RackStream#hijack
_rack_socket 2
EventMachine.schedule do
begin
EventMachine.attach(@rack_hijack_io,
Reader) do |reader|
reader.stream = self
if @rack_hijack_io
@rack_hijack_io_reader = reader
else
reader.close_connection_after_writing
end
https://github.com/faye/faye-websocket-ruby/
blob/0.10.5/lib/faye/rack_stream.rb#L37-L46
61
Faye::RackStream#hijack
_rack_socket 3
ensure
queue.push(nil)
end
end
queue.pop if
EventMachine.reactor_running?
end
https://github.com/faye/faye-websocket-
ruby/blob/0.10.5/lib/faye/
rack_stream.rb#L47-L53
62
Faye::RackStream#clean_
rack_hijack
def clean_rack_hijack
return unless @rack_hijack_io
@rack_hijack_io_reader.close_connection_afte
r_writing
@rack_hijack_io = @rack_hijack_io_reader =
nil
end
https://github.com/faye/faye-websocket-ruby/
blob/0.10.5/lib/faye/rack_stream.rb#L55-L59
63
Conclusion
64
Limitations
•I have not tried to spec out a full IO
API, and I'm not sure that we should.
•I have not tried to respec all of the
HTTP / anti-HTTP semantics.
•There is no spec for buffering or the
like.
•The intent is that this is an API to
"get out the way”.
https://github.com/rack/rack/pull/481
65
What?
this is a straw man that addresses this within
the confines of the rack 1.x spec. It's not an
attempt to build out what I hope a 2.0 spec
should be, but I am hoping that something like
this will be enough to aid Rails 4s ventures,
enable websockets, and a few other strategies.
With HTTP2 around the corner, we'll likely
want to revisit the IO API for 2.0, but we'll
see how this plays out. Maybe IO wrapped
around channels will be ok.
https://github.com/rack/rack/pull/481
66
Thank you.
67
Reference
• http://www.rubydoc.info/github/rack/rack/
master/file/SPEC#Hijacking
• http://old.blog.phusion.nl/2013/01/23/the-
new-rack-socket-hijacking-api/
• https://github.com/rack/rack/pull/481
1 of 68

Recommended

テスト文字列に「うんこ」と入れるな by
テスト文字列に「うんこ」と入れるなテスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるなKentaro Matsui
178.6K views16 slides
Swaggerでのapi開発よもやま話 by
Swaggerでのapi開発よもやま話Swaggerでのapi開発よもやま話
Swaggerでのapi開発よもやま話KEISUKE KONISHI
27.9K views36 slides
新たなgitのブランチモデル「Git Feature Flow」!Git Flow,Git Hub Flow,Git Lab Flowを超えれるか? by
新たなgitのブランチモデル「Git Feature Flow」!Git Flow,Git Hub Flow,Git Lab Flowを超えれるか?新たなgitのブランチモデル「Git Feature Flow」!Git Flow,Git Hub Flow,Git Lab Flowを超えれるか?
新たなgitのブランチモデル「Git Feature Flow」!Git Flow,Git Hub Flow,Git Lab Flowを超えれるか?naoki koyama
91.3K views50 slides
エンジニアの個人ブランディングと技術組織 by
エンジニアの個人ブランディングと技術組織エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織Takafumi ONAKA
23.4K views40 slides
マイクロサービスにおける 結果整合性との戦い by
マイクロサービスにおける 結果整合性との戦いマイクロサービスにおける 結果整合性との戦い
マイクロサービスにおける 結果整合性との戦いota42y
12.4K views41 slides
フロー効率性とリソース効率性について #xpjug by
フロー効率性とリソース効率性について #xpjugフロー効率性とリソース効率性について #xpjug
フロー効率性とリソース効率性について #xpjugItsuki Kuroda
106.3K views62 slides

More Related Content

What's hot

Webアプリを並行開発する際のマイグレーション戦略 by
Webアプリを並行開発する際のマイグレーション戦略Webアプリを並行開発する際のマイグレーション戦略
Webアプリを並行開発する際のマイグレーション戦略Takayuki Shimizukawa
4.8K views49 slides
Redshift Spectrumを使ってみた話 by
Redshift Spectrumを使ってみた話Redshift Spectrumを使ってみた話
Redshift Spectrumを使ってみた話Yoshiki Kouno
5.5K views25 slides
GoによるiOSアプリの開発 by
GoによるiOSアプリの開発GoによるiOSアプリの開発
GoによるiOSアプリの開発Takuya Ueda
16.3K views43 slides
20170406 hr meetup tokyo vol.5_ishiguro by
20170406 hr meetup tokyo vol.5_ishiguro20170406 hr meetup tokyo vol.5_ishiguro
20170406 hr meetup tokyo vol.5_ishiguroTakaya Ishiguro
1.1K views29 slides
Docker Tokyo by
Docker TokyoDocker Tokyo
Docker Tokyocyberblack28 Ichikawa
22.4K views34 slides
JenkinsとCodeBuildとCloud Buildと私 by
JenkinsとCodeBuildとCloud Buildと私JenkinsとCodeBuildとCloud Buildと私
JenkinsとCodeBuildとCloud Buildと私Shoji Shirotori
5.4K views30 slides

What's hot(20)

Webアプリを並行開発する際のマイグレーション戦略 by Takayuki Shimizukawa
Webアプリを並行開発する際のマイグレーション戦略Webアプリを並行開発する際のマイグレーション戦略
Webアプリを並行開発する際のマイグレーション戦略
Redshift Spectrumを使ってみた話 by Yoshiki Kouno
Redshift Spectrumを使ってみた話Redshift Spectrumを使ってみた話
Redshift Spectrumを使ってみた話
Yoshiki Kouno5.5K views
GoによるiOSアプリの開発 by Takuya Ueda
GoによるiOSアプリの開発GoによるiOSアプリの開発
GoによるiOSアプリの開発
Takuya Ueda16.3K views
20170406 hr meetup tokyo vol.5_ishiguro by Takaya Ishiguro
20170406 hr meetup tokyo vol.5_ishiguro20170406 hr meetup tokyo vol.5_ishiguro
20170406 hr meetup tokyo vol.5_ishiguro
Takaya Ishiguro1.1K views
JenkinsとCodeBuildとCloud Buildと私 by Shoji Shirotori
JenkinsとCodeBuildとCloud Buildと私JenkinsとCodeBuildとCloud Buildと私
JenkinsとCodeBuildとCloud Buildと私
Shoji Shirotori5.4K views
PostgreSQLのトラブルシューティング@第5回中国地方DB勉強会 by Shigeru Hanada
PostgreSQLのトラブルシューティング@第5回中国地方DB勉強会PostgreSQLのトラブルシューティング@第5回中国地方DB勉強会
PostgreSQLのトラブルシューティング@第5回中国地方DB勉強会
Shigeru Hanada8.8K views
Redisの特徴と活用方法について by Yuji Otani
Redisの特徴と活用方法についてRedisの特徴と活用方法について
Redisの特徴と活用方法について
Yuji Otani101.6K views
開発速度が速い #とは(LayerX社内資料) by mosa siru
開発速度が速い #とは(LayerX社内資料)開発速度が速い #とは(LayerX社内資料)
開発速度が速い #とは(LayerX社内資料)
mosa siru61.6K views
型安全性入門 by Akinori Abe
型安全性入門型安全性入門
型安全性入門
Akinori Abe7.4K views
綺麗なプレゼン資料の作り方、10のテクニック by Manabu Uekusa
綺麗なプレゼン資料の作り方、10のテクニック綺麗なプレゼン資料の作り方、10のテクニック
綺麗なプレゼン資料の作り方、10のテクニック
Manabu Uekusa381.5K views
Rails上でのpub/sub イベントハンドラの扱い by ota42y
Rails上でのpub/sub イベントハンドラの扱いRails上でのpub/sub イベントハンドラの扱い
Rails上でのpub/sub イベントハンドラの扱い
ota42y5.6K views
Java ORマッパー選定のポイント #jsug by Masatoshi Tada
Java ORマッパー選定のポイント #jsugJava ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsug
Masatoshi Tada90.2K views
PlaySQLAlchemy: SQLAlchemy入門 by 泰 増田
PlaySQLAlchemy: SQLAlchemy入門PlaySQLAlchemy: SQLAlchemy入門
PlaySQLAlchemy: SQLAlchemy入門
泰 増田21.4K views
テストコードの DRY と DAMP by Yusuke Kagata
テストコードの DRY と DAMPテストコードの DRY と DAMP
テストコードの DRY と DAMP
Yusuke Kagata1.6K views
Hatena::Letの式年遷宮 by Takafumi ONAKA
Hatena::Letの式年遷宮Hatena::Letの式年遷宮
Hatena::Letの式年遷宮
Takafumi ONAKA6.2K views
シェル芸初心者によるシェル芸入門 by icchy
シェル芸初心者によるシェル芸入門シェル芸初心者によるシェル芸入門
シェル芸初心者によるシェル芸入門
icchy37.9K views
そのRails Engine、 本当に必要ですか? by nixiesan
そのRails Engine、 本当に必要ですか?そのRails Engine、 本当に必要ですか?
そのRails Engine、 本当に必要ですか?
nixiesan3.5K views
Apache Arrow - データ処理ツールの次世代プラットフォーム by Kouhei Sutou
Apache Arrow - データ処理ツールの次世代プラットフォームApache Arrow - データ処理ツールの次世代プラットフォーム
Apache Arrow - データ処理ツールの次世代プラットフォーム
Kouhei Sutou7.6K views

Similar to What is Rack Hijacking API

Rack by
RackRack
Rackshen liu
2.1K views57 slides
Rhebok, High Performance Rack Handler / Rubykaigi 2015 by
Rhebok, High Performance Rack Handler / Rubykaigi 2015Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015Masahiro Nagano
76.1K views67 slides
Plack perl superglue for web frameworks and servers by
Plack perl superglue for web frameworks and serversPlack perl superglue for web frameworks and servers
Plack perl superglue for web frameworks and serversTatsuhiko Miyagawa
6.7K views127 slides
Intro to Rack by
Intro to RackIntro to Rack
Intro to RackRubyc Slides
3K views54 slides
HOW TO DEAL WITH BLOCKING CODE WITHIN ASYNCIO EVENT LOOP by
HOW TO DEAL WITH BLOCKING CODE WITHIN ASYNCIO EVENT LOOPHOW TO DEAL WITH BLOCKING CODE WITHIN ASYNCIO EVENT LOOP
HOW TO DEAL WITH BLOCKING CODE WITHIN ASYNCIO EVENT LOOPMykola Novik
3.5K views22 slides
Lecture05.pptx by
Lecture05.pptxLecture05.pptx
Lecture05.pptxMrVMNair
1 view25 slides

Similar to What is Rack Hijacking API(20)

Rack by shen liu
RackRack
Rack
shen liu2.1K views
Rhebok, High Performance Rack Handler / Rubykaigi 2015 by Masahiro Nagano
Rhebok, High Performance Rack Handler / Rubykaigi 2015Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015
Masahiro Nagano76.1K views
Plack perl superglue for web frameworks and servers by Tatsuhiko Miyagawa
Plack perl superglue for web frameworks and serversPlack perl superglue for web frameworks and servers
Plack perl superglue for web frameworks and servers
Tatsuhiko Miyagawa6.7K views
HOW TO DEAL WITH BLOCKING CODE WITHIN ASYNCIO EVENT LOOP by Mykola Novik
HOW TO DEAL WITH BLOCKING CODE WITHIN ASYNCIO EVENT LOOPHOW TO DEAL WITH BLOCKING CODE WITHIN ASYNCIO EVENT LOOP
HOW TO DEAL WITH BLOCKING CODE WITHIN ASYNCIO EVENT LOOP
Mykola Novik3.5K views
Lecture05.pptx by MrVMNair
Lecture05.pptxLecture05.pptx
Lecture05.pptx
MrVMNair1 view
Building web framework with Rack by sickill
Building web framework with RackBuilding web framework with Rack
Building web framework with Rack
sickill3.6K views
Complex Made Simple: Sleep Better with TorqueBox by bobmcwhirter
Complex Made Simple: Sleep Better with TorqueBoxComplex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBox
bobmcwhirter1.7K views
Containerd Project Update: FOSDEM 2018 by Phil Estes
Containerd Project Update: FOSDEM 2018Containerd Project Update: FOSDEM 2018
Containerd Project Update: FOSDEM 2018
Phil Estes1.7K views
"Wix Serverless from inside", Mykola Borozdin by Fwdays
"Wix Serverless from inside", Mykola Borozdin"Wix Serverless from inside", Mykola Borozdin
"Wix Serverless from inside", Mykola Borozdin
Fwdays273 views
Simplifying Migration from Kafka to Pulsar - Pulsar Summit NA 2021 by StreamNative
Simplifying Migration from Kafka to Pulsar - Pulsar Summit NA 2021Simplifying Migration from Kafka to Pulsar - Pulsar Summit NA 2021
Simplifying Migration from Kafka to Pulsar - Pulsar Summit NA 2021
StreamNative116 views
Scaling docker with kubernetes by Liran Cohen
Scaling docker with kubernetesScaling docker with kubernetes
Scaling docker with kubernetes
Liran Cohen2.4K views
Deis, a PaaS built with Docker, Docker Meetup Sao Paulo #3 @Wayra by Leo Lorieri
Deis, a PaaS built with Docker,  Docker Meetup Sao Paulo #3 @WayraDeis, a PaaS built with Docker,  Docker Meetup Sao Paulo #3 @Wayra
Deis, a PaaS built with Docker, Docker Meetup Sao Paulo #3 @Wayra
Leo Lorieri1.1K views
DevOps in PHP environment by Evaldo Felipe
DevOps in PHP environment DevOps in PHP environment
DevOps in PHP environment
Evaldo Felipe160 views
Devoxx France: Développement JAVA avec un IDE dans le Cloud: Yes we can ! by Florent BENOIT
Devoxx France: Développement JAVA avec un IDE dans le Cloud: Yes we can !Devoxx France: Développement JAVA avec un IDE dans le Cloud: Yes we can !
Devoxx France: Développement JAVA avec un IDE dans le Cloud: Yes we can !
Florent BENOIT1.2K views

Recently uploaded

Renewal Projects in Seismic Construction by
Renewal Projects in Seismic ConstructionRenewal Projects in Seismic Construction
Renewal Projects in Seismic ConstructionEngineering & Seismic Construction
5 views8 slides
ASSIGNMENTS ON FUZZY LOGIC IN TRAFFIC FLOW.pdf by
ASSIGNMENTS ON FUZZY LOGIC IN TRAFFIC FLOW.pdfASSIGNMENTS ON FUZZY LOGIC IN TRAFFIC FLOW.pdf
ASSIGNMENTS ON FUZZY LOGIC IN TRAFFIC FLOW.pdfAlhamduKure
8 views11 slides
sam_software_eng_cv.pdf by
sam_software_eng_cv.pdfsam_software_eng_cv.pdf
sam_software_eng_cv.pdfsammyigbinovia
10 views5 slides
Proposal Presentation.pptx by
Proposal Presentation.pptxProposal Presentation.pptx
Proposal Presentation.pptxkeytonallamon
67 views36 slides
Robotics in construction enterprise by
Robotics in construction enterpriseRobotics in construction enterprise
Robotics in construction enterpriseKhalid Abdel Naser Abdel Rahim
5 views1 slide
MK__Cert.pdf by
MK__Cert.pdfMK__Cert.pdf
MK__Cert.pdfHassan Khan
19 views1 slide

Recently uploaded(20)

ASSIGNMENTS ON FUZZY LOGIC IN TRAFFIC FLOW.pdf by AlhamduKure
ASSIGNMENTS ON FUZZY LOGIC IN TRAFFIC FLOW.pdfASSIGNMENTS ON FUZZY LOGIC IN TRAFFIC FLOW.pdf
ASSIGNMENTS ON FUZZY LOGIC IN TRAFFIC FLOW.pdf
AlhamduKure8 views
REACTJS.pdf by ArthyR3
REACTJS.pdfREACTJS.pdf
REACTJS.pdf
ArthyR337 views
SUMIT SQL PROJECT SUPERSTORE 1.pptx by Sumit Jadhav
SUMIT SQL PROJECT SUPERSTORE 1.pptxSUMIT SQL PROJECT SUPERSTORE 1.pptx
SUMIT SQL PROJECT SUPERSTORE 1.pptx
Sumit Jadhav 22 views
MongoDB.pdf by ArthyR3
MongoDB.pdfMongoDB.pdf
MongoDB.pdf
ArthyR349 views
Searching in Data Structure by raghavbirla63
Searching in Data StructureSearching in Data Structure
Searching in Data Structure
raghavbirla6317 views
Ansari: Practical experiences with an LLM-based Islamic Assistant by M Waleed Kadous
Ansari: Practical experiences with an LLM-based Islamic AssistantAnsari: Practical experiences with an LLM-based Islamic Assistant
Ansari: Practical experiences with an LLM-based Islamic Assistant
M Waleed Kadous9 views
Web Dev Session 1.pptx by VedVekhande
Web Dev Session 1.pptxWeb Dev Session 1.pptx
Web Dev Session 1.pptx
VedVekhande17 views
2023Dec ASU Wang NETR Group Research Focus and Facility Overview.pptx by lwang78
2023Dec ASU Wang NETR Group Research Focus and Facility Overview.pptx2023Dec ASU Wang NETR Group Research Focus and Facility Overview.pptx
2023Dec ASU Wang NETR Group Research Focus and Facility Overview.pptx
lwang78180 views
Design of machine elements-UNIT 3.pptx by gopinathcreddy
Design of machine elements-UNIT 3.pptxDesign of machine elements-UNIT 3.pptx
Design of machine elements-UNIT 3.pptx
gopinathcreddy37 views
BCIC - Manufacturing Conclave - Technology-Driven Manufacturing for Growth by Innomantra
BCIC - Manufacturing Conclave -  Technology-Driven Manufacturing for GrowthBCIC - Manufacturing Conclave -  Technology-Driven Manufacturing for Growth
BCIC - Manufacturing Conclave - Technology-Driven Manufacturing for Growth
Innomantra 15 views
_MAKRIADI-FOTEINI_diploma thesis.pptx by fotinimakriadi
_MAKRIADI-FOTEINI_diploma thesis.pptx_MAKRIADI-FOTEINI_diploma thesis.pptx
_MAKRIADI-FOTEINI_diploma thesis.pptx
fotinimakriadi12 views
Design_Discover_Develop_Campaign.pptx by ShivanshSeth6
Design_Discover_Develop_Campaign.pptxDesign_Discover_Develop_Campaign.pptx
Design_Discover_Develop_Campaign.pptx
ShivanshSeth649 views

What is Rack Hijacking API