Public: Follow HTTP 301, 302, 303, and 307 redirects.
For HTTP 303, the original GET, POST, PUT, DELETE, or PATCH request gets converted into a GET. For HTTP 301, 302, and 307, the HTTP method remains unchanged.
This middleware currently only works with synchronous requests; i.e. it doesn't support parallelism.
HTTP methods for which 30x redirects can be followed
Keys in env hash which will get cleared between requests
Default value for max redirects followed
HTTP redirect status codes that this middleware implements
Regex that matches characters that need to be escaped in URLs, sans the “%” character which we assume already represents an escaped sequence.
Public: Initialize the middleware.
options - An options Hash (default: {}):
:limit - A Integer redirect limit (default: 3).
# File lib/octokit/middleware/follow_redirects.rb, line 53 def initialize(app, options = {}) super(app) @options = options @convert_to_get = Set.new [303] end
# File lib/octokit/middleware/follow_redirects.rb, line 60 def call(env) perform_with_redirection(env, follow_limit) end
# File lib/octokit/middleware/follow_redirects.rb, line 66 def convert_to_get?(response) ![:head, :options].include?(response.env[:method]) && @convert_to_get.include?(response.status) end
# File lib/octokit/middleware/follow_redirects.rb, line 109 def follow_limit @options.fetch(:limit, FOLLOW_LIMIT) end
# File lib/octokit/middleware/follow_redirects.rb, line 104 def follow_redirect?(env, response) ALLOWED_METHODS.include?(env[:method]) && REDIRECT_CODES.include?(response.status) end
# File lib/octokit/middleware/follow_redirects.rb, line 71 def perform_with_redirection(env, follows) request_body = env[:body] response = @app.call(env) response.on_complete do |response_env| if follow_redirect?(response_env, response) raise(RedirectLimitReached, response) if follows.zero? new_request_env = update_env(response_env, request_body, response) response = perform_with_redirection(new_request_env, follows - 1) end end response end
Internal: Escapes unsafe characters from a URL which might be a path component only or a fully-qualified URI so that it can be joined onto a URI:HTTP using the `+` operator. Doesn't escape “%” characters so to not risk double-escaping.
# File lib/octokit/middleware/follow_redirects.rb, line 124 def safe_escape(uri) uri.to_s.gsub(URI_UNSAFE) { |match| "%" + match.unpack("H2" * match.bytesize).join("%").upcase } end
# File lib/octokit/middleware/follow_redirects.rb, line 113 def same_host?(original_url, redirect_url) original_uri = Addressable::URI.parse(original_url) redirect_uri = Addressable::URI.parse(redirect_url) redirect_uri.host.nil? || original_uri.host == redirect_uri.host end
# File lib/octokit/middleware/follow_redirects.rb, line 85 def update_env(env, request_body, response) original_url = env[:url] env[:url] += safe_escape(response["location"]) unless same_host?(original_url, env[:url]) env[:request_headers].delete("Authorization") end if convert_to_get?(response) env[:method] = :get env[:body] = nil else env[:body] = request_body end ENV_TO_CLEAR.each { |key| env.delete(key) } env end