workos 7.1.3 → 8.0.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.
- checksums.yaml +4 -4
- data/.github/workflows/docs.yml +46 -0
- data/.github/workflows/release-please.yml +1 -2
- data/.gitignore +2 -0
- data/.last-synced-sha +1 -1
- data/.oagen-manifest.json +61 -40
- data/.release-please-manifest.json +1 -1
- data/.yardopts +6 -0
- data/CHANGELOG.md +25 -3
- data/Gemfile +6 -0
- data/Gemfile.lock +33 -2
- data/lib/workos/api_keys/api_key.rb +1 -1
- data/lib/workos/api_keys/api_key_created_data.rb +1 -1
- data/lib/workos/api_keys/organization_api_key.rb +43 -0
- data/lib/workos/{types/events_order.rb → api_keys/organization_api_key_owner.rb} +1 -3
- data/lib/workos/api_keys/organization_api_key_with_value.rb +46 -0
- data/lib/workos/{types/audit_logs_order.rb → api_keys/organization_api_key_with_value_owner.rb} +1 -3
- data/lib/workos/api_keys.rb +46 -46
- data/lib/workos/audit_logs.rb +4 -4
- data/lib/workos/authorization/user_organization_membership_base_list_data.rb +5 -2
- data/lib/workos/authorization/{role_assignment.rb → user_role_assignment.rb} +5 -2
- data/lib/workos/authorization/{role_assignment_resource.rb → user_role_assignment_resource.rb} +1 -1
- data/lib/workos/authorization.rb +122 -22
- data/lib/workos/base_client.rb +1 -14
- data/lib/workos/client.rb +4 -4
- data/lib/workos/connect.rb +2 -2
- data/lib/workos/directory_sync/directory_user.rb +3 -0
- data/lib/workos/directory_sync/directory_user_with_groups.rb +4 -1
- data/lib/workos/directory_sync/dsync_user_updated_data.rb +3 -0
- data/lib/workos/directory_sync.rb +6 -6
- data/lib/workos/events.rb +2 -2
- data/lib/workos/feature_flags.rb +6 -6
- data/lib/workos/groups.rb +4 -4
- data/lib/workos/multi_factor_auth.rb +2 -2
- data/lib/workos/organizations.rb +2 -2
- data/lib/workos/sso/profile.rb +3 -0
- data/lib/workos/sso.rb +2 -2
- data/lib/workos/types/event_context_actor_source.rb +2 -1
- data/lib/workos/types/{applications_order.rb → pagination_order.rb} +1 -1
- data/lib/workos/types/{vault_byok_key_verification_completed_data_key_provider.rb → vault_byok_key_provider.rb} +1 -1
- data/lib/workos/user_management/create_user_api_key.rb +25 -0
- data/lib/workos/user_management/organization_membership.rb +5 -2
- data/lib/workos/user_management/user_api_key.rb +43 -0
- data/lib/workos/user_management/user_api_key_created_data_owner.rb +25 -0
- data/lib/workos/{api_keys/api_key_with_value_owner.rb → user_management/user_api_key_owner.rb} +1 -1
- data/lib/workos/{types/webhooks_order.rb → user_management/user_api_key_revoked_data_owner.rb} +1 -3
- data/lib/workos/{api_keys/api_key_with_value.rb → user_management/user_api_key_with_value.rb} +2 -2
- data/lib/workos/{types/groups_order.rb → user_management/user_api_key_with_value_owner.rb} +1 -3
- data/lib/workos/user_management/user_organization_membership.rb +5 -2
- data/lib/workos/user_management.rb +107 -10
- data/lib/workos/user_management_organization_membership_groups.rb +2 -2
- data/lib/workos/vault/vault_byok_key_deleted.rb +34 -0
- data/lib/workos/vault/vault_byok_key_deleted_data.rb +22 -0
- data/lib/workos/version.rb +1 -1
- data/lib/workos/webhooks.rb +2 -2
- data/rbi/workos/api_key.rbi +2 -2
- data/rbi/workos/api_key_created_data.rbi +2 -2
- data/rbi/workos/api_key_revoked_data.rbi +2 -2
- data/rbi/workos/api_keys.rbi +17 -17
- data/rbi/workos/authorization.rbi +27 -1
- data/rbi/workos/client.rbi +3 -3
- data/rbi/workos/create_user_api_key.rbi +36 -0
- data/rbi/workos/directory_user.rbi +6 -0
- data/rbi/workos/directory_user_with_groups.rbi +6 -0
- data/rbi/workos/dsync_user_updated_data.rbi +6 -0
- data/rbi/workos/organization_api_key.rbi +72 -0
- data/rbi/workos/{api_key_with_value_owner.rbi → organization_api_key_owner.rbi} +1 -1
- data/rbi/workos/organization_api_key_with_value.rbi +78 -0
- data/rbi/workos/organization_api_key_with_value_owner.rbi +30 -0
- data/rbi/workos/organization_membership.rbi +6 -0
- data/rbi/workos/profile.rbi +6 -0
- data/rbi/workos/user_api_key.rbi +72 -0
- data/rbi/workos/user_api_key_created_data_owner.rbi +36 -0
- data/rbi/workos/user_api_key_owner.rbi +36 -0
- data/rbi/workos/user_api_key_revoked_data_owner.rbi +36 -0
- data/rbi/workos/{api_key_with_value.rbi → user_api_key_with_value.rbi} +3 -3
- data/rbi/workos/user_api_key_with_value_owner.rbi +36 -0
- data/rbi/workos/user_management.rbi +31 -0
- data/rbi/workos/user_organization_membership.rbi +6 -0
- data/rbi/workos/user_organization_membership_base_list_data.rbi +6 -0
- data/rbi/workos/{role_assignment.rbi → user_role_assignment.rbi} +9 -3
- data/rbi/workos/{role_assignment_resource.rbi → user_role_assignment_resource.rbi} +1 -1
- data/rbi/workos/vault_byok_key_deleted.rbi +54 -0
- data/rbi/workos/vault_byok_key_deleted_data.rbi +30 -0
- data/script/docs +16 -0
- data/script/docs-serve +12 -0
- data/script/llms-txt +37 -0
- data/test/workos/test_api_keys.rb +17 -17
- data/test/workos/test_authorization.rb +16 -0
- data/test/workos/test_base_client.rb +0 -163
- data/test/workos/test_model_round_trip.rb +278 -83
- data/test/workos/test_user_management.rb +25 -1
- metadata +39 -33
- data/lib/workos/types/authorization_order.rb +0 -9
- data/lib/workos/types/connections_order.rb +0 -9
- data/lib/workos/types/directories_order.rb +0 -9
- data/lib/workos/types/directory_groups_order.rb +0 -9
- data/lib/workos/types/directory_users_order.rb +0 -9
- data/lib/workos/types/feature_flags_order.rb +0 -9
- data/lib/workos/types/organizations_api_keys_order.rb +0 -9
- data/lib/workos/types/organizations_feature_flags_order.rb +0 -9
- data/lib/workos/types/organizations_order.rb +0 -9
- data/lib/workos/types/permissions_order.rb +0 -9
- data/lib/workos/types/user_management_invitations_order.rb +0 -9
- data/lib/workos/types/user_management_multi_factor_authentication_order.rb +0 -9
- data/lib/workos/types/user_management_organization_membership_groups_order.rb +0 -9
- data/lib/workos/types/user_management_organization_membership_order.rb +0 -9
- data/lib/workos/types/user_management_users_authorized_applications_order.rb +0 -9
- data/lib/workos/types/user_management_users_feature_flags_order.rb +0 -9
- data/lib/workos/types/user_management_users_order.rb +0 -9
|
@@ -11,20 +11,6 @@ class ApiKeysTest < Minitest::Test
|
|
|
11
11
|
@client = WorkOS::Client.new(api_key: "sk_test_123")
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def test_create_validation_returns_expected_result
|
|
15
|
-
stub_request(:post, %r{\Ahttps://api\.workos\.com/api_keys/validations(\?|\z)})
|
|
16
|
-
.to_return(body: "{}", status: 200)
|
|
17
|
-
result = @client.api_keys.create_validation(value: "stub")
|
|
18
|
-
refute_nil result
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def test_delete_api_key_returns_expected_result
|
|
22
|
-
stub_request(:delete, %r{\Ahttps://api\.workos\.com/api_keys/stub(\?|\z)})
|
|
23
|
-
.to_return(body: "{}", status: 200)
|
|
24
|
-
result = @client.api_keys.delete_api_key(id: "stub")
|
|
25
|
-
assert_nil result
|
|
26
|
-
end
|
|
27
|
-
|
|
28
14
|
def test_list_organization_api_keys_returns_expected_result
|
|
29
15
|
stub_request(:get, %r{\Ahttps://api\.workos\.com/organizations/stub/api_keys(\?|\z)})
|
|
30
16
|
.to_return(body: '{"data": [], "list_metadata": {}}', status: 200)
|
|
@@ -39,12 +25,26 @@ class ApiKeysTest < Minitest::Test
|
|
|
39
25
|
refute_nil result
|
|
40
26
|
end
|
|
41
27
|
|
|
28
|
+
def test_create_validation_returns_expected_result
|
|
29
|
+
stub_request(:post, %r{\Ahttps://api\.workos\.com/api_keys/validations(\?|\z)})
|
|
30
|
+
.to_return(body: "{}", status: 200)
|
|
31
|
+
result = @client.api_keys.create_validation(value: "stub")
|
|
32
|
+
refute_nil result
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def test_delete_api_key_returns_expected_result
|
|
36
|
+
stub_request(:delete, %r{\Ahttps://api\.workos\.com/api_keys/stub(\?|\z)})
|
|
37
|
+
.to_return(body: "{}", status: 200)
|
|
38
|
+
result = @client.api_keys.delete_api_key(id: "stub")
|
|
39
|
+
assert_nil result
|
|
40
|
+
end
|
|
41
|
+
|
|
42
42
|
# Parameterized authentication error tests (one per endpoint).
|
|
43
43
|
[
|
|
44
|
-
{name: :create_validation, verb: :post, url: %r{\Ahttps://api\.workos\.com/api_keys/validations(\?|\z)}, args: {value: "stub"}},
|
|
45
|
-
{name: :delete_api_key, verb: :delete, url: %r{\Ahttps://api\.workos\.com/api_keys/stub(\?|\z)}, args: {id: "stub"}},
|
|
46
44
|
{name: :list_organization_api_keys, verb: :get, url: %r{\Ahttps://api\.workos\.com/organizations/stub/api_keys(\?|\z)}, args: {organization_id: "stub"}},
|
|
47
|
-
{name: :create_organization_api_key, verb: :post, url: %r{\Ahttps://api\.workos\.com/organizations/stub/api_keys(\?|\z)}, args: {organization_id: "stub", name: "stub"}}
|
|
45
|
+
{name: :create_organization_api_key, verb: :post, url: %r{\Ahttps://api\.workos\.com/organizations/stub/api_keys(\?|\z)}, args: {organization_id: "stub", name: "stub"}},
|
|
46
|
+
{name: :create_validation, verb: :post, url: %r{\Ahttps://api\.workos\.com/api_keys/validations(\?|\z)}, args: {value: "stub"}},
|
|
47
|
+
{name: :delete_api_key, verb: :delete, url: %r{\Ahttps://api\.workos\.com/api_keys/stub(\?|\z)}, args: {id: "stub"}}
|
|
48
48
|
].each do |spec|
|
|
49
49
|
define_method("test_#{spec[:name]}_raises_authentication_error_on_401") do
|
|
50
50
|
stub_request(spec[:verb], spec[:url])
|
|
@@ -192,6 +192,13 @@ class AuthorizationTest < Minitest::Test
|
|
|
192
192
|
assert_kind_of WorkOS::Types::ListStruct, result
|
|
193
193
|
end
|
|
194
194
|
|
|
195
|
+
def test_list_role_assignments_for_resource_by_external_id_returns_expected_result
|
|
196
|
+
stub_request(:get, %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/resources/stub/stub/role_assignments(\?|\z)})
|
|
197
|
+
.to_return(body: '{"data": [], "list_metadata": {}}', status: 200)
|
|
198
|
+
result = @client.authorization.list_role_assignments_for_resource_by_external_id(organization_id: "stub", resource_type_slug: "stub", external_id: "stub")
|
|
199
|
+
assert_kind_of WorkOS::Types::ListStruct, result
|
|
200
|
+
end
|
|
201
|
+
|
|
195
202
|
def test_list_resources_returns_expected_result
|
|
196
203
|
stub_request(:get, %r{\Ahttps://api\.workos\.com/authorization/resources(\?|\z)})
|
|
197
204
|
.to_return(body: '{"data": [], "list_metadata": {}}', status: 200)
|
|
@@ -259,6 +266,13 @@ class AuthorizationTest < Minitest::Test
|
|
|
259
266
|
assert_kind_of WorkOS::Types::ListStruct, result
|
|
260
267
|
end
|
|
261
268
|
|
|
269
|
+
def test_list_role_assignments_for_resource_returns_expected_result
|
|
270
|
+
stub_request(:get, %r{\Ahttps://api\.workos\.com/authorization/resources/stub/role_assignments(\?|\z)})
|
|
271
|
+
.to_return(body: '{"data": [], "list_metadata": {}}', status: 200)
|
|
272
|
+
result = @client.authorization.list_role_assignments_for_resource(resource_id: "stub")
|
|
273
|
+
assert_kind_of WorkOS::Types::ListStruct, result
|
|
274
|
+
end
|
|
275
|
+
|
|
262
276
|
def test_list_environment_roles_returns_expected_result
|
|
263
277
|
stub_request(:get, %r{\Ahttps://api\.workos\.com/authorization/roles(\?|\z)})
|
|
264
278
|
.to_return(body: "{}", status: 200)
|
|
@@ -358,12 +372,14 @@ class AuthorizationTest < Minitest::Test
|
|
|
358
372
|
{name: :update_resource_by_external_id, verb: :patch, url: %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/resources/stub/stub(\?|\z)}, args: {organization_id: "stub", resource_type_slug: "stub", external_id: "stub", parent_resource: WorkOS::Authorization::ParentResourceById.new(parent_resource_id: "stub")}},
|
|
359
373
|
{name: :delete_resource_by_external_id, verb: :delete, url: %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/resources/stub/stub(\?|\z)}, args: {organization_id: "stub", resource_type_slug: "stub", external_id: "stub"}},
|
|
360
374
|
{name: :list_memberships_for_resource_by_external_id, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/resources/stub/stub/organization_memberships(\?|\z)}, args: {organization_id: "stub", resource_type_slug: "stub", external_id: "stub", permission_slug: "stub"}},
|
|
375
|
+
{name: :list_role_assignments_for_resource_by_external_id, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/resources/stub/stub/role_assignments(\?|\z)}, args: {organization_id: "stub", resource_type_slug: "stub", external_id: "stub"}},
|
|
361
376
|
{name: :list_resources, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/resources(\?|\z)}, args: {parent: WorkOS::Authorization::ParentById.new(parent_resource_id: "stub")}},
|
|
362
377
|
{name: :create_resource, verb: :post, url: %r{\Ahttps://api\.workos\.com/authorization/resources(\?|\z)}, args: {external_id: "stub", name: "stub", resource_type_slug: "stub", organization_id: "stub", parent_resource: WorkOS::Authorization::ParentResourceById.new(parent_resource_id: "stub")}},
|
|
363
378
|
{name: :get_resource, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/resources/stub(\?|\z)}, args: {resource_id: "stub"}},
|
|
364
379
|
{name: :update_resource, verb: :patch, url: %r{\Ahttps://api\.workos\.com/authorization/resources/stub(\?|\z)}, args: {resource_id: "stub", parent_resource: WorkOS::Authorization::ParentResourceById.new(parent_resource_id: "stub")}},
|
|
365
380
|
{name: :delete_resource, verb: :delete, url: %r{\Ahttps://api\.workos\.com/authorization/resources/stub(\?|\z)}, args: {resource_id: "stub"}},
|
|
366
381
|
{name: :list_memberships_for_resource, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/resources/stub/organization_memberships(\?|\z)}, args: {resource_id: "stub", permission_slug: "stub"}},
|
|
382
|
+
{name: :list_role_assignments_for_resource, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/resources/stub/role_assignments(\?|\z)}, args: {resource_id: "stub"}},
|
|
367
383
|
{name: :list_environment_roles, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/roles(\?|\z)}},
|
|
368
384
|
{name: :create_environment_role, verb: :post, url: %r{\Ahttps://api\.workos\.com/authorization/roles(\?|\z)}, args: {slug: "stub", name: "stub"}},
|
|
369
385
|
{name: :get_environment_role, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/roles/stub(\?|\z)}, args: {slug: "stub"}},
|
|
@@ -82,36 +82,10 @@ class BaseClientTest < Minitest::Test
|
|
|
82
82
|
end
|
|
83
83
|
end
|
|
84
84
|
|
|
85
|
-
# A pooled connection that either returns a canned response or raises when
|
|
86
|
-
# driven, so execute_request can be exercised without real TCP+TLS.
|
|
87
|
-
class StubConnection < FakeConnection
|
|
88
|
-
attr_accessor :read_timeout, :open_timeout
|
|
89
|
-
|
|
90
|
-
def initialize(response: nil, error: nil, **kwargs)
|
|
91
|
-
super(**kwargs)
|
|
92
|
-
@response = response
|
|
93
|
-
@error = error
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def request(_request)
|
|
97
|
-
raise @error if @error
|
|
98
|
-
|
|
99
|
-
@response
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
|
|
103
85
|
def setup
|
|
104
86
|
@client = WorkOS::BaseClient.new(api_key: "sk_test_123", max_retries: 1)
|
|
105
87
|
end
|
|
106
88
|
|
|
107
|
-
def teardown
|
|
108
|
-
super
|
|
109
|
-
# Close any open connections and clear the fiber-local cache to avoid
|
|
110
|
-
# leaking pooled connections between tests.
|
|
111
|
-
@client.shutdown
|
|
112
|
-
Fiber[:workos_connections] = nil
|
|
113
|
-
end
|
|
114
|
-
|
|
115
89
|
def test_request_dispatches_known_methods
|
|
116
90
|
client = RecordingClient.new(api_key: "sk_test_123")
|
|
117
91
|
|
|
@@ -196,141 +170,4 @@ class BaseClientTest < Minitest::Test
|
|
|
196
170
|
assert evict.finished
|
|
197
171
|
refute keep.finished
|
|
198
172
|
end
|
|
199
|
-
|
|
200
|
-
# An exception execute_request's rescue clause doesn't list still leaves the
|
|
201
|
-
# socket mid-stream, so the connection must not survive in the pool for the
|
|
202
|
-
# next request on this thread to pick up.
|
|
203
|
-
def test_unlisted_request_error_evicts_the_pooled_connection
|
|
204
|
-
conn = StubConnection.new(error: Net::HTTPBadResponse.new("wrong version"))
|
|
205
|
-
cache = @client.send(:thread_connections)
|
|
206
|
-
cache["https:api.workos.com:443:30"] = conn
|
|
207
|
-
|
|
208
|
-
assert_raises(Net::HTTPBadResponse) do
|
|
209
|
-
@client.execute_request(request: Net::HTTP::Get.new("/things"))
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
refute cache.key?("https:api.workos.com:443:30"),
|
|
213
|
-
"a connection whose request did not complete must not stay pooled"
|
|
214
|
-
assert conn.finished
|
|
215
|
-
end
|
|
216
|
-
|
|
217
|
-
def test_completed_request_keeps_the_connection_pooled
|
|
218
|
-
conn = StubConnection.new(response: Net::HTTPOK.new("1.1", "200", "OK"))
|
|
219
|
-
cache = @client.send(:thread_connections)
|
|
220
|
-
cache["https:api.workos.com:443:30"] = conn
|
|
221
|
-
|
|
222
|
-
@client.execute_request(request: Net::HTTP::Get.new("/things"))
|
|
223
|
-
|
|
224
|
-
assert cache.key?("https:api.workos.com:443:30")
|
|
225
|
-
refute conn.finished
|
|
226
|
-
end
|
|
227
|
-
|
|
228
|
-
# Raised asynchronously into the worker thread to stand in for a caller-side
|
|
229
|
-
# abort: Timeout.timeout, Thread#kill, a signal handler unwinding the stack.
|
|
230
|
-
# It descends from Exception rather than StandardError so that nothing in
|
|
231
|
-
# execute_request can catch it — the `ensure` is the only cleanup that runs.
|
|
232
|
-
class AbortSignal < Exception; end # standard:disable Lint/InheritException
|
|
233
|
-
|
|
234
|
-
# End-to-end regression test over a real keep-alive socket, for the failure
|
|
235
|
-
# the eviction actually prevents: request one is abandoned mid-flight, the
|
|
236
|
-
# server then writes response one onto that socket, and request two on the
|
|
237
|
-
# same thread reads those stale bytes as if they were its own response.
|
|
238
|
-
#
|
|
239
|
-
# Before the fix, request two sees marker "one" (or a mangled response) off
|
|
240
|
-
# the pooled socket. After it, the abandoned socket is closed and the server
|
|
241
|
-
# accepts a fresh connection for request two.
|
|
242
|
-
def test_aborted_request_does_not_leak_its_response_to_the_next_request
|
|
243
|
-
WebMock.disable!
|
|
244
|
-
server = TCPServer.new("127.0.0.1", 0)
|
|
245
|
-
port = server.addr[1]
|
|
246
|
-
client = WorkOS::BaseClient.new(
|
|
247
|
-
api_key: "sk_test_123",
|
|
248
|
-
base_url: "http://127.0.0.1:#{port}",
|
|
249
|
-
timeout: 5,
|
|
250
|
-
max_retries: 0
|
|
251
|
-
)
|
|
252
|
-
|
|
253
|
-
request_one_read = Queue.new
|
|
254
|
-
release_response_one = Queue.new
|
|
255
|
-
response_one_written = Queue.new
|
|
256
|
-
aborted = Queue.new
|
|
257
|
-
connections = Queue.new
|
|
258
|
-
|
|
259
|
-
server_thread = Thread.new do
|
|
260
|
-
# Connection one: read the request, then hold the response back until
|
|
261
|
-
# the client has been aborted and has unwound.
|
|
262
|
-
first = server.accept
|
|
263
|
-
connections << first
|
|
264
|
-
read_http_request(first)
|
|
265
|
-
request_one_read << true
|
|
266
|
-
release_response_one.pop
|
|
267
|
-
begin
|
|
268
|
-
write_http_response(first, {marker: "one"})
|
|
269
|
-
rescue Errno::EPIPE, Errno::ECONNRESET, IOError
|
|
270
|
-
# Expected once the fix closes the abandoned socket.
|
|
271
|
-
end
|
|
272
|
-
response_one_written << true
|
|
273
|
-
|
|
274
|
-
# Connection two: a fresh accept, which only completes because the
|
|
275
|
-
# client did not reuse the socket above.
|
|
276
|
-
second = server.accept
|
|
277
|
-
connections << second
|
|
278
|
-
read_http_request(second)
|
|
279
|
-
write_http_response(second, {marker: "two"})
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
worker = Thread.new do
|
|
283
|
-
begin
|
|
284
|
-
client.execute_request(request: Net::HTTP::Get.new("/one"))
|
|
285
|
-
rescue AbortSignal
|
|
286
|
-
# The caller unwinds but the thread survives and goes on to serve more
|
|
287
|
-
# work, the way a Puma or Solid Queue worker does. execute_request's
|
|
288
|
-
# `ensure` has already run by the time this body executes.
|
|
289
|
-
aborted << true
|
|
290
|
-
response_one_written.pop
|
|
291
|
-
end
|
|
292
|
-
response = client.execute_request(request: Net::HTTP::Get.new("/two"))
|
|
293
|
-
JSON.parse(response.body)["marker"]
|
|
294
|
-
end
|
|
295
|
-
|
|
296
|
-
marker = Timeout.timeout(15) do
|
|
297
|
-
request_one_read.pop
|
|
298
|
-
worker.raise(AbortSignal)
|
|
299
|
-
aborted.pop
|
|
300
|
-
release_response_one << true
|
|
301
|
-
worker.value
|
|
302
|
-
end
|
|
303
|
-
|
|
304
|
-
assert_equal "two", marker,
|
|
305
|
-
"request two read the abandoned socket's response instead of its own"
|
|
306
|
-
ensure
|
|
307
|
-
server_thread&.kill
|
|
308
|
-
worker&.kill
|
|
309
|
-
until connections.nil? || connections.empty?
|
|
310
|
-
socket = connections.pop
|
|
311
|
-
socket.close unless socket.closed?
|
|
312
|
-
end
|
|
313
|
-
server&.close
|
|
314
|
-
WebMock.enable!
|
|
315
|
-
end
|
|
316
|
-
|
|
317
|
-
def read_http_request(socket)
|
|
318
|
-
socket.gets # request line
|
|
319
|
-
loop do
|
|
320
|
-
line = socket.gets
|
|
321
|
-
break if line.nil? || line == "\r\n"
|
|
322
|
-
end
|
|
323
|
-
end
|
|
324
|
-
|
|
325
|
-
def write_http_response(socket, body)
|
|
326
|
-
payload = JSON.generate(body)
|
|
327
|
-
socket.write(
|
|
328
|
-
"HTTP/1.1 200 OK\r\n" \
|
|
329
|
-
"Content-Type: application/json\r\n" \
|
|
330
|
-
"Content-Length: #{payload.bytesize}\r\n" \
|
|
331
|
-
"Connection: keep-alive\r\n" \
|
|
332
|
-
"\r\n#{payload}"
|
|
333
|
-
)
|
|
334
|
-
socket.flush
|
|
335
|
-
end
|
|
336
173
|
end
|