faraday-follow_redirects-0.4.0/0000755000004100000410000000000015067717411016527 5ustar www-datawww-datafaraday-follow_redirects-0.4.0/faraday-follow_redirects.gemspec0000644000004100000410000000363615067717411025057 0ustar www-datawww-data######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- # stub: faraday-follow_redirects 0.4.0 ruby lib Gem::Specification.new do |s| s.name = "faraday-follow_redirects".freeze s.version = "0.4.0".freeze s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.metadata = { "bug_tracker_uri" => "https://github.com/tisba/faraday-follow-redirects/issues", "changelog_uri" => "https://github.com/tisba/faraday-follow-redirects/blob/v0.4.0/CHANGELOG.md", "documentation_uri" => "http://www.rubydoc.info/gems/faraday-follow_redirects/0.4.0", "homepage_uri" => "https://github.com/tisba/faraday-follow-redirects", "rubygems_mfa_required" => "true", "source_code_uri" => "https://github.com/tisba/faraday-follow-redirects" } if s.respond_to? :metadata= s.require_paths = ["lib".freeze] s.authors = ["Sebastian Cohnen".freeze] s.date = "1980-01-02" s.description = "Faraday 1.x and 2.x compatible extraction of FaradayMiddleware::FollowRedirects.\n".freeze s.email = ["tisba@users.noreply.github.com".freeze] s.files = ["CHANGELOG.md".freeze, "LICENSE.md".freeze, "README.md".freeze, "lib/faraday/follow_redirects.rb".freeze, "lib/faraday/follow_redirects/middleware.rb".freeze, "lib/faraday/follow_redirects/redirect_limit_reached.rb".freeze, "lib/faraday/follow_redirects/version.rb".freeze] s.homepage = "https://github.com/tisba/faraday-follow-redirects".freeze s.licenses = ["MIT".freeze] s.required_ruby_version = Gem::Requirement.new([">= 2.6".freeze, "< 4".freeze]) s.rubygems_version = "3.6.9".freeze s.summary = "Faraday 1.x and 2.x compatible extraction of FaradayMiddleware::FollowRedirects".freeze s.specification_version = 4 s.add_runtime_dependency(%q.freeze, [">= 1".freeze, "< 3".freeze]) end faraday-follow_redirects-0.4.0/lib/0000755000004100000410000000000015067717411017275 5ustar www-datawww-datafaraday-follow_redirects-0.4.0/lib/faraday/0000755000004100000410000000000015067717411020704 5ustar www-datawww-datafaraday-follow_redirects-0.4.0/lib/faraday/follow_redirects.rb0000644000004100000410000000060615067717411024601 0ustar www-datawww-data# frozen_string_literal: true require 'faraday' require_relative 'follow_redirects/middleware' require_relative 'follow_redirects/redirect_limit_reached' require_relative 'follow_redirects/version' module Faraday # Main Faraday::FollowRedirects module. module FollowRedirects Faraday::Response.register_middleware(follow_redirects: Faraday::FollowRedirects::Middleware) end end faraday-follow_redirects-0.4.0/lib/faraday/follow_redirects/0000755000004100000410000000000015067717411024252 5ustar www-datawww-datafaraday-follow_redirects-0.4.0/lib/faraday/follow_redirects/redirect_limit_reached.rb0000644000004100000410000000063515067717411031255 0ustar www-datawww-data# frozen_string_literal: true require 'faraday' module Faraday module FollowRedirects # Exception thrown when the maximum amount of requests is # exceeded. class RedirectLimitReached < Faraday::ClientError attr_reader :response def initialize(response) super("too many redirects; last one to: #{response['location']}") @response = response end end end end faraday-follow_redirects-0.4.0/lib/faraday/follow_redirects/version.rb0000644000004100000410000000014715067717411026266 0ustar www-datawww-data# frozen_string_literal: true module Faraday module FollowRedirects VERSION = '0.4.0' end end faraday-follow_redirects-0.4.0/lib/faraday/follow_redirects/middleware.rb0000644000004100000410000001312515067717411026716 0ustar www-datawww-data# frozen_string_literal: true module Faraday module FollowRedirects # Public: Follow HTTP 301, 302, 303, 307, and 308 redirects. # # For HTTP 301, 302, and 303, the original GET, POST, PUT, DELETE, or PATCH # request gets converted into a GET. With `:standards_compliant => true`, # however, the HTTP method after 301/302 remains unchanged. This allows you # to opt into HTTP/1.1 compliance and act unlike the major web browsers. # # This middleware currently only works with synchronous requests; i.e. it # doesn't support parallelism. # # If you wish to persist cookies across redirects, you could use # the faraday-cookie_jar gem: # # Faraday.new(:url => url) do |faraday| # faraday.use FaradayMiddleware::FollowRedirects # faraday.use :cookie_jar # faraday.adapter Faraday.default_adapter # end class Middleware < Faraday::Middleware # HTTP methods for which 30x redirects can be followed ALLOWED_METHODS = Set.new %i[head options get post put patch delete] # HTTP redirect status codes that this middleware implements REDIRECT_CODES = Set.new [301, 302, 303, 307, 308] # Keys in env hash which will get cleared between requests ENV_TO_CLEAR = Set.new %i[status response response_headers] # Default value for max redirects followed FOLLOW_LIMIT = 3 # Regex that matches characters that need to be escaped in URLs, sans # the "%" character which we assume already represents an escaped sequence. URI_UNSAFE = %r{[^\-_.!~*'()a-zA-Z\d;/?:@&=+$,\[\]%]}.freeze AUTH_HEADER = 'Authorization' # Public: Initialize the middleware. # # options - An options Hash (default: {}): # :limit - A Numeric redirect limit (default: 3) # :standards_compliant - A Boolean indicating whether to respect # the HTTP spec when following 301/302 # (default: false) # :callback - A callable used on redirects # with the old and new envs # :cookies - An Array of Strings (e.g. # ['cookie1', 'cookie2']) to choose # cookies to be kept, or :all to keep # all cookies (default: []). # :clear_authorization_header - A Boolean indicating whether the request # Authorization header should be cleared on # redirects (default: true) def initialize(app, options = {}) super(app) @options = options @convert_to_get = Set.new [303] @convert_to_get << 301 << 302 unless standards_compliant? end def call(env) perform_with_redirection(env, follow_limit) end private def convert_to_get?(response) !%i[head options].include?(response.env[:method]) && @convert_to_get.include?(response.status) end 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.dup, request_body, response) callback&.call(response_env, new_request_env) response = perform_with_redirection(new_request_env, follows - 1) end end response end def update_env(env, request_body, response) redirect_from_url = env[:url].to_s redirect_to_url = safe_escape(response['location'] || '') env[:url] += redirect_to_url ENV_TO_CLEAR.each { |key| env.delete key } if convert_to_get?(response) env[:method] = :get env[:body] = nil else env[:body] = request_body end clear_authorization_header(env, redirect_from_url, redirect_to_url) env end def follow_redirect?(env, response) ALLOWED_METHODS.include?(env[:method]) && REDIRECT_CODES.include?(response.status) end def follow_limit @options.fetch(:limit, FOLLOW_LIMIT) end def standards_compliant? @options.fetch(:standards_compliant, false) end def callback @options[:callback] end # Internal: escapes unsafe characters from an URL which might be a path # component only or a fully qualified URI so that it can be joined onto an # URI:HTTP using the `+` operator. Doesn't escape "%" characters so to not # risk double-escaping. def safe_escape(uri) uri = uri.split('#')[0] # we want to remove the fragment if present uri.to_s.gsub(URI_UNSAFE) do |match| "%#{match.unpack('H2' * match.bytesize).join('%').upcase}" end end def clear_authorization_header(env, from_url, to_url) return env if redirect_to_same_host?(from_url, to_url) return env unless @options.fetch(:clear_authorization_header, true) env[:request_headers].delete(AUTH_HEADER) end def redirect_to_same_host?(from_url, to_url) return true if to_url.start_with?('/') from_uri = URI.parse(from_url) to_uri = URI.parse(to_url) [from_uri.scheme, from_uri.host, from_uri.port] == [to_uri.scheme, to_uri.host, to_uri.port] end end end end faraday-follow_redirects-0.4.0/LICENSE.md0000644000004100000410000000207315067717411020135 0ustar www-datawww-dataThe MIT License (MIT) Copyright (c) 2022 Sebastian Cohnen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. faraday-follow_redirects-0.4.0/README.md0000644000004100000410000000554315067717411020015 0ustar www-datawww-data# Faraday Follow Redirects [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/tisba/faraday-follow-redirects/ci.yaml)](https://github.com/tisba/faraday-follow-redirects/actions?query=branch%3Amain) [![Gem](https://img.shields.io/gem/v/faraday-follow_redirects.svg?style=flat-square)](https://rubygems.org/gems/faraday-follow_redirects) [![License](https://img.shields.io/github/license/tisba/faraday-follow-redirects.svg?style=flat-square)](LICENSE.md) [Faraday](https://github.com/lostisland/faraday) middleware to follow HTTP redirects transparently. > [!IMPORTANT] > This is a Faraday 2.x compatible extraction of the deprecated [`FaradayMiddleware::FollowRedirects` (v1.2.0)](https://github.com/lostisland/faraday_middleware/blob/v1.2.0/lib/faraday_middleware/response/follow_redirects.rb). This gem will also work with Faraday 1.x on a best-effort basis. **Faraday 1.x support is considered deprecated, please update to Faraday 2.x as soon as possible!** > > We only support non-EOL versions of Ruby. See [Ruby Maintenance Branches](https://www.ruby-lang.org/en/downloads/branches/) for the list of non-EOL Rubies. ## Installation Add this line to your application's Gemfile: ```ruby gem 'faraday-follow_redirects' ``` And then execute: ```shell bundle install ``` Or install it yourself as: ```shell gem install faraday-follow_redirects ``` ## Usage ```ruby require 'faraday/follow_redirects' Faraday.new(url: url) do |faraday| faraday.response :follow_redirects # use Faraday::FollowRedirects::Middleware faraday.adapter Faraday.default_adapter end ``` ## Upgrading from Faraday 1.x If you still use Faraday 1.x, and have uninstalled the `faraday_middleware` gem, all you have to change is: ```diff - conn.use FaradayMiddleware::FollowRedirects + conn.use Faraday::FollowRedirects::Middleware ``` ## Development After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/test` to run the tests. To install this gem onto your local machine, run `rake build`. To release a new version, make a commit with a message such as "Bumped to 0.0.2" and then run `rake release`. See how it works [here](https://bundler.io/guides/creating_gem.html#releasing-the-gem). The `.ruby-version` file defines the default version to be used for development. ### Appraisal for testing multiple versions of dependencies We use [appraisal](https://github.com/thoughtbot/appraisal) to test against both faraday 1.x and 2.x, and `./bin/test` will run tests against both. To run tests against just one you could: ```shell bundle exec appraisal faraday_1 rspec bundle exec appraisal faraday_2 rspec ``` ## Contributing Bug reports and pull requests are welcome on [GitHub](https://github.com/tisba/faraday-follow-redirects). ## License The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT). faraday-follow_redirects-0.4.0/CHANGELOG.md0000644000004100000410000000073215067717411020342 0ustar www-datawww-data# Changelog ## Unreleased * … ## 0.4.0 (2025-10-01) This release contains no user facing changes. * internal: adopt "Trusted Publishing" for new releases * internal: harden GitHub Action workflows * internal: move dev dependencies to Gemfile for easier updates ## 0.3.0 (2022-04-02) * lose version constraint on faraday to support 1.x and 2.x (#4) ## 0.2.0 (2022-03-07) * require faraday explicitly when loading this gem ## 0.1.0 (2022-02-24) * initial release