syntropy 0.30.0 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -0
  3. data/bin/syntropy +8 -86
  4. data/cmd/_banner.rb +16 -0
  5. data/cmd/help.rb +12 -0
  6. data/cmd/serve.rb +95 -0
  7. data/cmd/test.rb +40 -0
  8. data/examples/{counter.rb → basic/counter.rb} +1 -1
  9. data/examples/{templates.rb → basic/templates.rb} +1 -1
  10. data/examples/mcp-oauth/.ruby-version +1 -0
  11. data/examples/mcp-oauth/Gemfile +8 -0
  12. data/examples/mcp-oauth/README.md +128 -0
  13. data/examples/mcp-oauth/app/.well-known/oauth-authorization-server.rb +18 -0
  14. data/examples/mcp-oauth/app/.well-known/oauth-protected-resource.rb +10 -0
  15. data/examples/mcp-oauth/app/_lib/auth_store.rb +23 -0
  16. data/examples/mcp-oauth/app/index.md +1 -0
  17. data/examples/mcp-oauth/app/mcp.rb +38 -0
  18. data/examples/mcp-oauth/app/oauth/authorize.rb +26 -0
  19. data/examples/mcp-oauth/app/oauth/consent.rb +86 -0
  20. data/examples/mcp-oauth/app/oauth/register.rb +15 -0
  21. data/examples/mcp-oauth/app/oauth/token.rb +79 -0
  22. data/examples/mcp-oauth/app/signin.rb +85 -0
  23. data/examples/mcp-oauth/test/helper.rb +9 -0
  24. data/examples/mcp-oauth/test/test_app.rb +27 -0
  25. data/examples/mcp-oauth/test/test_oauth.rb +628 -0
  26. data/lib/syntropy/app.rb +15 -4
  27. data/lib/syntropy/applets/builtin/default_error_handler.rb +3 -3
  28. data/lib/syntropy/applets/builtin/req.rb +1 -1
  29. data/lib/syntropy/dev_mode.rb +1 -1
  30. data/lib/syntropy/errors.rb +6 -0
  31. data/lib/syntropy/http/client.rb +43 -0
  32. data/lib/syntropy/http/client_connection.rb +36 -0
  33. data/lib/syntropy/http/io_extensions.rb +148 -0
  34. data/lib/syntropy/http/server.rb +5 -5
  35. data/lib/syntropy/http/{connection.rb → server_connection.rb} +9 -38
  36. data/lib/syntropy/http.rb +3 -1
  37. data/lib/syntropy/logger.rb +5 -1
  38. data/lib/syntropy/papercraft_extensions.rb +1 -1
  39. data/lib/syntropy/request/mock_adapter.rb +2 -0
  40. data/lib/syntropy/request/request_info.rb +20 -1
  41. data/lib/syntropy/request/response.rb +2 -2
  42. data/lib/syntropy/request/validation.rb +10 -3
  43. data/lib/syntropy/routing_tree.rb +2 -1
  44. data/lib/syntropy/test.rb +65 -0
  45. data/lib/syntropy/version.rb +1 -1
  46. data/lib/syntropy.rb +1 -21
  47. data/syntropy.gemspec +1 -2
  48. data/test/app/.well-known/foo.rb +3 -0
  49. data/test/helper.rb +1 -25
  50. data/test/test_app.rb +53 -68
  51. data/test/test_caching.rb +1 -1
  52. data/test/test_http_client.rb +52 -0
  53. data/test/test_http_client_connection.rb +43 -0
  54. data/test/{test_connection.rb → test_http_server_connection.rb} +29 -29
  55. data/test/test_json_api.rb +4 -4
  56. data/test/{test_request_extensions.rb → test_request.rb} +150 -18
  57. data/test/test_routing_tree.rb +15 -3
  58. metadata +41 -29
  59. data/test/test_request_info.rb +0 -90
  60. /data/examples/{bad.rb → basic/bad.rb} +0 -0
  61. /data/examples/{card.rb → basic/card.rb} +0 -0
  62. /data/examples/{counter.js → basic/counter.js} +0 -0
  63. /data/examples/{counter_api.rb → basic/counter_api.rb} +0 -0
  64. /data/examples/{favicon.ico → basic/favicon.ico} +0 -0
  65. /data/examples/{index.md → basic/index.md} +0 -0
data/test/test_app.rb CHANGED
@@ -19,111 +19,111 @@ class AppTest < Minitest::Test
19
19
  watch_files: 0.05,
20
20
  machine: @machine
21
21
  )
22
- end
23
22
 
24
- def make_request(*, **)
25
- req = mock_req(*, **)
26
- @app.call(req)
27
- req
23
+ @test_harness = Syntropy::TestHarness.new(@app)
28
24
  end
29
25
 
30
26
  def test_app_rendering
31
- req = make_request(':method' => 'GET', ':path' => '/')
27
+ req = @test_harness.request(':method' => 'GET', ':path' => '/')
32
28
  assert_equal HTTP::NOT_FOUND, req.response_status
