Class: Async::HTTP::Protocol::HTTP

Inherits:
Object
  • Object
show all
Defined in:
lib/async/http/protocol/http.rb

Overview

HTTP is an http:// server that auto-selects HTTP/1.1 or HTTP/2 by detecting the HTTP/2 connection preface.

Constant Summary collapse

HTTP2_PREFACE =
"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
HTTP2_PREFACE_SIZE =
HTTP2_PREFACE.bytesize

Instance Method Summary collapse

Constructor Details

#initialize(http1: HTTP1, http2: HTTP2) ⇒ HTTP

Create a new HTTP protocol instance.



24
25
26
27
# File 'lib/async/http/protocol/http.rb', line 24

def initialize(http1: HTTP1, http2: HTTP2)
	@http1 = http1
	@http2 = http2
end

Instance Method Details

#client(peer, **options) ⇒ Object

Create a client for an outbound connection. Defaults to HTTP/1 for plaintext connections.



62
63
64
65
66
# File 'lib/async/http/protocol/http.rb', line 62

def client(peer, **options)
	options = options[@http1] || {}
	
	return @http1.client(peer, **options)
end

#namesObject

The names of all supported protocols.



31
32
33
# File 'lib/async/http/protocol/http.rb', line 31

def names
	(@http2.names + @http1.names).uniq
end

#protocol_for(stream) ⇒ Object

Determine if the inbound connection is HTTP/1 or HTTP/2.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/async/http/protocol/http.rb', line 39

def protocol_for(stream)
	# Detect HTTP/2 connection preface
	# https://www.rfc-editor.org/rfc/rfc9113.html#section-3.4
	preface = stream.peek do |read_buffer|
		if read_buffer.bytesize >= HTTP2_PREFACE_SIZE
			break read_buffer[0, HTTP2_PREFACE_SIZE]
		elsif read_buffer.bytesize > 0
			# If partial read_buffer already doesn't match, no need to wait for more bytes.
			break read_buffer unless HTTP2_PREFACE[read_buffer]
		end
	end
	
	if preface == HTTP2_PREFACE
		@http2
	else
		@http1
	end
end

#server(peer, **options) ⇒ Object

Create a server for an inbound connection. Able to detect HTTP1 and HTTP2.



72
73
74
75
76
77
78
# File 'lib/async/http/protocol/http.rb', line 72

def server(peer, **options)
	stream = IO::Stream(peer)
	protocol = protocol_for(stream)
	options = options[protocol] || {}
	
	return protocol.server(stream, **options)
end