1212module Sus ::Fixtures
1313 module Async
1414 module HTTP
15+ # ServerContext provides a test fixture for HTTP server and client testing.
16+ # It sets up an HTTP server with a bound endpoint and provides a corresponding client
17+ # for making requests. This context handles the lifecycle of both server and client,
18+ # ensuring proper setup and teardown.
19+ #
20+ # The context automatically:
21+ # - Binds to an available port
22+ # - Starts an HTTP server with configurable middleware
23+ # - Creates a client configured to connect to the server
24+ # - Handles cleanup of resources after tests
1525 module ServerContext
1626 include ReactorContext
1727
28+ # The HTTP protocol version to use for the server.
29+ # @returns [Class] The protocol class (defaults to HTTP/1.1).
1830 def protocol
1931 ::Async ::HTTP ::Protocol ::HTTP1
2032 end
2133
34+ # The base URL for the HTTP server.
35+ # @returns [String] The URL string with host and port (defaults to localhost:0 for auto-assigned port).
2236 def url
2337 "http://localhost:0"
2438 end
2539
40+ # Get all bound URLs for the server endpoints.
41+ # @returns [Array(String)] Array of URLs the server is bound to, sorted alphabetically.
2642 def bound_urls
2743 urls = [ ]
2844
@@ -44,61 +60,94 @@ def bound_urls
4460 return urls
4561 end
4662
63+ # Get the first bound URL for the server.
64+ # @returns [String] The first bound URL, typically used for single-endpoint testing.
4765 def bound_url
4866 bound_urls . first
4967 end
5068
69+ # Options for configuring the HTTP endpoint.
70+ # @returns [Hash] Hash of endpoint options including port reuse and protocol settings.
5171 def endpoint_options
5272 { reuse_port : true , protocol : protocol }
5373 end
5474
75+ # The HTTP endpoint configuration.
76+ # @returns [Async::HTTP::Endpoint] Parsed endpoint with configured options.
5577 def endpoint
5678 ::Async ::HTTP ::Endpoint . parse ( url , **endpoint_options )
5779 end
5880
81+ # Number of retries for client requests.
82+ # @returns [Integer] Number of retry attempts (defaults to 1).
5983 def retries
6084 1
6185 end
6286
87+ # The HTTP application/middleware to serve.
88+ # @returns [Object] The application object that handles HTTP requests (defaults to HelloWorld middleware).
6389 def app
6490 ::Protocol ::HTTP ::Middleware ::HelloWorld
6591 end
6692
93+ # The middleware stack for the HTTP server.
94+ # @returns [Object] The middleware configuration (defaults to the app).
6795 def middleware
6896 app
6997 end
7098
99+ # Create the server endpoint from a bound endpoint.
100+ # @parameter bound_endpoint [Async::HTTP::Endpoint] The bound endpoint.
101+ # @returns [Async::HTTP::Endpoint] The server endpoint configuration.
71102 def make_server_endpoint ( bound_endpoint )
72103 bound_endpoint
73104 end
74105
106+ # Create an HTTP server instance.
107+ # @parameter endpoint [Async::HTTP::Endpoint] The endpoint to bind the server to.
108+ # @returns [Async::HTTP::Server] The configured HTTP server.
75109 def make_server ( endpoint )
76110 ::Async ::HTTP ::Server . new ( middleware , endpoint )
77111 end
78112
113+ # The HTTP server instance.
114+ # @returns [Async::HTTP::Server] The running HTTP server.
79115 def server
80116 @server
81117 end
82118
119+ # The HTTP client instance.
120+ # @returns [Async::HTTP::Client] The HTTP client configured to connect to the server.
83121 def client
84122 @client
85123 end
86124
125+ # The client endpoint configuration.
126+ # @returns [Async::HTTP::Endpoint] The endpoint the client uses to connect to the server.
87127 def client_endpoint
88128 @client_endpoint
89129 end
90130
131+ # Create a client endpoint from a bound endpoint.
132+ # @parameter bound_endpoint [Async::HTTP::Endpoint] The bound server endpoint.
133+ # @returns [Async::HTTP::Endpoint] The client endpoint with local address and timeout.
91134 def make_client_endpoint ( bound_endpoint )
92135 # Pass through the timeout:
93136 bound_endpoint . local_address_endpoint ( timeout : endpoint . timeout )
94137 end
95138
139+ # Create an HTTP client instance.
140+ # @parameter endpoint [Async::HTTP::Endpoint] The endpoint to connect to.
141+ # @parameter options [Hash] Additional client options.
142+ # @returns [Async::HTTP::Client] The configured HTTP client.
96143 def make_client ( endpoint , **options )
97144 options [ :retries ] = retries unless options . key? ( :retries )
98145
99146 ::Async ::HTTP ::Client . new ( endpoint , **options )
100147 end
101148
149+ # Set up the server and client before running tests.
150+ # This method binds the endpoint, starts the server, and creates a client.
102151 def before
103152 super
104153
@@ -128,6 +177,9 @@ def before
128177 @client = make_client ( @client_endpoint )
129178 end
130179
180+ # Clean up resources after running tests.
181+ # This method closes the client, stops the server, and closes the bound endpoint.
182+ # @parameter error [Exception | Nil] Any error that occurred during the test.
131183 def after ( error = nil )
132184 # We add a timeout here, to avoid hanging in `@client.close`:
133185 ::Async ::Task . current . with_timeout ( 1 ) do
0 commit comments