33
29
  assert_equal 'Not found', req.response_body
34
30
 
35
- req = make_request(':method' => 'HEAD', ':path' => '/')
31
+ req = @test_harness.request(':method' => 'HEAD', ':path' => '/')
36
32
  assert_equal HTTP::NOT_FOUND, req.response_status
37
33
  assert_nil req.response_body
38
34
 
39
- req = make_request(':method' => 'POST', ':path' => '/')
35
+ req = @test_harness.request(':method' => 'POST', ':path' => '/')
40
36
  assert_equal 'Not found', req.response_body
41
37
  assert_equal HTTP::NOT_FOUND, req.response_status
42
38
 
43
- req = make_request(':method' => 'GET', ':path' => '/test')
39
+ req = @test_harness.request(':method' => 'GET', ':path' => '/test')
44
40
  assert_equal HTTP::OK, req.response_status
45
41
  assert_equal '<h1>Hello, world!</h1>', req.response_body
46
42
 
47
- req = make_request(':method' => 'HEAD', ':path' => '/test')
43
+ req = @test_harness.request(':method' => 'HEAD', ':path' => '/test')
48
44
  assert_equal HTTP::OK, req.response_status
49
45
  assert_nil req.response_body
50
46
 
51
- req = make_request(':method' => 'POST', ':path' => '/test')
47
+ req = @test_harness.request(':method' => 'POST', ':path' => '/test')
52
48
  assert_equal HTTP::METHOD_NOT_ALLOWED, req.response_status
53
49
  assert_equal "Method not allowed", req.response_body
54
50
 
55
- req = make_request(':method' => 'GET', ':path' => '/test/assets/style.css')
51
+ req = @test_harness.request(':method' => 'GET', ':path' => '/test/assets/style.css')
56
52
  assert_equal '* { color: beige }', req.response_body
57
53
  assert_equal 'text/css', req.response_headers['Content-Type']
58
54
 
59
- req = make_request(':method' => 'GET', ':path' => '/assets/style.css')
55
+ req = @test_harness.request(':method' => 'GET', ':path' => '/assets/style.css')
60
56
  assert_equal HTTP::NOT_FOUND, req.response_status
61
57
 
62
- req = make_request(':method' => 'GET', ':path' => '/test/api?q=get')
63
- assert_equal({ status: 'OK', response: 0 }, req.response_json)
58
+ req = @test_harness.request(':method' => 'GET', ':path' => '/test/api?q=get')
59
+ assert_equal({ 'status' => 'OK', 'response' => 0 }, req.response_json)
64
60
 
65
- req = make_request(':method' => 'POST', ':path' => '/test/api?q=get')
61
+ req = @test_harness.request(':method' => 'POST', ':path' => '/test/api?q=get')
66
62
  assert_equal HTTP::METHOD_NOT_ALLOWED, req.response_status
67
- assert_equal({ status: 'Error', message: 'Method not allowed' }, req.response_json)
63
+ assert_equal({ 'status' => 'Error', 'message' => 'Method not allowed' }, req.response_json)
68
64
 
69
- req = make_request(':method' => 'GET', ':path' => '/test/api/foo?q=get')
70
- assert_equal({ status: 'OK', response: 0 }, req.response_json)
65
+ req = @test_harness.request(':method' => 'GET', ':path' => '/test/api/foo?q=get')
66
+ assert_equal({ 'status' => 'OK', 'response' => 0 }, req.response_json)
71
67
 
72
- req = make_request(':method' => 'POST', ':path' => '/test/api?q=incr')
73
- assert_equal({ status: 'OK', response: 1 }, req.response_json)
68
+ req = @test_harness.request(':method' => 'POST', ':path' => '/test/api?q=incr')
69
+ assert_equal({ 'status' => 'OK', 'response' => 1 }, req.response_json)
74
70
 
75
- req = make_request(':method' => 'GET', ':path' => '/test/api?q=incr')
71
+ req = @test_harness.request(':method' => 'GET', ':path' => '/test/api?q=incr')
76
72
  assert_equal HTTP::METHOD_NOT_ALLOWED, req.response_status
77
- assert_equal({ status: 'Error', message: 'Method not allowed' }, req.response_json)
73
+ assert_equal({ 'status' => 'Error', 'message' => 'Method not allowed' }, req.response_json)
78
74
 
79
- req = make_request(':method' => 'POST', ':path' => '/test/api/foo?q=incr')
80
- assert_equal({ status: 'Error', message: 'Teapot' }, req.response_json)
75
+ req = @test_harness.request(':method' => 'POST', ':path' => '/test/api/foo?q=incr')
76
+ assert_equal({ 'status' => 'Error', 'message' => 'Teapot' }, req.response_json)
81
77
  assert_equal HTTP::TEAPOT, req.response_status
82
78
 
