Class: Async::HTTP::Protocol::HTTP2::Server

Inherits:
Protocol::HTTP2::Server
  • Object
show all
Includes:
Connection
Defined in:
lib/async/http/protocol/http2/server.rb

Overview

An HTTP/2 server connection that receives requests and sends responses.

Instance Attribute Summary collapse

Attributes included from Connection

#count, #promises, #stream

Instance Method Summary collapse

Methods included from Connection

#as_json, #concurrency, #http1?, #http2?, #peer, #read_in_background, #reusable?, #start_connection, #synchronize, #to_json, #to_s, #version, #viable?, #write_frame, #write_frames

Constructor Details

#initialize(stream) ⇒ Server

Initialize the HTTP/2 server with an IO stream.



21
22
23
24
25
26
27
28
29
30
# File 'lib/async/http/protocol/http2/server.rb', line 21

def initialize(stream)
	# Used by some generic methods in Connetion:
	@stream = stream
	
	framer = ::Protocol::HTTP2::Framer.new(stream)
	
	super(framer)
	
	@requests = Async::Queue.new
end

Instance Attribute Details

#requestsObject (readonly)

Returns the value of attribute requests.



32
33
34
# File 'lib/async/http/protocol/http2/server.rb', line 32

def requests
  @requests
end

Instance Method Details

#accept_stream(stream_id) ⇒ Object

Accept a new stream from a client.



36
37
38
39
40
# File 'lib/async/http/protocol/http2/server.rb', line 36

def accept_stream(stream_id)
	super do
		Request::Stream.create(self, stream_id)
	end
end

#close(error = nil) ⇒ Object

Close the server connection and stop accepting requests.



43
44
45
46
47
48
49
50
51
# File 'lib/async/http/protocol/http2/server.rb', line 43

def close(error = nil)
	if @requests
		# Stop the request loop:
		@requests.enqueue(nil)
		@requests = nil
	end
	
	super
end

#each(task: Task.current) ⇒ Object

Enumerate incoming requests, yielding each one for processing.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/async/http/protocol/http2/server.rb', line 56

def each(task: Task.current)
	task.annotate("Reading #{version} requests for #{self.class}.")
	
	# It's possible the connection has died before we get here...
	@requests&.async do |task, request|
		task.annotate("Incoming request: #{request.method} #{request.path.inspect}.")
		
		response = nil
		
		task.defer_stop do
			response = yield(request)
		rescue
			# We need to close the stream if the user code blows up while generating a response:
			request.stream.send_reset_stream(::Protocol::HTTP2::INTERNAL_ERROR)
			
			raise
		else
			request.send_response(response)
			# If send response is successful, we clear it so that we don't close it below.
			response = nil
		ensure
			# If some failure occurs and we didn't send the response correctly, ensure that it's closed:
			response&.close
		end
	end
	
	# Maybe we should add some synchronisation here - i.e. only exit once all requests are finished.
end