class Client
An in-process client for exercising protocol HTTP middleware.
Definitions
def initialize(delegate, scheme: "http", authority: "localhost")
Initialize the client.
Signature
-
parameter
delegate::Protocol::HTTP::Middleware The middleware to exercise.
-
parameter
schemeString The default request scheme.
-
parameter
authorityString The default request authority.
Implementation
def initialize(delegate, scheme: "http", authority: "localhost")
super(delegate)
@scheme = scheme
@authority = authority
@headers = {}
@cookies = {}
@closed = false
@exchange_closed = true
end
attr :scheme
Signature
-
attribute
String The default request scheme.
attr :headers
Signature
-
attribute
Hash(String, String) Headers added to every request.
attr :last_request
Signature
-
attribute
::Protocol::HTTP::Request | Nil The most recent request.
attr :last_response
Signature
-
attribute
::Protocol::HTTP::Response | Nil The most recent response.
def request(method, path, headers = nil, body = nil, **options)
Construct and perform a request.
Signature
-
parameter
methodString The request method.
-
parameter
pathString The request path.
-
parameter
headersHash | ::Protocol::HTTP::Headers | Nil The request headers.
-
parameter
bodyString | Array(String) | ::Protocol::HTTP::Body::Readable | Nil The request body.
-
parameter
optionsHash Additional options for
::Protocol::HTTP::Request.[].-
returns
::Protocol::HTTP::Response The application response.
Implementation
def request(method, path, headers = nil, body = nil, **options)
return self.call(
::Protocol::HTTP::Request[method, path, headers, body, **options]
)
end
def call(request)
Perform a prepared request against the application.
Signature
-
parameter
request::Protocol::HTTP::Request The prepared request.
-
returns
::Protocol::HTTP::Response The application response.
Implementation
def call(request)
if @closed
raise IOError, "Client is closed!"
end
self.close_exchange
self.prepare_request(request)
@last_request = request
@last_response = nil
@exchange_closed = false
begin
@last_response = super(request)
self.store_cookies(@last_response.headers["set-cookie"])
return @last_response
rescue => error
self.close_exchange(error)
raise
end
end
def follow_redirect!
Follow the location in the most recent redirect response.
Statuses 307 and 308 preserve the original method and body. Other redirects use GET, except that HEAD remains HEAD.
Signature
-
returns
::Protocol::HTTP::Response The redirected response.
Implementation
def follow_redirect!
response = @last_response
request = @last_request
unless response&.redirection?
raise RuntimeError, "The last response is not a redirect!"
end
location = response.headers["location"]
unless location
raise RuntimeError, "The redirect response has no location!"
end
base = "#{request.scheme}://#{request.authority}#{request.path}"
target = ::URI.join(base, location.to_s)
if response.preserve_method?
if @request_had_body && !@replay_body
raise IOError, "The request body cannot be replayed!"
end
method = request.method
body = @replay_body
elsif request.head?
method = ::Protocol::HTTP::Methods::HEAD
body = nil
else
method = ::Protocol::HTTP::Methods::GET
body = nil
end
return self.request(
method,
target.request_uri,
nil,
body,
scheme: target.scheme,
authority: target.authority,
)
end
def close(error = nil)
Close the current exchange and application.
Signature
-
parameter
errorException | Nil The error which caused the client to close.
Implementation
def close(error = nil)
return if @closed
@closed = true
begin
self.close_exchange(error)
ensure
super()
end
end