83
- req = make_request(':method' => 'POST', ':path' => '/test/api/foo/bar?q=incr')
84
- assert_equal({ status: 'Error', message: 'Teapot' }, req.response_json)
79
+ req = @test_harness.request(':method' => 'POST', ':path' => '/test/api/foo/bar?q=incr')
80
+ assert_equal({ 'status' => 'Error', 'message' => 'Teapot' }, req.response_json)
85
81
  assert_equal HTTP::TEAPOT, req.response_status
86
82
 
87
- req = make_request(':method' => 'GET', ':path' => '/test/bar')
83
+ req = @test_harness.request(':method' => 'GET', ':path' => '/test/bar')
88
84
  assert_equal 'foobar', req.response_body
89
85
  assert_equal HTTP::OK, req.response_status
90
86
 
91
- req = make_request(':method' => 'POST', ':path' => '/test/bar')
87
+ req = @test_harness.request(':method' => 'POST', ':path' => '/test/bar')
92
88
  assert_equal 'foobar', req.response_body
93
89
  assert_equal HTTP::OK, req.response_status
94
90
 
95
- req = make_request(':method' => 'GET', ':path' => '/test/baz')
91
+ req = @test_harness.request(':method' => 'GET', ':path' => '/test/baz')
96
92
  assert_equal 'foobar', req.response_body
97
93
  assert_equal HTTP::OK, req.response_status
98
94
 
99
- req = make_request(':method' => 'POST', ':path' => '/test/baz')
95
+ req = @test_harness.request(':method' => 'POST', ':path' => '/test/baz')
100
96
  assert_equal 'Method not allowed', req.response_body
101
97
  assert_equal HTTP::METHOD_NOT_ALLOWED, req.response_status
102
98
 
103
- req = make_request(':method' => 'GET', ':path' => '/test/about')
99
+ req = @test_harness.request(':method' => 'GET', ':path' => '/test/about')
104
100
  assert_equal 'About', req.response_body.chomp
105
101
 
106
- req = make_request(':method' => 'GET', ':path' => '/test/about/foo')
102
+ req = @test_harness.request(':method' => 'GET', ':path' => '/test/about/foo')
107
103
  assert_equal '<!DOCTYPE html><html><head><title></title></head><body><p>Hello from Markdown</p></body></html>', req.response_body.gsub(/\n/, '')
108
104
 
109
- req = make_request(':method' => 'HEAD', ':path' => '/test/about/foo')
105
+ req = @test_harness.request(':method' => 'HEAD', ':path' => '/test/about/foo')
110
106
  assert_nil req.response_body
111
107
 
112
- req = make_request(':method' => 'GET', ':path' => '/test/about/foo/bar')
108
+ req = @test_harness.request(':method' => 'GET', ':path' => '/test/about/foo/bar')
113
109
  assert_equal HTTP::NOT_FOUND, req.response_status
114
110
 
115
- req = make_request(':method' => 'GET', ':path' => '/test/params/abc')
111
+ req = @test_harness.request(':method' => 'GET', ':path' => '/test/params/abc')
116
112
  assert_equal '/test/params/[foo]-abc', req.response_body.chomp
117
113
 
118
- req = make_request(':method' => 'GET', ':path' => '/test/rss')
114
+ req = @test_harness.request(':method' => 'GET', ':path' => '/test/rss')
119
115
  assert_equal '<link>foo</link>', req.response_body
120
116
 
121
- req = make_request(':method' => 'GET', ':path' => '/test/bad_mod')
117
+ req = @test_harness.request(':method' => 'GET', ':path' => '/test/bad_mod')
122
118
  assert_equal HTTP::INTERNAL_SERVER_ERROR, req.response_status
119
+
120
+ req = @test_harness.request(':method' => 'GET', ':path' => '/test/.well-known/foo')
121
+ assert_equal HTTP::OK, req.response_status
122
+ assert_equal 'foo', req.response_body
123
123
  end
124
124
 
125
125
  def test_automatic_redirect_on_trailing_slash
126
- req = make_request(':method' => 'GET', ':path' => '/test/rss/')
126
+ req = @test_harness.request(':method' => 'GET', ':path' => '/test/rss/')
127
127
  assert_equal HTTP::MOVED_PERMANENTLY, req.response_status
128
128
  assert_equal '/test/rss', req.response_headers['Location']
129
129
  end
@@ -131,37 +131,37 @@ class AppTest < Minitest::Test
131
131
  def test_app_file_watching
132
132
  @machine.sleep 0.3
133
133
 
134
- req = make_request(':method' => 'GET', ':path' => @tmp_path)
134
+ req = @test_harness.request(':method' => 'GET', ':path' => @tmp_path)
135
135
  assert_equal 'foo', req.response_body
136
136
 
137
137
  orig_body = IO.read(@tmp_fn)
138
138
  IO.write(@tmp_fn, orig_body.gsub('foo', 'bar'))
139
139
  @machine.sleep(0.3)
140
140
 
141
- req = make_request(':method' => 'GET', ':path' => @tmp_path)
141
+ req = @test_harness.request(':method' => 'GET', ':path' => @tmp_path)
142
142
  assert_equal 'bar', req.response_body
143
143
  ensure
144
144
  IO.write(@tmp_fn, orig_body) if orig_body
145
145
  end
146
146
 
147
147
  def test_middleware
148
- req = make_request(':method' => 'HEAD', ':path' => '/test?foo=42')
148
+ req = @test_harness.request(':method' => 'HEAD', ':path' => '/test?foo=42')
149
149
  assert_equal HTTP::OK, req.response_status
150
150
  assert_nil req.response_body
151
151
  assert_equal '42', req.ctx[:foo]
152
152
 
153
- req = make_request(':method' => 'HEAD', ':path' => '/test/about/raise?foo=43')
153
+ req = @test_harness.request(':method' => 'HEAD', ':path' => '/test/about/raise?foo=43')
154
154
  assert_equal HTTP::INTERNAL_SERVER_ERROR, req.response_status
155
155
  assert_equal '<h1>Raised error</h1>', req.response_body
156
156
  assert_equal '43', req.ctx[:foo]
157
157
  end
158
158
 
159
159
  def test_middleware_invocation_on_404
160
- req = make_request(':method' => 'HEAD', ':path' => '/azerty?foo=bar')
160
+ req = @test_harness.request(':method' => 'HEAD', ':path' => '/azerty?foo=bar')
161
161
  assert_equal HTTP::NOT_FOUND, req.response_status
162
162
  assert_nil req.ctx[:foo]
163
163
 
164
- req = make_request(':method' => 'HEAD', ':path' => '/test/azerty?foo=bar')
164
+ req = @test_harness.request(':method' => 'HEAD', ':path' => '/test/azerty?foo=bar')
165
165
  assert_equal HTTP::NOT_FOUND, req.response_status
166
166
  assert_equal 'bar', req.ctx[:foo]
167
167
  end
@@ -179,16 +179,11 @@ class CustomAppTest < Minitest::Test
179
179
  root_dir: APP_ROOT,
180
180
  mount_path: '/'
181
181
  )
182
- end
183
-
184
- def make_request(*, **)
185
- req = mock_req(*, **)
186
- @app.call(req)
187
- req
182
+ @test_harness = Syntropy::TestHarness.new(@app)
188
183
  end
189
184
 
190
185
  def test_app_with_site_rb_file
191
- req = make_request(':method' => 'GET', ':path' => '/foo/bar')
186
+ req = @test_harness.request(':method' => 'GET', ':path' => '/foo/bar')
192
187
  assert_nil req.response_body
193
188
  assert_equal HTTP::TEAPOT, req.response_status
194
189
  end
@@ -206,23 +201,18 @@ class MultiSiteAppTest < Minitest::Test
206
201
  root_dir: APP_ROOT,
207
202
  mount_path: '/'
208
203
  )
209
- end
210
-
211
- def make_request(*, **)
212
- req = mock_req(*, **)
213
- @app.call(req)
214
- req
204
+ @test_harness = Syntropy::TestHarness.new(@app)
215
205
  end
216
206
 
217
207
  def test_route_by_host
218
- req = make_request(':method' => 'GET', ':path' => '/', 'host' => 'blah')
208
+ req = @test_harness.request(':method' => 'GET', ':path' => '/', 'host' => 'blah')
219
209
  assert_nil req.response_body
220
210
  assert_equal HTTP::BAD_REQUEST, req.response_status
221
211
 
222
- req = make_request(':method' => 'GET', ':path' => '/', 'host' => 'foo.bar')
212
+ req = @test_harness.request(':method' => 'GET', ':path' => '/', 'host' => 'foo.bar')
223
213
  assert_equal '<h1>foo.bar</h1>', req.response_body.chomp
224
214
 
225
- req = make_request(':method' => 'GET', ':path' => '/', 'host' => 'bar.baz')
215
+ req = @test_harness.request(':method' => 'GET', ':path' => '/', 'host' => 'bar.baz')
226
216
  assert_equal '<h1>bar.baz</h1>', req.response_body.chomp
227
217
  end
228
218
  end
@@ -296,12 +286,6 @@ class AppDependenciesTest < Minitest::Test
296
286
 
297
287
  APP_ROOT = File.join(__dir__, 'app')
298
288
 
299
- def make_request(*, **)
300
- req = mock_req(*, **)
301
- @app.call(req)
302
- req
303
- end
304
-
305
289
  def test_app_dependencies
306
290
  foo = { foo: 'foo' }
307
291
  bar = { bar: 'bar' }
@@ -318,8 +302,9 @@ class AppDependenciesTest < Minitest::Test
318
302
  foo: foo,
319
303
  bar: bar
320
304
  )
305
+ @test_harness = Syntropy::TestHarness.new(@app)
321
306
 
322
- req = make_request(':method' => 'GET', ':path' => '/test/bar')
307
+ req = @test_harness.request(':method' => 'GET', ':path' => '/test/bar')
323
308
  assert_equal 'foobar', req.response_body
324
309
  assert_equal HTTP::OK, req.response_status
325
310
  end
data/test/test_caching.rb CHANGED
@@ -40,7 +40,7 @@ class CachingTest < Minitest::Test
40
40
  @app = Syntropy::App.new(**@env)
41
41
 
42
42
  @c_fd, @s_fd = make_socket_pair
43
- @adapter = Syntropy::HTTP::Connection.new(nil, @machine, @s_fd, @env) { @app.(it) }
43
+ @adapter = Syntropy::HTTP::ServerConnection.new(@machine, @s_fd, @env) { @app.(it) }
44
44
  end
45
45
 
46
46
  def teardown
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './helper'
4
+ require 'json'
5
+
6
+ class HTTPClientTest < Minitest::Test
7
+ def setup
8
+ @machine = UM.new
9
+ @handler = ->(req) { req.respond_json(req.headers) }
10
+
11
+ @port = 10000 + rand(30000)
12
+ @env = { bind: "127.0.0.1:#{@port}" }
13
+ @server = Syntropy::HTTP::Server.new(@machine, @env) { @app&.call(it) }
14
+ @server_fiber = @machine.spin { @server.run }
15
+
16
+ # let server spin and listen to incoming connections
17
+ @machine.sleep(0.01)
18
+
19
+ @client = Syntropy::HTTP::Client.new(@machine)
20
+ end
21
+
22
+ def teardown
23
+ @machine.schedule(@server_fiber, UM::Terminate.new)
24
+ @machine.join(@server_fiber)
25
+ end
26
+
27
+ def test_get
28
+ @app = ->(req) { req.respond('foo') }
29
+ headers, body = @client.get("http://localhost:#{@port}")
30
+
31
+ assert_kind_of Hash, headers
32
+ assert_equal Syntropy::HTTP::OK, headers[':status']
33
+
34
+ assert_kind_of String, body
35
+ assert_equal 'foo', body
36
+ end
37
+
38
+ def test_get_with_block
39
+ @app = ->(req) { req.respond('foo') }
40
+ headers = body = nil
41
+ @client.get("http://localhost:#{@port}") { |h, c|
42
+ headers = h
43
+ body = c.get_response_body(headers)
44
+ }
45
+
46
+ assert_kind_of Hash, headers
47
+ assert_equal Syntropy::HTTP::OK, headers[':status']
48
+
49
+ assert_kind_of String, body
50
+ assert_equal 'foo', body
51
+ end
52
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './helper'
4
+ require 'json'
5
+
6
+ class HTTPClientConectionTest < Minitest::Test
7
+ def setup
8
+ @client_fd, @server_fd = UM.socketpair(UM::AF_UNIX, UM::SOCK_STREAM, 0)
9
+ @machine = UM.new
10
+ @handler = ->(req) { req.respond_json(req.headers) }
11
+ @server_connection = Syntropy::HTTP::ServerConnection.new(
12
+ @machine, @server_fd, {}, &->(req) { @handler.(req) }
13
+ )
14
+ @server_fiber = @machine.spin { @server_connection.run }
15
+ @client_connection = Syntropy::HTTP::ClientConnection.new(
16
+ @machine, @client_fd
17
+ )
18
+ end
19
+
20
+ def teardown
21
+ @machine.schedule(@server_fiber, UM::Terminate.new)
22
+ @machine.join(@server_fiber)
23
+ end
24
+
25
+ def test_req_teapot
26
+ @handler = ->(req) { req.respond(nil, ':status' => Syntropy::HTTP::TEAPOT) }
27
+ headers = @client_connection.req(':method' => 'GET', ':path' => '/')
28
+
29
+ assert_kind_of Hash, headers
30
+ assert_equal Syntropy::HTTP::TEAPOT, headers[':status']
31
+ end
32
+
33
+ def test_req_with_response_body
34
+ @handler = ->(req) { req.respond('foo') }
35
+ headers = @client_connection.req(':method' => 'GET', ':path' => '/')
36
+
37
+ assert_kind_of Hash, headers
38
+ assert_equal Syntropy::HTTP::OK, headers[':status']
39
+
40
+ body = @client_connection.get_response_body(headers)
41
+ assert_equal 'foo', body
42
+ end
43
+ end
@@ -3,7 +3,7 @@
3
3
  require_relative './helper'
4
4
  require 'securerandom'
5
5
 
6
- class ConnectionTest < Minitest::Test
6
+ class HTTPServerConnectionTest < Minitest::Test
7
7
  def make_socket_pair
8
8
  port = SecureRandom.random_number(10000..40000)
9
9
  server_fd = @machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
@@ -29,7 +29,7 @@ class ConnectionTest < Minitest::Test
29
29
  @hook = nil
30
30
  @app = ->(req) { @reqs << req; @hook&.call(req) }
31
31
  @env = {}
32
- @adapter = Syntropy::HTTP::Connection.new(nil, @machine, @s_fd, @env, &@app)
32
+ @connection = Syntropy::HTTP::ServerConnection.new(@machine, @s_fd, @env, &@app)
33
33
  end
34
34
 
35
35
  def teardown
@@ -54,14 +54,14 @@ class ConnectionTest < Minitest::Test
54
54
 
55
55
  def test_http_unsupported_versions
56
56
  write_http_request "GET / HTTP/0.9\r\n\r\n"
57
- @adapter.serve_request
57
+ @connection.serve_request
58
58
  response = read_client_side
59
59
  assert_equal "HTTP/1.1 505\r\nTransfer-Encoding: chunked\r\n\r\n1a\r\nHTTP version not supported\r\n0\r\n\r\n", response
60
60
 
61
61
  setup
62
62
 
63
63
  write_http_request "GET / HTTP/1.0\r\n\r\n"
64
- @adapter.serve_request
64
+ @connection.serve_request
65
65
  response = read_client_side
66
66
  assert_equal "HTTP/1.1 505\r\nTransfer-Encoding: chunked\r\n\r\n1a\r\nHTTP version not supported\r\n0\r\n\r\n", response
67
67
 
@@ -69,7 +69,7 @@ class ConnectionTest < Minitest::Test
69
69
 
70
70
  @hook = ->(req) { req.respond('hi') }
71
71
  write_http_request "GET / HTTP/1.1\r\n\r\n"
72
- @adapter.serve_request
72
+ @connection.serve_request
73
73
  @machine.close(@s_fd)
74
74
  response = read_client_side
75
75
  assert_equal "HTTP/1.1 200\r\nTransfer-Encoding: chunked\r\n\r\n2\r\nhi\r\n0\r\n\r\n", response
@@ -78,7 +78,7 @@ class ConnectionTest < Minitest::Test
78
78
  def test_basic_request_parsing
79
79
  write_http_request "GET / HTTP/1.1\r\n\r\n"
80
80
 
81
- @adapter.serve_request
81
+ @connection.serve_request
82
82
  assert_equal 1, @reqs.size
83
83
  req = @reqs.shift
84
84
  headers = req.headers
@@ -101,7 +101,7 @@ class ConnectionTest < Minitest::Test
101
101
  HTTP
102
102
  write_http_request msg
103
103
 
104
- @adapter.run
104
+ @connection.run
105
105
  assert_equal 2, @reqs.size
106
106
  req0 = @reqs.shift
107
107
  headers = req0.headers
@@ -137,7 +137,7 @@ class ConnectionTest < Minitest::Test
137
137
  @bodies = []
138
138
  @hook = ->(req) { @bodies << req.read }
139
139
 
140
- @adapter.run
140
+ @connection.run
141
141
  assert_equal 2, @reqs.size
142
142
 
143
143
  req0 = @reqs.shift
@@ -195,7 +195,7 @@ class ConnectionTest < Minitest::Test
195
195
  @bodies = []
196
196
  @hook = ->(req) { @bodies << req.read }
197
197
 
198
- @adapter.run
198
+ @connection.run
199
199
  assert_equal 2, @reqs.size
200
200
 
201
201
  req0 = @reqs.shift
@@ -247,7 +247,7 @@ class ConnectionTest < Minitest::Test
247
247
  chunks = []
248
248
  @hook = ->(req) { req.each_chunk { chunks << it } }
249
249
 
250
- @adapter.serve_request
250
+ @connection.serve_request
251
251
  assert_equal 1, @reqs.size
252
252
 
253
253
  req0 = @reqs.shift
@@ -263,7 +263,7 @@ class ConnectionTest < Minitest::Test
263
263
  assert_equal ['abc', 'de'], chunks
264
264
 
265
265
  chunks.clear
266
- @adapter.serve_request
266
+ @connection.serve_request
267
267
  assert_equal 1, @reqs.size
268
268
 
269
269
  req1 = @reqs.shift
@@ -285,7 +285,7 @@ class ConnectionTest < Minitest::Test
285
285
  }
286
286
 
287
287
  write_http_request "GET / HTTP/1.1\r\n\r\n"
288
- @adapter.run
288
+ @connection.run
289
289
  response = read_client_side
290
290
 
291
291
  expected = <<~HTTP.crlf_lines
@@ -305,7 +305,7 @@ class ConnectionTest < Minitest::Test
305
305
 
306
306
  # using HTTP 1.0, server should close connection after responding
307
307
  write_http_request "GET / HTTP/1.1\r\n\r\n"
308
- @adapter.run
308
+ @connection.run
309
309
 
310
310
  response = read_client_side
311
311
  expected = "HTTP/1.1 200\r\nTransfer-Encoding: chunked\r\n\r\nd\r\nHello, world!\r\n0\r\n\r\n"
@@ -318,14 +318,14 @@ class ConnectionTest < Minitest::Test
318
318
  }
319
319
 
320
320
  write_http_request "GET / HTTP/1.1\r\nConnection: close\r\n\r\n", false
321
- res = @adapter.serve_request
321
+ res = @connection.serve_request
322
322
  assert_equal false, res
323
323
 
324
324
  response = read_client_side
325
325
  assert_equal("HTTP/1.1 200\r\nTransfer-Encoding: chunked\r\n\r\n2\r\nHi\r\n0\r\n\r\n", response)
326
326
 
327
327
  write_http_request "GET / HTTP/1.1\r\n\r\n", false
328
- res = @adapter.serve_request
328
+ res = @connection.serve_request
329
329
  assert_equal true, res
330
330
 
331
331
  response = read_client_side
@@ -344,7 +344,7 @@ class ConnectionTest < Minitest::Test
344
344
  }
345
345
 
346
346
  write_http_request "GET / HTTP/1.1\r\n\r\nGET / HTTP/1.1\r\nFoo: bar\r\n\r\n"
347
- @adapter.run
347
+ @connection.run
348
348
  response = read_client_side
349
349
 
350
350
  expected = "HTTP/1.1 200\r\nTransfer-Encoding: chunked\r\n\r\nd\r\nHello, world!\r\n0\r\n\r\n" +
@@ -368,7 +368,7 @@ class ConnectionTest < Minitest::Test
368
368
 
369
369
  msg = "POST / HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n6\r\nfoobar\r\n"
370
370
  write_http_request msg, false
371
- @machine.spin { @adapter.serve_request rescue nil }
371
+ @machine.spin { @connection.serve_request rescue nil }
372
372
  @machine.sleep(0.01)
373
373
 
374
374
  assert request
@@ -417,7 +417,7 @@ class ConnectionTest < Minitest::Test
417
417
 
418
418
  msg = "GET / HTTP/1.1\r\nUpgrade: echo\r\nConnection: upgrade\r\n\r\n"
419
419
  write_http_request(msg, false)
420
- @machine.spin { @adapter.serve_request rescue nil }
420
+ @machine.spin { @connection.serve_request rescue nil }
421
421
  @machine.sleep(0.01)
422
422
 
423
423
  response = read_client_side
@@ -462,7 +462,7 @@ class ConnectionTest < Minitest::Test
462
462
 
463
463
  write_client_side("GET / HTTP/1.1\r\n\r\n")
464
464
  @machine.spin do
465
- @adapter.serve_request
465
+ @connection.serve_request
466
466
  rescue => e
467
467
  p e
468
468
  p e.backtrace
@@ -498,7 +498,7 @@ class ConnectionTest < Minitest::Test
498
498
 
499
499
  write_client_side("GET / HTTP/1.1\r\n\r\n")
500
500
  @machine.spin do
501
- @adapter.serve_request
501
+ @connection.serve_request
502
502
  rescue => e
503
503
  p e
504
504
  p e.backtrace
@@ -531,7 +531,7 @@ class ConnectionTest < Minitest::Test
531
531
  count = 0
532
532
 
533
533
  write_client_side("GET / HTTP/1.1\r\n\r\n")
534
- @machine.spin { @adapter.serve_request }
534
+ @machine.spin { @connection.serve_request }
535
535
 
536
536
  while (data = read_client_side(65536))
537
537
  response << data
@@ -551,7 +551,7 @@ class ConnectionTest < Minitest::Test
551
551
  end
552
552
 
553
553
  write_client_side("GET / HTTP/1.1\r\n\r\n")
554
- @adapter.serve_request
554
+ @connection.serve_request
555
555
  response = read_client_side(65536)
556
556
  expected = "HTTP/1.1 200\r\nTransfer-Encoding: chunked\r\nServer: Syntropy\r\n\r\n3\r\nfoo\r\n0\r\n\r\n"
557
557
  assert_equal expected, response
@@ -559,7 +559,7 @@ class ConnectionTest < Minitest::Test
559
559
  @env[:server_headers] = "Server: TP3\r\n"
560
560
 
561
561
  write_client_side("GET / HTTP/1.1\r\n\r\n")
562
- @adapter.serve_request
562
+ @connection.serve_request
563
563
  response = read_client_side(65536)
564
564
  expected = "HTTP/1.1 200\r\nTransfer-Encoding: chunked\r\nServer: TP3\r\n\r\n3\r\nfoo\r\n0\r\n\r\n"
565
565
  assert_equal expected, response
@@ -572,7 +572,7 @@ class ConnectionTest < Minitest::Test
572
572
  }
573
573
 
574
574
  write_client_side("GET / HTTP/1.1\r\n\r\n")
575
- @adapter.serve_request
575
+ @connection.serve_request
576
576
  response = read_client_side(65536)
577
577
  expected = "HTTP/1.1 200\r\nTransfer-Encoding: chunked\r\nSet-Cookie: foo=bar\r\n\r\n3\r\nfoo\r\n0\r\n\r\n"
578
578
  assert_equal expected, response
@@ -583,7 +583,7 @@ class ConnectionTest < Minitest::Test
583
583
  }
584
584
 
585
585
  write_client_side("GET / HTTP/1.1\r\n\r\n")
