Skip to content

Instantly share code, notes, and snippets.

@seenmyfate
Created March 30, 2016 19:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seenmyfate/dad1a1bd1045063c7dfd6b7ad17cc233 to your computer and use it in GitHub Desktop.
Save seenmyfate/dad1a1bd1045063c7dfd6b7ad17cc233 to your computer and use it in GitHub Desktop.
require_relative 'helper'
class MyApp
def half_close(request)
[200, { 'content-type' => 'text/plan' }, 'Hello HTTP 2.0! GET request']
end
def promise(request)
[200, { 'content-type' => 'text/plan' }, 'A promise']
end
end
class Message
def initialize(response)
@status, @headers, @data = response
end
def response
[headers, @data]
end
private
def headers
@headers.merge(
'status' => @status.to_s,
'content-length' => @data.bytesize.to_s,
)
end
end
class Server
attr_reader :app, :server
protected :app, :server
def initialize(app, server)
@app, @server = app, server
end
def sock
@sock ||= server.accept
end
def conn
@conn ||= HTTP2::Server.new
end
def listen
loop do
conn.on(:frame) do |bytes|
sock.write bytes
end
conn.on(:stream) do |stream|
req = {}
stream.on(:headers) do |h|
req = Hash[*h.flatten]
end
stream.on(:half_close) do
headers, data = Message.new(app.half_close(req)).response
stream.headers(headers, end_stream: false)
# split response into multiple DATA frames
stream.data(data.slice!(0, 5), end_stream: false)
stream.data(data)
end
end
while !sock.closed? && !(sock.eof? rescue true) # rubocop:disable Style/RescueModifier
data = sock.readpartial(1024)
# puts "Received bytes: #{data.unpack("H*").first}"
begin
conn << data
rescue => e
puts "#{e.class} exception: #{e.message} - closing socket."
e.backtrace.each { |l| puts "\t" + l }
sock.close
end
end
end
end
end
Server.new(MyApp.new, TCPServer.new(8080)).listen
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment