class Gems::RedirectHandler

Handles HTTP redirects for API requests @api private

Constants

DEFAULT_MAX_REDIRECTS

Default maximum number of redirects to follow

Attributes

The connection for making requests @api private @return [Connection] the connection for making requests @example Get the connection

handler.connection

The request builder for creating requests @api private @return [RequestBuilder] the request builder for creating requests @example Get the request builder

handler.request_builder

Public Class Methods

Initialize a new RedirectHandler

@api private @param connection [Connection] the connection for making requests @param request_builder [RequestBuilder] the request builder for creating requests @param max_redirects [Integer] the maximum number of redirects to follow @return [RedirectHandler] a new instance @example Create a redirect handler

handler = Gems::RedirectHandler.new(connection: conn, request_builder: builder)
# File lib/gems/redirect_handler.rb, line 64
def initialize(connection: Connection.new, request_builder: RequestBuilder.new,
  max_redirects: DEFAULT_MAX_REDIRECTS)
  @connection = connection
  @request_builder = request_builder
  self.max_redirects = max_redirects
end

Public Instance Methods

Handle redirects for an HTTP response

A redirect to another scheme, host, or port is followed without the credentials of the request, as curl and browsers do, so that a redirect cannot send them to a host they were not meant for. The headers the caller asked for are dropped along with them, since a header of the caller’s own may carry a credential too. A later redirect back to the original host does not restore either.

A redirect that cannot be followed, such as 304 Not Modified or one whose Location header is missing, is not a valid URL, or is not an HTTP or HTTPS URL, is returned as it is, so that the caller raises the HTTPError of its status.

A 307 or 308 redirect is followed with the method of the request and the body it was built from, which is given as it was given to {RequestBuilder#build}, since a multipart body cannot be read back from the request. One to another scheme, host, or port is not followed at all when the request has a body, and is returned as a redirect that cannot be followed is: the credentials of a request are not all carried by the headers a cross-origin redirect drops, since {API::APIKeyEndpoints#update_api_key} sends an API key as a form field and the trusted publishing token exchange sends an ID token as a JSON field, and a body replayed to the host the redirect names would take them there.

@api private @param response [Net::HTTPResponse] the HTTP response to handle @param request [Net::HTTPRequest] the original HTTP request @param authenticator [Authenticator] the authenticator for requests @param body [Hash, Array, String, nil] the body the request was built from @param content_type [String, nil] the content type the request was built with, for a String body @param headers [Hash{String => String}] the headers the request was built with @param redirect_count [Integer] the current redirect count @return [Net::HTTPResponse] the final HTTP response after following redirects @raise [TooManyRedirects] if the maximum number of redirects is exceeded @example Handle a response

response = handler.handle(response: resp, request: req)
# File lib/gems/redirect_handler.rb, line 102
def handle(response:, request:, authenticator: Authenticator.new, body: nil, content_type: nil, headers: {},
  redirect_count: 0)
  return response unless response.is_a?(Net::HTTPRedirection)

  raise TooManyRedirects, "Too many redirects" if redirect_count >= max_redirects

  new_uri = build_new_uri(response, request)
  return response if new_uri.nil?

  follow(response:, request:, uri: new_uri, authenticator:, body:, content_type:, headers:, redirect_count:)
end