586
- @adapter.serve_request
586
+ @connection.serve_request
587
587
  response = read_client_side(65536)
588
588
  expected = "HTTP/1.1 200\r\nTransfer-Encoding: chunked\r\nSet-Cookie: foo=bar\r\nContent-Type: text/plain\r\n\r\n3\r\nfoo\r\n0\r\n\r\n"
589
589
  assert_equal expected, response
@@ -597,7 +597,7 @@ class ConnectionTest < Minitest::Test
597
597
  }
598
598
 
599
599
  write_client_side("GET / HTTP/1.1\r\n\r\n")
600
- @adapter.serve_request
600
+ @connection.serve_request
601
601
  response = read_client_side(65536)
602
602
  expected = "HTTP/1.1 200\r\nTransfer-Encoding: chunked\r\nSet-Cookie: foo=bar\r\nFoo: bar\r\nContent-Type: text/plain\r\n\r\n3\r\nfoo\r\n0\r\n\r\n"
603
603
  assert_equal expected, response
@@ -610,7 +610,7 @@ class ConnectionTest < Minitest::Test
610
610
  }
611
611
 
612
612
  write_client_side("GET / HTTP/1.1\r\n\r\n")
613
- @adapter.serve_request
613
+ @connection.serve_request
614
614
  response = read_client_side(65536)
615
615
  expected = "HTTP/1.1 200\r\nTransfer-Encoding: chunked\r\nSet-Cookie: foo=bar; HttpOnly\r\n\r\n3\r\nfoo\r\n0\r\n\r\n"
616
616
  assert_equal expected, response
@@ -624,7 +624,7 @@ class ConnectionTest < Minitest::Test
624
624
  }
625
625
 
626
626
  write_client_side("GET / HTTP/1.1\r\n\r\n")
627
- @adapter.serve_request
627
+ @connection.serve_request
628
628
  response = read_client_side(65536)
629
629
  expected = "HTTP/1.1 200\r\nTransfer-Encoding: chunked\r\nSet-Cookie: foo=bar; HttpOnly\r\nSet-Cookie: bar=baz\r\n\r\n3\r\nfoo\r\n0\r\n\r\n"
630
630
  assert_equal expected, response
@@ -640,7 +640,7 @@ class ConnectionTest < Minitest::Test
640
640
  }
641
641
 
642
642
  write_client_side("GET / HTTP/1.1\r\n\r\n")
643
- @adapter.serve_request
643
+ @connection.serve_request
644
644
  response = read_client_side(65536)
645
645
  expected = "HTTP/1.1 200\r\nTransfer-Encoding: chunked\r\nSet-Cookie: a=1\r\nSet-Cookie: b=2\r\nSet-Cookie: c=3\r\nSet-Cookie: d=4\r\nSet-Cookie: e=5\r\n\r\n3\r\nfoo\r\n0\r\n\r\n"
646
646
  assert_equal expected, response
@@ -28,7 +28,7 @@ class JSONAPITest < Minitest::Test
28
28
  req = mock_req(':method' => 'GET', ':path' => '/?q=foo')
29
29
  @app.call(req)
30
30
  assert_equal HTTP::OK, req.response_status
31
- assert_equal({ status: 'OK', response: nil }, req.response_json)
31
+ assert_equal({ 'status' => 'OK', 'response' => nil }, req.response_json)
32
32
 
33
33
  req = mock_req(':method' => 'POST', ':path' => '/?q=foo')
34
34
  @app.call(req)
@@ -38,7 +38,7 @@ class JSONAPITest < Minitest::Test
38
38
  req = mock_req(':method' => 'POST', ':path' => '/?q=bar&v=foo')
39
39
  @app.call(req)
40
40
  assert_equal HTTP::OK, req.response_status
41
- assert_equal({ status: 'OK', response: true }, req.response_json)
41
+ assert_equal({ 'status' => 'OK', 'response' => true }, req.response_json)
42
42
 
43
43
  req = mock_req(':method' => 'GET', ':path' => '/?q=bar&v=foo')
44
44
  @app.call(req)
@@ -47,12 +47,12 @@ class JSONAPITest < Minitest::Test
47
47
  req = mock_req(':method' => 'GET', ':path' => '/?q=foo')
48
48
  @app.call(req)
49
49
  assert_equal HTTP::OK, req.response_status
50
- assert_equal({ status: 'OK', response: 'foo' }, req.response_json)
50
+ assert_equal({ 'status' => 'OK', 'response' => 'foo' }, req.response_json)
51
51
 
52
52
  req = mock_req(':method' => 'GET', ':path' => '/?q=foo')
53
53
  @app.call(req)
54
54
  assert_equal HTTP::OK, req.response_status
55
- assert_equal({ status: 'OK', response: 'foo' }, req.response_json)
55
+ assert_equal({ 'status' => 'OK', 'response' => 'foo' }, req.response_json)
56
56
 
57
57
  req = mock_req(':method' => 'GET', ':path' => '/?q=xxx')
58
58
  @app.call(req)