File: http2.rb

package info (click to toggle)
ruby-async-http 0.94.2-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 916 kB
  • sloc: ruby: 5,224; javascript: 40; makefile: 4
file content (124 lines) | stat: -rw-r--r-- 2,946 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# frozen_string_literal: true

# Released under the MIT License.
# Copyright, 2018-2025, by Samuel Williams.

require "async/http/protocol/http2"
require "async/http/a_protocol"

describe Async::HTTP::Protocol::HTTP2 do
	it_behaves_like Async::HTTP::AProtocol
	
	with "#as_json" do
		include Sus::Fixtures::Async::HTTP::ServerContext
		let(:protocol) {subject}
		
		it "generates a JSON representation" do
			response = client.get("/")
			connection = response.connection
			
			expect(connection.as_json).to be =~ /#<Async::HTTP::Protocol::HTTP2::Client \d+ active streams>/
		ensure
			response&.close
		end
		
		it "generates a JSON string" do
			response = client.get("/")
			connection = response.connection
			
			expect(JSON.dump(connection)).to be == connection.to_json
		ensure
			response&.close
		end
	end
	
	with "server" do
		include Sus::Fixtures::Async::HTTP::ServerContext
		let(:protocol) {subject}
		
		with "bad requests" do
			it "should fail with explicit authority" do
				expect do
					client.post("/", [[":authority", "foo"]])
				end.to raise_exception(Protocol::HTTP2::StreamError)
			end
		end
		
		with "closed streams" do
			it "should delete stream after response stream is closed" do
				response = client.get("/")
				connection = response.connection
				
				response.read
				
				expect(connection.streams).to be(:empty?)
			end
		end
		
		with "host header" do
			let(:app) do
				Protocol::HTTP::Middleware.for do |request|
					Protocol::HTTP::Response[200, request.headers, ["Authority: #{request.authority.inspect}"]]
				end
			end
			
			def make_client(endpoint, **options)
				# We specify nil for the authority - it won't be sent.
				options[:authority] = nil
				super
			end
			
			it "should not send :authority header if host header is present" do
				response = client.post("/", [["host", "foo"]])
				
				expect(response.headers).to have_keys("host")
				expect(response.headers["host"]).to be == "foo"
				
				# TODO Should HTTP/2 respect host header?
				expect(response.read).to be == "Authority: nil"
			end
		end
		
		with "stopping requests" do
			let(:notification) {Async::Notification.new}
			
			let(:app) do
				Protocol::HTTP::Middleware.for do |request|
					body = Async::HTTP::Body::Writable.new
					
					reactor.async do |task|
						begin
							100.times do |i|
								body.write("Chunk #{i}")
								sleep (0.01)
							end
						rescue
							# puts "Response generation failed: #{$!}"
						ensure
							body.close
							notification.signal
						end
					end
					
					Protocol::HTTP::Response[200, {}, body]
				end
			end
			
			let(:pool) {client.pool}
			
			it "should close stream without closing connection" do
				expect(pool).to be(:empty?)
				
				response = client.get("/")
				
				expect(pool).not.to be(:empty?)
				
				response.close
				
				notification.wait
				
				expect(response.stream.connection).to be(:reusable?)
			end
		end
	end
end